package tracing import ( "context" "fmt" "strings" "go.nhat.io/otelsql" semconv "go.opentelemetry.io/otel/semconv/v1.14.0" "go.opentelemetry.io/otel/trace" "golang.org/x/xerrors" ) // Postgres driver will register a new tracing sql driver and return the driver name. func PostgresDriver(tp trace.TracerProvider, service string) (string, error) { // Register the otelsql wrapper for the provided postgres driver. driverName, err := otelsql.Register("postgres", otelsql.WithDefaultAttributes( semconv.ServiceNameKey.String(service), ), otelsql.TraceQueryWithoutArgs(), otelsql.WithSystem(semconv.DBSystemPostgreSQL), otelsql.WithTracerProvider(tp), otelsql.WithSpanNameFormatter(formatPostgresSpan), ) if err != nil { return "", xerrors.Errorf("registering postgres tracing driver: %w", err) } return driverName, nil } func formatPostgresSpan(ctx context.Context, op string) string { const qPrefix = "-- name: " q := otelsql.QueryFromContext(ctx) if q == "" || !strings.HasPrefix(q, qPrefix) { return strings.ToUpper(op) } // Remove the qPrefix and then grab the method name. // We expect the first line of the query to be in // the format "-- name: GetAPIKeyByID :one". s := strings.SplitN(strings.TrimPrefix(q, qPrefix), " ", 2)[0] return fmt.Sprintf("%s %s", strings.ToUpper(op), s) }