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 semconv