Skip to Content
How-To GuidesGoEnabling OpenTelemetry for a Go Agent

Enabling OpenTelemetry for a Go Agent

The golem-otlp-exporter is a built-in plugin that exports agent telemetry (traces, logs, metrics) to any OTLP-compatible collector via OTLP/HTTP. It runs on the platform side (as an oplog processor), so enabling it is a manifest concern — the configuration is the same regardless of the agent’s language. No plugin installation is needed; just enable it in golem.yaml.

Step 1 — Enable the Plugin in golem.yaml

Add the plugin to the component (or agent) that should emit telemetry:

components: my-app:service: plugins: - name: golem-otlp-exporter version: "1.5.0" parameters: endpoint: "http://localhost:4318" signals: "traces,logs,metrics"

Plugin Parameters

ParameterRequiredDescription
endpointYesOTLP collector base URL (e.g., http://localhost:4318)
signalsNoComma-separated: traces, logs, metrics. Default: traces
headersNoComma-separated key=value HTTP headers (e.g., x-api-key=secret)
service-name-modeNoagent-id (default) or agent-type

Step 2 — Deploy

golem deploy --yes

After deployment, newly created agents from this component automatically send telemetry to the configured collector.

What Gets Exported

Traces

Spans are created automatically for:

  • Agent invocations
  • RPC calls to other agents
  • Outgoing HTTP requests

Trace and span IDs propagate from inbound HTTP requests (via code-first routes) and are included in outgoing HTTP request headers automatically.

Custom spans

The github.com/golemcloud/golem/sdks/go/golem/invocation package starts your own spans and reads the invocation context:

span := invocation.StartSpan("charge") defer span.Finish() span.SetAttribute("order", orderID) ctx := invocation.CurrentContext() slog.Info("charging", "trace", ctx.TraceID(), "span", ctx.SpanID())
  • A custom span is a child of the current context; RPC and HTTP calls made while it is open inherit it.
  • ctx.Attribute(key, inherited), Attributes, AttributeChain, AttributeChains and Parent read the span stack; TraceContextHeaders() returns the W3C headers as an http.Header.
  • invocation.AllowForwardingTraceContextHeaders(false) stops adding trace headers to outgoing HTTP requests and returns the previous setting.
  • A span that is never finished ends when it is garbage collected; natively (in go test) the context is empty and spans record nothing.

Logs

When logs is included in signals, all log output is forwarded to the OTLP collector. Use the standard library log/slog — the runtime routes it through the host logging channel and, in turn, to the collector. See the golem-logging-go skill for full logging guidance.

import "log/slog" slog.Info("hello from Go") slog.Debug("this is a debug log entry", "step", 1)

Metrics

When metrics is included in signals, the following metrics are exported:

MetricTypeDescription
golem_invocation_countCounterNumber of agent method invocations
golem_invocation_duration_nsCounterInvocation duration
golem_invocation_fuel_consumedCounterFuel consumed by invocations
golem_invocation_pending_countCounterNumber of pending invocations
golem_host_call_countCounterNumber of internal host calls
golem_log_countCounterNumber of log entries emitted
golem_memory_initial_bytesGaugeInitially allocated memory
golem_memory_total_bytesGaugeTotal allocated memory
golem_memory_growth_bytesCounterMemory growth since start
golem_component_size_bytesGaugeComponent size in bytes
golem_error_countCounterNumber of recorded errors
golem_interruption_countCounterNumber of interrupt requests
golem_exit_countCounterNumber of process exit signals
golem_restart_countCounterNumber of times a fresh state was created
golem_resources_createdCounterNumber of internal resources created
golem_resources_droppedCounterNumber of internal resources dropped
golem_resources_activeGaugeNumber of active internal resources
golem_update_success_countCounterNumber of successful updates
golem_update_failure_countCounterNumber of failed updates
golem_transaction_committedCounterNumber of committed database transactions
golem_transaction_rolled_backCounterNumber of rolled back database transactions
golem_snapshot_size_bytesCounterSnapshot size in bytes
golem_oplog_processor_lagGaugeOplog processor delivery lag

Each metric includes service.name, golem.agent.id, golem.component.id, and golem.component.version attributes.

Export Semantics

  • Durable Start, End, and Cancelled metadata drives span lifecycle. Long-lived spans retain their origin trace across invocations; failed or retrying attempts do not prematurely close the logical span. Logs use their recorded trace context.
  • Stream summaries use bounded event/outcome metric labels and aggregate item counts; they do not emit a span per item. Active resource and memory values are gauges, and metric labels avoid resource IDs and payload values.
  • In agent-type service-name mode, service.name excludes constructor parameters and phantom instance IDs; golem.agent.id remains the full identity.
  • Collector export is best effort. Accepted source state advances when a send fails, and traces, logs, and metrics are still attempted independently. Exactly-once plugin batch delivery is not exactly-once collector delivery.
  • Fork/revert cannot retract telemetry already accepted by a collector. Source deletion does not provide a terminal signal, so no successful close is invented. Switching plugin instances can lose open-span state.

Local Observability Stack

The Golem repository includes a ready-made Docker Compose setup at docker-examples/otlp-collector/:

docker compose -f docker-examples/otlp-collector/docker-compose.yml up -d

This starts:

Configure the plugin with endpoint: "http://localhost:4318" to use this stack.

Per-Environment Configuration

Use presets to vary the endpoint across environments:

components: my-app:service: plugins: - name: golem-otlp-exporter version: "1.5.0" parameters: endpoint: "http://localhost:4318" signals: "traces,logs,metrics" presets: production: pluginsMergeMode: replace plugins: - name: golem-otlp-exporter version: "1.5.0" parameters: endpoint: "https://otel.prod.example.com:4318" headers: "x-api-key={{ OTLP_API_KEY }}" signals: "traces,logs,metrics"

Parameter values support Jinja-style {{ VAR_NAME }} substitution resolved against the host machine’s environment variables at deploy time.

Key Points

  • Built-in — no golem plugin register needed, just add to golem.yaml.
  • Deploy required — run golem deploy after adding the plugin configuration.
  • Trace context propagates automatically through HTTP routes and RPC calls.
  • Plugin can be activated/deactivated per agent with golem agent activate-plugin / golem agent deactivate-plugin.
GuideDescription
golem-logging-goStructured logging from Go agent code (forwarded when logs is enabled)
golem-manage-pluginsGeneral plugin installation model (manifest sections, CLI, priority, per-environment config)