nozle.WrapHTTPClient returns a copy of an *http.Client that records the token usage of every successful LLM response it carries. Pass it to any provider SDK that accepts an HTTP client, or use it for your own requests. Requests and responses pass through unchanged, and prompts and completions are never sent to Nozle.
WrapHTTPClient and RecordUsage require v0.12.0. The provider-specific wrappers are available in earlier versions.
Usage is recognised by the shape of the response, not by provider name: an OpenAI-style usage (OpenAI chat completions, the Responses API and any OpenAI-compatible API), an Anthropic usage, or Gemini usageMetadata, for JSON responses and streams.
Capture records usage events; they bill only when a metered Feature has the same event code. See Set up AI token billing for the Feature, charge and cost model to create first.
Capture any client
X-Nozle-Customer-Id request header (removed before the request is sent), WithCustomer on the request context, CaptureOptions.CustomerIDFunc, then CaptureOptions.CustomerID. A request without a customer passes through and nothing is recorded. X-Nozle-Feature (also removed) or Feature sets the feature property; CostMeterCode adds categorized Cost Events. Chat completion streams are sent with stream_options.include_usage; set SkipStreamUsage for a server that rejects the field. OnError also receives, once per event code, a *nozle.SetupError with Code feature_not_found when no Feature has the event code.
client.RecordUsage(ctx, nozle.ProviderCapture{CustomerID: ..., Model: ..., RequestID: ...}, nozle.Usage{InputTokens: ..., OutputTokens: ...}) records usage your code read itself.
Provider-specific wrappers
WrapOpenAIHTTPClient and WrapAnthropicHTTPClient observe only /chat/completions and /messages. They are kept for existing integrations.
OpenAI
github.com/openai/openai-go/v3 as openai and its /option package as openaiopt. The provider SDK reads OPENAI_API_KEY from the environment. NewStreaming is also captured automatically: the wrapper requests stream_options.include_usage and records the final usage-bearing chunk after the stream is consumed. Closing a stream before final usage arrives cannot produce a usage event.
Anthropic
github.com/anthropics/anthropic-sdk-go as anthropic and its /option package as anthropicopt. The provider SDK reads ANTHROPIC_API_KEY from the environment. NewStreaming is captured after its message_start input usage and message_delta output usage have been read.
Wrapper options and delivery
The wrapper copies the supplied
*http.Client; it does not mutate the original. It captures only request paths ending in /chat/completions (OpenAI) and /messages (Anthropic); other routes, such as /v1/responses, pass through without an event. Usage delivery runs in a goroutine after the provider response or stream completes, without delaying the provider result. Use OnError to log or queue failures. The wrapper does not automatically retry telemetry.
The callbacks fire only when there was usage to deliver. A provider non-2xx response, a body that is not valid JSON, a response without usage, or a stream closed before its final usage produces no event and calls neither OnError nor OnResult. Because delivery is in the background, a process that exits right after the provider call loses the event; wait for OnResult before exiting a short-lived program. A DeliveryTimeout that is too short fails delivery: with 1 ms, both callbacks receive a context deadline error.
Manual capture
Use the direct capture methods when your provider client cannot accept an*http.Client, or when your application needs to choose a transaction ID or coordinate durable delivery. Pass usage from the completed provider response; these methods return Nozle telemetry errors to your code.
OpenAI usage
Mapprompt_tokens to PromptTokens, completion_tokens to CompletionTokens, and the cached-input and reasoning details when available.
PromptTokens and CompletionTokens remain the total Feature Event counts; detailed Cost Events split those totals by category.
Anthropic usage
Mapinput_tokens to InputTokens, cache_read_input_tokens to CachedInputTokens, cache_creation_input_tokens to CacheWriteTokens, and output_tokens to OutputTokens. For manual stream capture, collect input usage from message_start and output usage from message_delta, then capture after the stream completes.
input_tokens includes regular input, cached input, and cache-write input. Negative token counts are clamped to zero.
Tracked properties
Automatic and manual capture create one Feature Event through Engine with these properties:Latency on ProviderCapture; otherwise latency_ms is zero. FeatureCode defaults to llm_tokens. Supplying SubscriptionID avoids a lookup when a customer has more than one active subscription.
When CostMeterCode is set, each non-zero token category creates a linked Engine Cost Event with properties { tokens, provider, model, type }:
- OpenAI:
input,cached_input,output, andreasoning. - Anthropic:
input,cached_input,cache_write, andoutput.
llm-<format>-<response id> when the response has an id, so the same response is never recorded twice; otherwise a UUIDv7 is generated. In manual capture, you can supply TransactionID; category Cost Event IDs derive from that same ID, so reuse it when retrying the same capture.
Delivery and errors
Go sends the Feature Event first, then attempts each non-zero Cost Event category. If one Cost Event fails, it attempts the remaining categories. Automatic capture reports delivery errors throughOnError and OnResult (see the cases above where neither fires); manual capture returns them. If the Feature Event fails, Cost Events are not sent. Neither path retries automatically.
For strict or durable telemetry delivery, use manual capture through your queue with a stable transaction ID. The automatic wrapper preserves successful provider responses when Nozle tracking fails.
The Go wrappers, like the Node and Python wrappers, capture completed provider calls and streams automatically. Go connects at the provider HTTP client because Go does not support replacing another package’s methods at runtime. The Feature Event fields and Cost Event categories match the published SDKs.