Skip to content

Traces

Chinmina creates distributed trace spans for HTTP requests, external API calls, and background operations. Spans capture timing information, status codes, and contextual attributes.

HTTP server spans represent incoming requests to Chinmina endpoints.

Span name: Route pattern (e.g., /token, /git-credentials, /healthcheck, /organization/token/{profile})

Span kind: Server

Parent span: Extracted from incoming request headers via W3C Trace Context propagation, if present.

Created by: otelhttp.NewHandler() wrapper around each HTTP route handler.

Attributes are added automatically by the otelhttp package following OpenTelemetry HTTP semantic conventions. Common attributes include:

AttributeTypeDescription
http.request.methodstringHTTP method (GET, POST)
http.routestringMatched route pattern (e.g., /token)
url.pathstringRequest path
url.schemestringProtocol (http or https)
http.response.status_codeintHTTP response status code
network.protocol.versionstringHTTP version (e.g., “1.1”)
user_agent.originalstringUser-Agent header value
server.addressstringServer hostname
server.portintServer port
client.addressstringClient IP address

Status:

  • Unset for 1xx, 2xx, 3xx, and 4xx responses
  • Error for 5xx responses

The JWT validation middleware extracts Buildkite identity fields from the authenticated token and writes them to the current span. These attributes appear on every authenticated request span.

AttributeTypeDescription
buildkite.organization_slugstringBuildkite organization
buildkite.pipeline_slugstringPipeline that initiated the request
buildkite.job_idstringJob ID
buildkite.build_numberintBuild number
buildkite.build_branchstringBranch being built

All authenticated endpoints create server spans:

  • POST /token
  • POST /git-credentials
  • POST /organization/token/{profile}
  • POST /organization/git-credentials/{profile}

The GET /healthcheck endpoint is unauthenticated and excluded from telemetry instrumentation.

HTTP client spans represent outgoing requests to external APIs.

Span name: Varies by request (typically HTTP method and URL path)

Span kind: Client

Parent span: Server span from incoming request, or profile refresh span for background operations.

Created by: otelhttp.NewTransport() wrapper around the HTTP client transport.

Attributes are added by the otelhttp package. Common attributes include:

AttributeTypeDescription
http.request.methodstringHTTP method (GET, POST, etc.)
url.fullstringFull request URL
http.response.status_codeintHTTP response status code
url.pathstringRequest path
server.addressstringTarget hostname
server.portintTarget port

When OBSERVE_CONNECTION_TRACE_ENABLED=true, additional timing attributes are added to client spans:

  • DNS lookup timing
  • Connection establishment timing
  • TLS handshake timing
  • Time to first byte

These attributes are added to the parent HTTP client span rather than creating separate child spans.

Client spans are created for requests to:

  • GitHub API (api.github.com): Token generation requests
  • Buildkite API (api.buildkite.com): Pipeline repository lookups

The profile refresh span represents periodic background operations that fetch and update organization profile configurations.

Span name: refresh_organization_profile

Tracer name: github.com/chinmina/chinmina-bridge/internal/profile

Span kind: Internal

Parent span: None (root span for background operation)

Lifecycle: Created at the start of each periodic refresh operation, ended when the operation completes.

AttributeTypeDescription
profile.digest_currentstringSHA-256 digest of previous profile configuration (hex-encoded)
profile.digest_updatedstringSHA-256 digest of new profile configuration (hex-encoded)
profile.digest_changedboolWhether configuration content changed

Attributes are added during the profile update process, after the new profile is computed but before it is stored.

ConditionStatus CodeStatus Message
SuccessOk"profile refreshed"
Panic during refreshError"profile refresh panicked"
Fetch failureError"profile refresh failed"

Error recording: Errors are recorded on the span via span.RecordError() before setting the error status.

Profile refresh operations create child HTTP client spans for requests to the GitHub API to fetch profile configurations.

Each cache operation (get, set, invalidate) writes its result and timing directly to the active span. These attributes appear alongside the HTTP server span attributes on the parent request.

AttributeTypeDescription
cache.typestringCache backend ("memory" or "distributed")
cache.{operation}.statusstringOutcome of the operation
cache.{operation}.durationfloat64Duration in seconds

Where {operation} is one of get, set, or invalidate.

When cache encryption is active, encrypt and decrypt operations write timing and outcome attributes to the active span.

AttributeTypeDescription
cache.{operation}.durationfloat64Duration in seconds
cache.{operation}.outcomestring"success" or "error"

Where {operation} is encrypt or decrypt.

Typical trace hierarchy for a token request:

Server span: POST /token
├── Client span: GET api.buildkite.com/v2/organizations/.../pipelines/...
└── Client span: POST api.github.com/app/installations/.../access_tokens

Profile refresh creates a root span with child API call spans:

Internal span: refresh_organization_profile
└── Client span: GET api.github.com/...

With full tracing enabled, each token request generates:

  • 1 server span (incoming request)
  • 1–2 client spans (Buildkite API + GitHub API)
  • Connection timing attributes on client spans (if OBSERVE_CONNECTION_TRACE_ENABLED=true)

Organization endpoint requests generate fewer spans (1 server + 1 client) because no Buildkite API call is needed.

Background profile refresh operations generate additional traces periodically based on the configured refresh interval.

For span configuration details, see: