Skip to content

Commit 8bb8d91

Browse files
f0sselkylecarbs
authored andcommitted
feat: add tracing for sql (#1610)
1 parent 8a1db7b commit 8bb8d91

File tree

5 files changed

+86
-31
lines changed

5 files changed

+86
-31
lines changed

cli/server.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,13 @@ import (
2828
"github.com/pion/webrtc/v3"
2929
"github.com/prometheus/client_golang/prometheus/promhttp"
3030
"github.com/spf13/cobra"
31+
sdktrace "go.opentelemetry.io/otel/sdk/trace"
3132
"golang.org/x/oauth2"
3233
xgithub "golang.org/x/oauth2/github"
3334
"golang.org/x/xerrors"
3435
"google.golang.org/api/idtoken"
3536
"google.golang.org/api/option"
3637

37-
sdktrace "go.opentelemetry.io/otel/sdk/trace"
38-
3938
"cdr.dev/slog"
4039
"cdr.dev/slog/sloggers/sloghuman"
4140
"github.com/coder/coder/cli/cliflag"
@@ -103,8 +102,11 @@ func server() *cobra.Command {
103102
logger = logger.Leveled(slog.LevelDebug)
104103
}
105104

106-
var tracerProvider *sdktrace.TracerProvider
107-
var err error
105+
var (
106+
tracerProvider *sdktrace.TracerProvider
107+
err error
108+
sqlDriver = "postgres"
109+
)
108110
if trace {
109111
tracerProvider, err = tracing.TracerProvider(cmd.Context(), "coderd")
110112
if err != nil {
@@ -116,6 +118,13 @@ func server() *cobra.Command {
116118
defer cancel()
117119
_ = tracerProvider.Shutdown(ctx)
118120
}()
121+
122+
d, err := tracing.PostgresDriver(tracerProvider, "coderd.database")
123+
if err != nil {
124+
logger.Warn(cmd.Context(), "failed to start postgres tracing driver", slog.Error(err))
125+
} else {
126+
sqlDriver = d
127+
}
119128
}
120129
}
121130

@@ -245,7 +254,7 @@ func server() *cobra.Command {
245254
_, _ = fmt.Fprintln(cmd.ErrOrStderr())
246255

247256
if !dev {
248-
sqlDB, err := sql.Open("postgres", postgresURL)
257+
sqlDB, err := sql.Open(sqlDriver, postgresURL)
249258
if err != nil {
250259
return xerrors.Errorf("dial postgres: %w", err)
251260
}

coderd/tracing/httpmw.go

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,23 @@ import (
66

77
"github.com/go-chi/chi/middleware"
88
"github.com/go-chi/chi/v5"
9-
"go.opentelemetry.io/otel/attribute"
10-
"go.opentelemetry.io/otel/codes"
119
sdktrace "go.opentelemetry.io/otel/sdk/trace"
10+
semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
1211
)
1312

1413
// HTTPMW adds tracing to http routes.
1514
func HTTPMW(tracerProvider *sdktrace.TracerProvider, name string) func(http.Handler) http.Handler {
1615
return func(next http.Handler) http.Handler {
1716
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
18-
// do not trace if exporter has not be initialized
1917
if tracerProvider == nil {
2018
next.ServeHTTP(rw, r)
2119
return
2220
}
2321

2422
// start span with default span name. Span name will be updated to "method route" format once request finishes.
25-
_, span := tracerProvider.Tracer(name).Start(r.Context(), fmt.Sprintf("%s %s", r.Method, r.RequestURI))
23+
ctx, span := tracerProvider.Tracer(name).Start(r.Context(), fmt.Sprintf("%s %s", r.Method, r.RequestURI))
2624
defer span.End()
25+
r = r.WithContext(ctx)
2726

2827
wrw := middleware.NewWrapResponseWriter(rw, r.ProtoMajor)
2928

@@ -35,34 +34,21 @@ func HTTPMW(tracerProvider *sdktrace.TracerProvider, name string) func(http.Hand
3534
if route != "" {
3635
span.SetName(fmt.Sprintf("%s %s", r.Method, route))
3736
}
38-
span.SetAttributes(attribute.KeyValue{
39-
Key: "http.method",
40-
Value: attribute.StringValue(r.Method),
41-
})
42-
span.SetAttributes(attribute.KeyValue{
43-
Key: "http.route",
44-
Value: attribute.StringValue(route),
45-
})
46-
span.SetAttributes(attribute.KeyValue{
47-
Key: "http.path",
48-
Value: attribute.StringValue(r.URL.EscapedPath()),
49-
})
37+
span.SetName(fmt.Sprintf("%s %s", r.Method, route))
38+
span.SetAttributes(semconv.NetAttributesFromHTTPRequest("tcp", r)...)
39+
span.SetAttributes(semconv.EndUserAttributesFromHTTPRequest(r)...)
40+
span.SetAttributes(semconv.HTTPServerAttributesFromHTTPRequest("", route, r)...)
41+
span.SetAttributes(semconv.HTTPRouteKey.String(route))
5042

5143
// set the status code
5244
status := wrw.Status()
5345
// 0 status means one has not yet been sent in which case net/http library will write StatusOK
5446
if status == 0 {
5547
status = http.StatusOK
5648
}
57-
span.SetAttributes(attribute.KeyValue{
58-
Key: "http.status_code",
59-
Value: attribute.IntValue(status),
60-
})
61-
62-
// if 5XX we set the span to "error" status
63-
if status >= 500 {
64-
span.SetStatus(codes.Error, fmt.Sprintf("%d: %s", status, http.StatusText(status)))
65-
}
49+
span.SetAttributes(semconv.HTTPStatusCodeKey.Int(status))
50+
spanStatus, spanMessage := semconv.SpanStatusFromHTTPStatusCode(status)
51+
span.SetStatus(spanStatus, spanMessage)
6652
})
6753
}
6854
}

coderd/tracing/postgres.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package tracing
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/nhatthm/otelsql"
9+
semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
10+
"go.opentelemetry.io/otel/trace"
11+
"golang.org/x/xerrors"
12+
)
13+
14+
// Postgres driver will register a new tracing sql driver and return the driver name.
15+
func PostgresDriver(tp trace.TracerProvider, service string) (string, error) {
16+
// Register the otelsql wrapper for the provided postgres driver.
17+
driverName, err := otelsql.Register("postgres",
18+
otelsql.WithDefaultAttributes(
19+
semconv.ServiceNameKey.String(service),
20+
),
21+
otelsql.TraceQueryWithoutArgs(),
22+
otelsql.WithSystem(semconv.DBSystemPostgreSQL),
23+
otelsql.WithTracerProvider(tp),
24+
otelsql.WithSpanNameFormatter(formatPostgresSpan),
25+
)
26+
if err != nil {
27+
return "", xerrors.Errorf("registering postgres tracing driver: %w", err)
28+
}
29+
30+
return driverName, nil
31+
}
32+
33+
func formatPostgresSpan(ctx context.Context, op string) string {
34+
const qPrefix = "-- name: "
35+
q := otelsql.QueryFromContext(ctx)
36+
if q == "" || !strings.HasPrefix(q, qPrefix) {
37+
return strings.ToUpper(op)
38+
}
39+
40+
// Remove the qPrefix and then grab the method name.
41+
// We expect the first line of the query to be in
42+
// the format "-- name: GetAPIKeyByID :one".
43+
s := strings.SplitN(strings.TrimPrefix(q, qPrefix), " ", 2)[0]
44+
return fmt.Sprintf("%s %s", strings.ToUpper(op), s)
45+
}

go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ require (
197197
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect
198198
github.com/muesli/reflow v0.3.0 // indirect
199199
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 // indirect
200+
github.com/nhatthm/otelsql v0.3.0
200201
github.com/niklasfasching/go-org v1.6.2 // indirect
201202
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
202203
github.com/opencontainers/go-digest v1.0.0 // indirect
@@ -241,8 +242,9 @@ require (
241242
go.opentelemetry.io/otel v1.7.0
242243
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.7.0 // indirect
243244
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.7.0
245+
go.opentelemetry.io/otel/metric v0.30.0 // indirect
244246
go.opentelemetry.io/otel/sdk v1.7.0
245-
go.opentelemetry.io/otel/trace v1.7.0 // indirect
247+
go.opentelemetry.io/otel/trace v1.7.0
246248
go.opentelemetry.io/proto/otlp v0.16.0 // indirect
247249
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
248250
google.golang.org/appengine v1.6.7 // indirect

go.sum

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
9797
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
9898
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
9999
github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
100+
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
100101
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
101102
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
102103
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
@@ -228,6 +229,7 @@ github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqO
228229
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
229230
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
230231
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
232+
github.com/bool64/shared v0.1.4 h1:zwtb1dl2QzDa9TJOq2jzDTdb5IPf9XlxTGKN8cySWT0=
231233
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
232234
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
233235
github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
@@ -896,6 +898,7 @@ github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQg
896898
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
897899
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
898900
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
901+
github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA=
899902
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
900903
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
901904
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -1190,6 +1193,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
11901193
github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
11911194
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
11921195
github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI=
1196+
github.com/nhatthm/otelsql v0.3.0 h1:BvqFgk6FkkmlY2KrtSyxILkPJL5oI2Bzny/s7d134N8=
1197+
github.com/nhatthm/otelsql v0.3.0/go.mod h1:6OmgQmHfKwLqNQp+nNh5xHOrMl19y8n4v44FLRZWYlQ=
11931198
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
11941199
github.com/niklasfasching/go-org v1.6.2 h1:kQBIZlfL4oRNApJCrBgaeNBfzxWzP6XlC7/b744Polk=
11951200
github.com/niklasfasching/go-org v1.6.2/go.mod h1:wn76Xgu4/KRe43WZhsgZjxYMaloSrl3BSweGV74SwHs=
@@ -1490,6 +1495,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
14901495
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
14911496
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
14921497
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
1498+
github.com/swaggest/assertjson v1.6.8 h1:1O/9UI5M+2OJI7BeEWKGj0wTvpRXZt5FkOJ4nRkY4rA=
14931499
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
14941500
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
14951501
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -1554,6 +1560,8 @@ github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2
15541560
github.com/yashtewari/glob-intersection v0.1.0 h1:6gJvMYQlTDOL3dMsPF6J0+26vwX9MB8/1q3uAdhmTrg=
15551561
github.com/yashtewari/glob-intersection v0.1.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok=
15561562
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
1563+
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
1564+
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
15571565
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
15581566
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
15591567
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -1615,8 +1623,12 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.6.3/go.mod h1
16151623
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.7.0 h1:MFAyzUPrTwLOwCi+cltN0ZVyy4phU41lwH+lyMyQTS4=
16161624
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.7.0/go.mod h1:E+/KKhwOSw8yoPxSSuUHG6vKppkvhN+S1Jc7Nib3k3o=
16171625
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE=
1626+
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.30.0 h1:2glg1ZFVVZf47zFuX0iwBPPid4tqzBYYWTVVu0pc+us=
1627+
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0 h1:8hPcgCg0rUJiKE6VWahRvjgLUrNl7rW2hffUEPKXVEM=
16181628
go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
16191629
go.opentelemetry.io/otel/metric v0.28.0/go.mod h1:TrzsfQAmQaB1PDcdhBauLMk7nyyg9hm+GoQq/ekE9Iw=
1630+
go.opentelemetry.io/otel/metric v0.30.0 h1:Hs8eQZ8aQgs0U49diZoaS6Uaxw3+bBE3lcMUKBFIk3c=
1631+
go.opentelemetry.io/otel/metric v0.30.0/go.mod h1:/ShZ7+TS4dHzDFmfi1kSXMhMVubNoP0oIaBp70J6UXU=
16201632
go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
16211633
go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
16221634
go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
@@ -1625,6 +1637,7 @@ go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1
16251637
go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
16261638
go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
16271639
go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
1640+
go.opentelemetry.io/otel/sdk/metric v0.30.0 h1:XTqQ4y3erR2Oj8xSAOL5ovO5011ch2ELg51z4fVkpME=
16281641
go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
16291642
go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
16301643
go.opentelemetry.io/otel/trace v1.6.0/go.mod h1:qs7BrU5cZ8dXQHBGxHMOxwME/27YH2qEp4/+tZLLwJE=

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy