OpenTelemetry Go implementation providing APIs for distributed tracing, metrics, and logging to instrument applications and send telemetry data to observability platforms
Semantic conventions define standard attribute names and values for common operations and resources, ensuring consistency across observability data.
OpenTelemetry provides semantic conventions for:
import semconv "go.opentelemetry.io/otel/semconv/v1.37.0"Note: Use the latest semantic conventions version (v1.37.0 as of this writing). The version corresponds to the OpenTelemetry semantic conventions specification version.
go get go.opentelemetry.io/otel/semconv/v1.37.0Standard attributes for describing resources.
// Service name
semconv.ServiceName(name string) attribute.KeyValue
// Service version
semconv.ServiceVersion(version string) attribute.KeyValue
// Service instance ID
semconv.ServiceInstanceID(id string) attribute.KeyValue
// Service namespace
semconv.ServiceNamespace(namespace string) attribute.KeyValueExample:
import (
"context"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
)
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceName("my-service"),
semconv.ServiceVersion("1.0.0"),
semconv.ServiceInstanceID("instance-1"),
semconv.ServiceNamespace("production"),
),
)// Deployment environment
semconv.DeploymentEnvironment(env string) attribute.KeyValue
// Deployment environment name (alias)
semconv.DeploymentEnvironmentName(name string) attribute.KeyValueExample:
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.DeploymentEnvironment("production"),
),
)// Host name
semconv.HostName(name string) attribute.KeyValue
// Host ID
semconv.HostID(id string) attribute.KeyValue
// Host type
semconv.HostType(hostType string) attribute.KeyValue
// Host architecture
semconv.HostArch(arch string) attribute.KeyValue// Process ID
semconv.ProcessPID(pid int) attribute.KeyValue
// Process executable name
semconv.ProcessExecutableName(name string) attribute.KeyValue
// Process executable path
semconv.ProcessExecutablePath(path string) attribute.KeyValue
// Process command
semconv.ProcessCommand(command string) attribute.KeyValue
// Process owner
semconv.ProcessOwner(owner string) attribute.KeyValue// Container ID
semconv.ContainerID(id string) attribute.KeyValue
// Container name
semconv.ContainerName(name string) attribute.KeyValue
// Container image name
semconv.ContainerImageName(name string) attribute.KeyValue
// Container image tag
semconv.ContainerImageTag(tag string) attribute.KeyValue// Pod name
semconv.K8SPodName(name string) attribute.KeyValue
// Namespace name
semconv.K8SNamespaceName(namespace string) attribute.KeyValue
// Node name
semconv.K8SNodeName(node string) attribute.KeyValue
// Deployment name
semconv.K8SDeploymentName(deployment string) attribute.KeyValue
// Cluster name
semconv.K8SClusterName(cluster string) attribute.KeyValueExample:
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceName("my-service"),
semconv.K8SPodName("my-service-7d5f6b8c9d-abcde"),
semconv.K8SNamespaceName("production"),
semconv.K8SDeploymentName("my-service"),
semconv.K8SClusterName("prod-cluster"),
),
)// Cloud provider
semconv.CloudProvider(provider string) attribute.KeyValue
// Cloud account ID
semconv.CloudAccountID(id string) attribute.KeyValue
// Cloud region
semconv.CloudRegion(region string) attribute.KeyValue
// Cloud availability zone
semconv.CloudAvailabilityZone(zone string) attribute.KeyValue
// Cloud platform
semconv.CloudPlatform(platform string) attribute.KeyValueExample:
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.CloudProvider("aws"),
semconv.CloudPlatform("aws_eks"),
semconv.CloudRegion("us-east-1"),
semconv.CloudAvailabilityZone("us-east-1a"),
semconv.CloudAccountID("123456789012"),
),
)Standard attributes for describing operations.
// HTTP method
semconv.HTTPMethod(method string) attribute.KeyValue
// HTTP URL
semconv.HTTPURL(url string) attribute.KeyValue
// HTTP status code
semconv.HTTPStatusCode(code int) attribute.KeyValue
// HTTP target
semconv.HTTPTarget(target string) attribute.KeyValue
// HTTP host
semconv.HTTPHost(host string) attribute.KeyValue
// HTTP scheme
semconv.HTTPScheme(scheme string) attribute.KeyValue
// HTTP user agent
semconv.HTTPUserAgent(userAgent string) attribute.KeyValue
// HTTP request content length
semconv.HTTPRequestContentLength(length int) attribute.KeyValue
// HTTP response content length
semconv.HTTPResponseContentLength(length int) attribute.KeyValueExample:
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
)
func makeHTTPRequest(ctx context.Context, url string) {
tracer := otel.Tracer("http-client")
ctx, span := tracer.Start(ctx, "HTTP GET",
trace.WithSpanKind(trace.SpanKindClient),
trace.WithAttributes(
semconv.HTTPMethod("GET"),
semconv.HTTPURL(url),
semconv.HTTPScheme("https"),
),
)
defer span.End()
// Make request
// ...
// Record response
span.SetAttributes(
semconv.HTTPStatusCode(200),
semconv.HTTPResponseContentLength(1024),
)
}// HTTP route (pattern matched)
semconv.HTTPRoute(route string) attribute.KeyValue
// HTTP server name
semconv.HTTPServerName(name string) attribute.KeyValue
// Net host name
semconv.NetHostName(name string) attribute.KeyValue
// Net host port
semconv.NetHostPort(port int) attribute.KeyValueExample:
func handleHTTPRequest(w http.ResponseWriter, r *http.Request) {
tracer := otel.Tracer("http-server")
ctx, span := tracer.Start(r.Context(), r.URL.Path,
trace.WithSpanKind(trace.SpanKindServer),
trace.WithAttributes(
semconv.HTTPMethod(r.Method),
semconv.HTTPTarget(r.URL.Path),
semconv.HTTPRoute("/api/users/:id"),
semconv.NetHostName(r.Host),
semconv.HTTPScheme(r.URL.Scheme),
),
)
defer span.End()
// Handle request
// ...
span.SetAttributes(semconv.HTTPStatusCode(200))
}// Database system
semconv.DBSystem(system string) attribute.KeyValue
// Database connection string
semconv.DBConnectionString(connectionString string) attribute.KeyValue
// Database user
semconv.DBUser(user string) attribute.KeyValue
// Database name
semconv.DBName(name string) attribute.KeyValue
// Database statement
semconv.DBStatement(statement string) attribute.KeyValue
// Database operation
semconv.DBOperation(operation string) attribute.KeyValue
// SQL table
semconv.DBSQLTable(table string) attribute.KeyValueExample:
func queryDatabase(ctx context.Context, query string) {
tracer := otel.Tracer("database")
ctx, span := tracer.Start(ctx, "db.query",
trace.WithSpanKind(trace.SpanKindClient),
trace.WithAttributes(
semconv.DBSystem("postgresql"),
semconv.DBName("mydb"),
semconv.DBStatement(query),
semconv.DBOperation("SELECT"),
semconv.DBSQLTable("users"),
semconv.NetPeerName("db.example.com"),
semconv.NetPeerPort(5432),
),
)
defer span.End()
// Execute query
// ...
}// RPC system
semconv.RPCSystem(system string) attribute.KeyValue
// RPC service
semconv.RPCService(service string) attribute.KeyValue
// RPC method
semconv.RPCMethod(method string) attribute.KeyValue
// gRPC status code
semconv.RPCGRPCStatusCode(code int) attribute.KeyValueExample:
func callGRPC(ctx context.Context) {
tracer := otel.Tracer("grpc-client")
ctx, span := tracer.Start(ctx, "grpc.call",
trace.WithSpanKind(trace.SpanKindClient),
trace.WithAttributes(
semconv.RPCSystem("grpc"),
semconv.RPCService("UserService"),
semconv.RPCMethod("GetUser"),
semconv.NetPeerName("api.example.com"),
semconv.NetPeerPort(9090),
),
)
defer span.End()
// Make gRPC call
// ...
span.SetAttributes(semconv.RPCGRPCStatusCode(0)) // OK
}// Messaging system
semconv.MessagingSystem(system string) attribute.KeyValue
// Messaging destination
semconv.MessagingDestination(destination string) attribute.KeyValue
// Messaging destination kind
semconv.MessagingDestinationKind(kind string) attribute.KeyValue
// Messaging message ID
semconv.MessagingMessageID(id string) attribute.KeyValue
// Messaging operation
semconv.MessagingOperation(operation string) attribute.KeyValueExample:
func publishMessage(ctx context.Context) {
tracer := otel.Tracer("messaging")
ctx, span := tracer.Start(ctx, "message.send",
trace.WithSpanKind(trace.SpanKindProducer),
trace.WithAttributes(
semconv.MessagingSystem("kafka"),
semconv.MessagingDestination("orders"),
semconv.MessagingDestinationKind("topic"),
semconv.MessagingOperation("send"),
),
)
defer span.End()
// Publish message
// ...
span.SetAttributes(
semconv.MessagingMessageID("msg-123"),
)
}// Network peer name
semconv.NetPeerName(name string) attribute.KeyValue
// Network peer port
semconv.NetPeerPort(port int) attribute.KeyValue
// Network peer IP
semconv.NetPeerIP(ip string) attribute.KeyValue
// Network transport
semconv.NetTransport(transport string) attribute.KeyValue
// Network protocol name
semconv.NetProtocolName(name string) attribute.KeyValue
// Network protocol version
semconv.NetProtocolVersion(version string) attribute.KeyValue// Exception type
semconv.ExceptionType(exceptionType string) attribute.KeyValue
// Exception message
semconv.ExceptionMessage(message string) attribute.KeyValue
// Exception stacktrace
semconv.ExceptionStacktrace(stacktrace string) attribute.KeyValue
// Exception escaped
semconv.ExceptionEscaped(escaped bool) attribute.KeyValueExample:
func handleError(ctx context.Context, err error) {
tracer := otel.Tracer("error-handler")
ctx, span := tracer.Start(ctx, "handle-error")
defer span.End()
if err != nil {
span.RecordError(err, trace.WithAttributes(
semconv.ExceptionType("DatabaseError"),
semconv.ExceptionMessage(err.Error()),
))
span.SetStatus(codes.Error, err.Error())
}
}Standard metric names and attributes.
// HTTP server request duration
"http.server.request.duration"
// HTTP server active requests
"http.server.active_requests"
// HTTP client request duration
"http.client.request.duration"Example:
meter := otel.Meter("http-server")
requestDuration, err := meter.Float64Histogram(
"http.server.request.duration",
metric.WithDescription("Duration of HTTP server requests"),
metric.WithUnit("ms"),
)
requestDuration.Record(ctx, 45.2,
metric.WithAttributes(
semconv.HTTPMethod("GET"),
semconv.HTTPRoute("/api/users"),
semconv.HTTPStatusCode(200),
),
)// System CPU utilization
"system.cpu.utilization"
// System memory usage
"system.memory.usage"
// System network I/O
"system.network.io"package main
import (
"context"
"log"
"net/http"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
"go.opentelemetry.io/otel/trace"
)
func main() {
ctx := context.Background()
// Create resource with semantic conventions
res, err := resource.New(ctx,
resource.WithAttributes(
// Service attributes
semconv.ServiceName("user-api"),
semconv.ServiceVersion("1.0.0"),
semconv.ServiceInstanceID("instance-1"),
semconv.DeploymentEnvironment("production"),
// Cloud attributes
semconv.CloudProvider("aws"),
semconv.CloudPlatform("aws_eks"),
semconv.CloudRegion("us-east-1"),
// Kubernetes attributes
semconv.K8SPodName("user-api-7d5f6b8c9d-abcde"),
semconv.K8SNamespaceName("production"),
semconv.K8SDeploymentName("user-api"),
),
resource.WithProcess(),
resource.WithHost(),
)
if err != nil {
log.Fatal(err)
}
// Setup tracing
exporter, err := otlptracehttp.New(ctx)
if err != nil {
log.Fatal(err)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(res),
)
otel.SetTracerProvider(tp)
defer tp.Shutdown(ctx)
// Setup propagation
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
propagation.TraceContext{},
propagation.Baggage{},
))
// Start HTTP server
http.HandleFunc("/api/users", handleUsers)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handleUsers(w http.ResponseWriter, r *http.Request) {
tracer := otel.Tracer("user-api")
// Extract context
ctx := otel.GetTextMapPropagator().Extract(
r.Context(),
propagation.HeaderCarrier(r.Header),
)
// Start server span with semantic conventions
ctx, span := tracer.Start(ctx, r.URL.Path,
trace.WithSpanKind(trace.SpanKindServer),
trace.WithAttributes(
semconv.HTTPMethod(r.Method),
semconv.HTTPTarget(r.URL.Path),
semconv.HTTPRoute("/api/users"),
semconv.HTTPScheme(r.URL.Scheme),
semconv.NetHostName(r.Host),
semconv.HTTPUserAgent(r.UserAgent()),
),
)
defer span.End()
// Process request
err := processUserRequest(ctx)
// Record response with semantic conventions
statusCode := http.StatusOK
if err != nil {
statusCode = http.StatusInternalServerError
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
}
span.SetAttributes(
semconv.HTTPStatusCode(statusCode),
)
w.WriteHeader(statusCode)
}
func processUserRequest(ctx context.Context) error {
tracer := otel.Tracer("user-api")
// Database query with semantic conventions
ctx, dbSpan := tracer.Start(ctx, "db.query",
trace.WithSpanKind(trace.SpanKindClient),
trace.WithAttributes(
semconv.DBSystem("postgresql"),
semconv.DBName("users"),
semconv.DBStatement("SELECT * FROM users WHERE id = $1"),
semconv.DBOperation("SELECT"),
semconv.NetPeerName("db.example.com"),
semconv.NetPeerPort(5432),
),
)
defer dbSpan.End()
// Execute query
// ...
return nil
}OpenTelemetry semantic conventions are versioned independently from the SDK.
// Use v1.37.0 (latest stable)
import semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
// Use older version if needed
import semconv124 "go.opentelemetry.io/otel/semconv/v1.24.0"// Gradually migrate to newer version
import (
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
semconvold "go.opentelemetry.io/otel/semconv/v1.24.0"
)
// Use new version for new code
semconv.HTTPMethod("GET")
// Old code still works with old version
semconvold.HTTPMethodKey.String("GET")// Good: Use semantic conventions
span.SetAttributes(
semconv.HTTPMethod("GET"),
semconv.HTTPStatusCode(200),
)
// Bad: Custom attribute names
span.SetAttributes(
attribute.String("http.method", "GET"),
attribute.Int("status.code", 200),
)// Good: Use latest stable version
import semconv "go.opentelemetry.io/otel/semconv/v1.37.0"// Good: Consistent use of conventions
semconv.HTTPMethod(r.Method)
semconv.HTTPStatusCode(statusCode)
semconv.HTTPRoute(route)
// Bad: Mix of conventions and custom
semconv.HTTPMethod(r.Method)
attribute.Int("status", statusCode) // Should use semconvInstall with Tessl CLI
npx tessl i tessl/golang-go-opentelemetry-io--otel