Go SDK
Use telemetry-go for direct synchronous event and query calls from a Go service. The published client creates an HTTP request for each method call. It does not expose context, a custom http.Client, an SDK timeout, automatic retries, batching, or a flush queue.
Install and initialize
go get github.com/telemetry-sh/telemetry-go
import (
"os"
telemetry "github.com/telemetry-sh/telemetry-go"
)
telemetryClient := telemetry.NewTelemetry()
telemetryClient.Init(os.Getenv("TELEMETRY_API_KEY"))
Initialize one client during application startup. Use a write-scoped key for ingestion and a read-scoped key for query-only automation.
Send a structured event
event := map[string]interface{}{
"event_id": eventID,
"route_template": "/api/projects/:id",
"method": "POST",
"status_code": 201,
"status": "success",
"latency_ms": float64(time.Since(startedAt).Microseconds()) / 1000,
"request_id": requestID,
"release": os.Getenv("APP_RELEASE"),
}
response, err := telemetryClient.Log("api_request_completed", event)
if err != nil {
log.Printf("telemetry delivery failed event_id=%s error_type=transport_error", eventID)
}
_ = response
Do not send raw request paths containing identifiers, headers, cookies, request bodies, credentials, or private customer content. Use a normalized route pattern and controlled error category.
The Go SDK accepts one map[string]interface{} per Log call. Use the HTTP Log API directly if an application-owned worker needs bulk ingestion.
Run a query
query := `
SELECT
route_template,
COUNT(*) AS requests
FROM api_request_completed
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
GROUP BY route_template
ORDER BY requests DESC
`
result, err := telemetryClient.Query(query)
if err != nil {
return fmt.Errorf("query telemetry: %w", err)
}
rows, _ := result["data"].([]interface{})
fmt.Printf("rows=%d\n", len(rows))
The response uses generic maps and slices. Check types, missing fields, API status, and empty results before using a value in automation. Use the asynchronous Query API for large JSON or Parquet exports.
Production transport boundary
The current SDK constructs http.Client{} without a timeout. A stalled network request can therefore outlive the latency budget of an HTTP handler or worker. When a bounded timeout, context cancellation, connection-pool configuration, bulk payload, or explicit status handling is required, wrap the Telemetry HTTP contract in the service's existing http.Client.
Keep the same event schema and authorization rules:
client := &http.Client{Timeout: 2 * time.Second}
Use that client to POST https://api.telemetry.sh/log with a JSON body containing table and data. Check the HTTP status before decoding the response.
Retry and critical-path policy
Retry only transient connection failures, 429, 502, 503, and 504. Apply exponential backoff with jitter, cap elapsed time, and reuse the same event_id. Do not retry an unchanged schema or request error.
For normal application analytics, do not replace a completed customer response because telemetry failed. For billing or approved audit events that require durability, persist an outbox record in the system that owns the business transaction and deliver it from a worker.
See event delivery and idempotency and batching and backpressure.
Verify the integration
Send synthetic success, failure, retry, and timeout events, then run:
SELECT timestamp_utc, event_id, route_template, status, latency_ms, error_type
FROM api_request_completed
ORDER BY timestamp_utc DESC
LIMIT 20;
Confirm the table name, field types, units, and absence of sensitive content. Test process shutdown and a stalled Telemetry request before attaching instrumentation to a high-traffic handler.
Troubleshooting
- Initialization error: confirm the server-side key is non-empty before the first method call.
- Request hangs: use the HTTP API through a client with a timeout and request context.
- Non-success response appears as data: inspect the returned status field; the current SDK decodes the JSON body without enforcing HTTP success.
- Schema rejection: keep a field's type stable and remove null or unsupported shapes.
- Duplicate rows after retry: preserve
event_idand audit with the duplicate event recipe.
Continue with Go HTTP server structured logging, the Log API, and rate limits and API errors.