dexcost
Go

Configuration

All Config fields, environment variables, development mode, attribution context helpers, and the dexcost CLI.

Configuration options

Pass a dexcost.Config struct to dexcost.Init(). Init is safe to call multiple times — only the first call takes effect.

FieldTypeDefaultDescription
APIKeystring"" — falls back to DEXCOST_API_KEYAPI key for cloud push. Must start with dx_live_ (production) or dx_test_ (sandbox). Omit or set Storage: "local" for local-only mode.
Storagestring"" (auto-detect)Force "local" to disable cloud push regardless of API key.
BatchSizeint100Maximum number of events per sync batch sent to the Control Layer.
FlushIntervalSecondsfloat645.0Seconds between background sync pushes.
BufferDirstring~/.dexcostDirectory for the local SQLite buffer (dexcost.db). Useful when the default path is on a read-only filesystem.
RedactFields[]stringnil (no redaction)Field names removed from event Details before cloud push (e.g. []string{"prompt", "completion"}).
HashCustomerIDboolfalseSHA-256 hash customer_id before cloud push so raw identifiers never leave the process.
Environmentstring"" — falls back to DEXCOST_ENVSet to "development" to enable dev console output and disable cloud push.
TrackHTTPboolfalseWrap http.DefaultTransport on Init to record external HTTP costs process-wide.
ServiceCatalogURLstring""URL to fetch an updated service catalog JSON at startup, extending or replacing the bundled 163-service catalog.
EnableRetryHeuristicsboolfalseEnable the in-memory RetryHeuristicEngine for automatic retry detection on RecordLLMCall.
RetryHeuristicWindowfloat6430Sliding-window size in seconds used by the heuristic engine.
RetryHeuristicThresholdfloat640.8Confidence threshold in (0, 1] above which an event is automatically flagged as a retry.
NetworkEventThresholdBytesint102400Combined request+response bytes above which an un-cataloged call emits a network event (100 KiB). 0 disables.
NetworkEventOnErrorbooltrueEmit a network event for un-cataloged calls that return a status >= 400.
NetworkEventLatencyMsint0Emit a network event for calls slower than this many milliseconds. 0 disables.
ComputeBillingOverridesmap[string]stringnilCompute billing-model overrides. The pricing engine recognizes {"cloud_run": "instance"}.
K8sNodeAwareboolfalseReserved for Kubernetes node-aware compute accounting. Accepted but not yet active.

Init returns an error if the API key format is invalid, the buffer directory cannot be created, or the pricing engine fails to load.

err := dexcost.Init(dexcost.Config{
    APIKey:               "dx_live_...",
    BatchSize:            200,
    FlushIntervalSeconds: 10.0,
    RedactFields:         []string{"prompt", "completion"},
    HashCustomerID:       true,
    TrackHTTP:            true,
    EnableRetryHeuristics: true,
})
if err != nil {
    log.Fatalf("dexcost init: %v", err)
}
defer dexcost.Close()

Environment variables

Environment variables are read inside Config.init() when Init is called. Explicit field values in Config take precedence over environment variables.

VariableDescription
DEXCOST_API_KEYAPI key. Read when Config.APIKey is empty and Config.Storage is not "local".
DEXCOST_ENVSet to development to enable dev console mode without setting Config.Environment.

Development mode

Pass Environment: "development" in Config (or set DEXCOST_ENV=development) to enable dev mode:

dexcost.Init(dexcost.Config{Environment: "development"})

In dev mode:

  • Every llm_call, external_cost, compute_cost, and retry_marker event is printed to stderr as it is recorded, with provider, model, token counts, and cost.
  • Task completion is printed with aggregated cost totals and retry counts.
  • Cloud push is disabled — the SyncWorker (EventPusher) is not started.
  • An API key is not required.

Dev mode is controlled by the module-level devMode variable, managed by dexcost.EnableDevMode() and reset by dexcost.Close(). dexcost.IsDevMode() returns the current state.


Attribution & context

SetContext and SetContextWithMetadata

dexcost.SetContext attaches customer_id and project_id to a context.Context without starting an explicit task. HTTP adapters and wrapper clients use this attribution when no explicit task is present:

ctx = dexcost.SetContext(ctx, "acme-corp", "chatbot-v2")
resp, err := trackedClient.CreateChatCompletion(ctx, req)

dexcost.SetContextWithMetadata additionally sets an agent name and arbitrary metadata:

ctx = dexcost.SetContextWithMetadata(ctx,
    "acme-corp",      // customerID
    "chatbot-v2",     // projectID
    "support_agent",  // agent name
    map[string]interface{}{
        "tier":   "enterprise",
        "region": "us-east-1",
    },
)

Both functions return a derived context.Context and follow standard Go context propagation — pass the returned context to all downstream calls.

dexcost.GetContext(ctx) returns the *core.ContextData stored in the context, or nil. dexcost.ClearContext(ctx) returns a context with attribution removed.

WithCustomer and WithProject

dexcost.WithCustomer and dexcost.WithProject are TaskOption values that set attribution on a specific task at StartTask time:

ctx, task := dexcost.StartTask(ctx, "resolve_ticket",
    dexcost.WithCustomer("acme-corp"),
    dexcost.WithProject("support"),
)

Additional task options: dexcost.WithMetadata(map[string]interface{}{...}), dexcost.WithExperiment("exp-id"), dexcost.WithVariant("variant-a").


CLI

The dexcost CLI works offline against the local SQLite buffer. No API key is required.

Install via go install:

go install github.com/DexwoxBusiness/dexcost-sdk/go/cmd/dexcost@latest

dexcost status

Show the state of the local buffer:

dexcost status
dexcost status --db /path/to/dexcost.db

Output includes: DB location, event count, task count, last task timestamp, pending and synced event counts, and the current pricing data version.

dexcost rates

Manage the per-service cost rate registry. Rates are stored persistently at ~/.dexcost/rates.yaml:

# List all registered rates
dexcost rates --list

# Import rates from a YAML file into the persistent store
dexcost rates --import rates.yaml

# Export the persistent store to a YAML file
dexcost rates --export rates.yaml

# Override the default store location
dexcost rates --store /path/to/rates.yaml --list

YAML format expected by --import (canonical format shared with the Python SDK):

rates:
  maps.googleapis.com:
    per: request
    cost_usd: "0.005"
  ocr-api.com:
    per: page
    cost_usd: "0.01"

dexcost scan

Static-analysis scan of your codebase to find cost points that are not yet tracked. No API key or network connection is required:

dexcost scan ./cmd
dexcost scan ./cmd --generate-stubs

scan walks the target directory (default .), identifies LLM call sites (reported as auto-instrumented), and flags external API calls that likely incur cost but have no RecordCost() call nearby (reported as needing manual recording).

--generate-stubs prints ready-to-paste RecordCost() snippets for each untracked cost point found.

On this page