Thanks to visit codestin.com
Credit goes to github.com

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

+14-5
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

+11-25
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

+45
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

+3-1
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

+13
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)