Skip to content

Commit 145df27

Browse files
authored
Merge pull request #2503 from authzed/1548-tracing-otel-semantic-conventions
OpenTelemetry Semantic Conventions for Tracing
2 parents 1f1a1c5 + 1186309 commit 145df27

File tree

25 files changed

+975
-86
lines changed

25 files changed

+975
-86
lines changed

internal/caveats/run.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"go.opentelemetry.io/otel"
1010
"go.opentelemetry.io/otel/attribute"
1111

12+
"github.com/authzed/spicedb/internal/telemetry/otelconv"
1213
"github.com/authzed/spicedb/pkg/caveats"
1314
caveattypes "github.com/authzed/spicedb/pkg/caveats/types"
1415
"github.com/authzed/spicedb/pkg/datastore"
@@ -90,8 +91,8 @@ func (cr *CaveatRunner) PopulateCaveatDefinitionsForExpr(ctx context.Context, ex
9091
caveatNames := mapz.NewSet[string]()
9192
collectCaveatNames(expr, caveatNames)
9293

93-
span.AddEvent("collected caveat names")
94-
span.SetAttributes(attribute.StringSlice("caveat-names", caveatNames.AsSlice()))
94+
span.AddEvent(otelconv.EventCaveatsNamesCollected)
95+
span.SetAttributes(attribute.StringSlice(otelconv.AttrCaveatsNames, caveatNames.AsSlice()))
9596

9697
if caveatNames.IsEmpty() {
9798
return fmt.Errorf("received empty caveat expression")
@@ -111,7 +112,7 @@ func (cr *CaveatRunner) PopulateCaveatDefinitionsForExpr(ctx context.Context, ex
111112
if err != nil {
112113
return err
113114
}
114-
span.AddEvent("looked up caveats")
115+
span.AddEvent(otelconv.EventCaveatsLookedUp)
115116

116117
for _, cd := range caveatDefs {
117118
cr.caveatDefs[cd.Definition.GetName()] = cd.Definition
@@ -170,7 +171,7 @@ func (cr *CaveatRunner) runExpressionWithCaveats(
170171
defer span.End()
171172

172173
if expr.GetCaveat() != nil {
173-
span.SetAttributes(attribute.String("caveat-name", expr.GetCaveat().CaveatName))
174+
span.SetAttributes(attribute.StringSlice(otelconv.AttrCaveatsNames, []string{expr.GetCaveat().CaveatName}))
174175

175176
caveat, compiled, err := cr.get(expr.GetCaveat().CaveatName)
176177
if err != nil {
@@ -211,7 +212,7 @@ func (cr *CaveatRunner) runExpressionWithCaveats(
211212
}
212213

213214
cop := expr.GetOperation()
214-
span.SetAttributes(attribute.String("caveat-operation", cop.Op.String()))
215+
span.SetAttributes(attribute.StringSlice(otelconv.AttrCaveatsOperations, []string{cop.Op.String()}))
215216

216217
var currentResult ExpressionResult = syntheticResult{
217218
value: cop.Op == core.CaveatOperation_AND,

internal/datastore/common/relationships.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"go.opentelemetry.io/otel/trace"
1111
"google.golang.org/protobuf/types/known/timestamppb"
1212

13+
"github.com/authzed/spicedb/internal/telemetry/otelconv"
1314
"github.com/authzed/spicedb/pkg/datastore"
1415
corev1 "github.com/authzed/spicedb/pkg/proto/core/v1"
1516
"github.com/authzed/spicedb/pkg/tuple"
@@ -116,17 +117,17 @@ func QueryRelationships[R Rows, C ~map[string]any](ctx context.Context, builder
116117
var integrityHash []byte
117118
var timestamp time.Time
118119

119-
span.AddEvent("Selecting columns")
120+
span.AddEvent(otelconv.EventDatastoreColumnsSelected)
120121
colsToSelect, err := ColumnsToSelect(builder, &resourceObjectType, &resourceObjectID, &resourceRelation, &subjectObjectType, &subjectObjectID, &subjectRelation, &caveatName, &caveatCtx, &expiration, &integrityKeyID, &integrityHash, &timestamp)
121122
if err != nil {
122123
return nil, fmt.Errorf(errUnableToQueryRels, err)
123124
}
124125

125-
span.AddEvent("Returning iterator", trace.WithAttributes(attribute.Int("column-count", len(colsToSelect))))
126+
span.AddEvent(otelconv.EventDatastoreIteratorCreate, trace.WithAttributes(attribute.Int(otelconv.AttrDatastoreColumnCount, len(colsToSelect))))
126127
return func(yield func(tuple.Relationship, error) bool) {
127-
span.AddEvent("Issuing query to database")
128+
span.AddEvent(otelconv.EventDatastoreExecuteIssued)
128129
err := tx.QueryFunc(ctx, func(ctx context.Context, rows R) error {
129-
span.AddEvent("Query issued to database")
130+
span.AddEvent(otelconv.EventDatastoreExecuteStarted)
130131

131132
var r Rows = rows
132133
if crwe, ok := r.(closeRowsWithError); ok {
@@ -138,15 +139,15 @@ func QueryRelationships[R Rows, C ~map[string]any](ctx context.Context, builder
138139
relCount := 0
139140
for rows.Next() {
140141
if relCount == 0 {
141-
span.AddEvent("First row returned")
142+
span.AddEvent(otelconv.EventDatastoreRowsFirstReturned)
142143
}
143144

144145
if err := rows.Scan(colsToSelect...); err != nil {
145146
return fmt.Errorf(errUnableToQueryRels, fmt.Errorf("scan err: %w", err))
146147
}
147148

148149
if relCount == 0 {
149-
span.AddEvent("First row scanned")
150+
span.AddEvent(otelconv.EventDatastoreRowsFirstScanned)
150151
}
151152

152153
var caveat *corev1.ContextualizedCaveat
@@ -198,7 +199,7 @@ func QueryRelationships[R Rows, C ~map[string]any](ctx context.Context, builder
198199
}
199200
}
200201

201-
span.AddEvent("Relationships loaded", trace.WithAttributes(attribute.Int("relCount", relCount)))
202+
span.AddEvent(otelconv.EventDatastoreRelationshipsLoaded, trace.WithAttributes(attribute.Int(otelconv.AttrDatastoreRelationshipsCount, relCount)))
202203
if err := rows.Err(); err != nil {
203204
return fmt.Errorf(errUnableToQueryRels, fmt.Errorf("rows err: %w", err))
204205
}

internal/datastore/mysql/revisions.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ import (
88
"time"
99

1010
"github.com/ccoveille/go-safecast"
11+
"go.opentelemetry.io/otel/attribute"
12+
"go.opentelemetry.io/otel/trace"
1113

1214
"github.com/authzed/spicedb/internal/datastore/revisions"
15+
"github.com/authzed/spicedb/internal/telemetry/otelconv"
1316
"github.com/authzed/spicedb/pkg/datastore"
1417
"github.com/authzed/spicedb/pkg/spiceerrors"
1518
)
@@ -153,7 +156,10 @@ func (mds *Datastore) checkValidTransaction(ctx context.Context, revisionTx uint
153156
return false, false, fmt.Errorf(errCheckRevision, err)
154157
}
155158

156-
span.AddEvent("DB returned validTransaction checks")
159+
span.AddEvent(otelconv.EventDatastoreMySQLTransactionValidated, trace.WithAttributes(
160+
attribute.Bool(otelconv.AttrDatastoreMySQLTransactionFresh, freshEnough.Bool),
161+
attribute.Bool(otelconv.AttrDatastoreMySQLTransactionUnknown, unknown.Bool),
162+
))
157163

158164
return freshEnough.Bool, unknown.Bool, nil
159165
}

internal/datastore/postgres/log_tracer.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ import (
55

66
"github.com/jackc/pgx/v5/tracelog"
77
"go.opentelemetry.io/otel/attribute"
8+
semconv "go.opentelemetry.io/otel/semconv/v1.32.0"
89
"go.opentelemetry.io/otel/trace"
10+
11+
"github.com/authzed/spicedb/internal/telemetry/otelconv"
912
)
1013

1114
type tracingLogger struct{}
1215

1316
func (tl tracingLogger) Log(ctx context.Context, level tracelog.LogLevel, msg string, _ map[string]any) {
1417
span := trace.SpanFromContext(ctx)
15-
span.AddEvent(msg, trace.WithAttributes(attribute.Stringer("level", level), attribute.String("datastore", "postgres")))
18+
span.AddEvent(msg, trace.WithAttributes(attribute.Stringer(otelconv.AttrDatastorePostgresLogLevel, level), semconv.DBSystemNamePostgreSQL))
1619
}

internal/datastore/proxy/observable.go

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
1313

1414
"github.com/authzed/spicedb/internal/datastore/common"
15+
"github.com/authzed/spicedb/internal/telemetry/otelconv"
1516
"github.com/authzed/spicedb/pkg/datastore"
1617
"github.com/authzed/spicedb/pkg/datastore/options"
1718
core "github.com/authzed/spicedb/pkg/proto/core/v1"
@@ -97,7 +98,7 @@ func (p *observableProxy) OptimizedRevision(ctx context.Context) (datastore.Revi
9798

9899
func (p *observableProxy) CheckRevision(ctx context.Context, revision datastore.Revision) error {
99100
ctx, closer := observe(ctx, "CheckRevision", "", trace.WithAttributes(
100-
attribute.String("revision", revision.String()),
101+
attribute.String(otelconv.AttrDatastoreRevision, revision.String()),
101102
))
102103
defer closer()
103104

@@ -154,7 +155,7 @@ type observableReader struct{ delegate datastore.Reader }
154155

155156
func (r *observableReader) CountRelationships(ctx context.Context, name string) (int, error) {
156157
ctx, closer := observe(ctx, "CountRelationships", "", trace.WithAttributes(
157-
attribute.String("name", name),
158+
attribute.StringSlice(otelconv.AttrDatastoreNames, []string{name}),
158159
))
159160
defer closer()
160161

@@ -170,7 +171,7 @@ func (r *observableReader) LookupCounters(ctx context.Context) ([]datastore.Rela
170171

171172
func (r *observableReader) ReadCaveatByName(ctx context.Context, name string) (*core.CaveatDefinition, datastore.Revision, error) {
172173
ctx, closer := observe(ctx, "ReadCaveatByName", "", trace.WithAttributes(
173-
attribute.String("name", name),
174+
attribute.StringSlice(otelconv.AttrDatastoreNames, []string{name}),
174175
))
175176
defer closer()
176177

@@ -179,7 +180,7 @@ func (r *observableReader) ReadCaveatByName(ctx context.Context, name string) (*
179180

180181
func (r *observableReader) LookupCaveatsWithNames(ctx context.Context, caveatNames []string) ([]datastore.RevisionedCaveat, error) {
181182
ctx, closer := observe(ctx, "LookupCaveatsWithNames", "", trace.WithAttributes(
182-
attribute.StringSlice("names", caveatNames),
183+
attribute.StringSlice(otelconv.AttrDatastoreNames, caveatNames),
183184
))
184185
defer closer()
185186

@@ -202,7 +203,7 @@ func (r *observableReader) ListAllNamespaces(ctx context.Context) ([]datastore.R
202203

203204
func (r *observableReader) LookupNamespacesWithNames(ctx context.Context, nsNames []string) ([]datastore.RevisionedNamespace, error) {
204205
ctx, closer := observe(ctx, "LookupNamespacesWithNames", "", trace.WithAttributes(
205-
attribute.StringSlice("names", nsNames),
206+
attribute.StringSlice(otelconv.AttrDatastoreNames, nsNames),
206207
))
207208
defer closer()
208209

@@ -211,7 +212,7 @@ func (r *observableReader) LookupNamespacesWithNames(ctx context.Context, nsName
211212

212213
func (r *observableReader) ReadNamespaceByName(ctx context.Context, nsName string) (*core.NamespaceDefinition, datastore.Revision, error) {
213214
ctx, closer := observe(ctx, "ReadNamespaceByName", "", trace.WithAttributes(
214-
attribute.String("name", nsName),
215+
attribute.StringSlice(otelconv.AttrDatastoreNames, []string{nsName}),
215216
))
216217
defer closer()
217218

@@ -221,9 +222,9 @@ func (r *observableReader) ReadNamespaceByName(ctx context.Context, nsName strin
221222
func (r *observableReader) QueryRelationships(ctx context.Context, filter datastore.RelationshipsFilter, opts ...options.QueryOptionsOption) (datastore.RelationshipIterator, error) {
222223
queryOpts := options.NewQueryOptionsWithOptions(opts...)
223224
ctx, closer := observe(ctx, "QueryRelationships", string(queryOpts.QueryShape), trace.WithAttributes(
224-
attribute.String("resourceType", filter.OptionalResourceType),
225-
attribute.String("resourceRelation", filter.OptionalResourceRelation),
226-
attribute.String("queryShape", string(queryOpts.QueryShape)),
225+
attribute.String(otelconv.AttrDatastoreResourceType, filter.OptionalResourceType),
226+
attribute.String(otelconv.AttrDatastoreResourceRelation, filter.OptionalResourceRelation),
227+
attribute.String(otelconv.AttrDatastoreQueryShape, string(queryOpts.QueryShape)),
227228
))
228229

229230
iterator, err := r.delegate.QueryRelationships(ctx, filter, opts...)
@@ -249,8 +250,8 @@ func (r *observableReader) QueryRelationships(ctx context.Context, filter datast
249250
func (r *observableReader) ReverseQueryRelationships(ctx context.Context, subjectsFilter datastore.SubjectsFilter, opts ...options.ReverseQueryOptionsOption) (datastore.RelationshipIterator, error) {
250251
queryOpts := options.NewReverseQueryOptionsWithOptions(opts...)
251252
ctx, closer := observe(ctx, "ReverseQueryRelationships", string(queryOpts.QueryShapeForReverse), trace.WithAttributes(
252-
attribute.String("subjectType", subjectsFilter.SubjectType),
253-
attribute.String("queryShape", string(queryOpts.QueryShapeForReverse))))
253+
attribute.String(otelconv.AttrDatastoreSubjectType, subjectsFilter.SubjectType),
254+
attribute.String(otelconv.AttrDatastoreQueryShape, string(queryOpts.QueryShapeForReverse))))
254255

255256
iterator, err := r.delegate.ReverseQueryRelationships(ctx, subjectsFilter, opts...)
256257
if err != nil {
@@ -279,7 +280,7 @@ type observableRWT struct {
279280

280281
func (rwt *observableRWT) RegisterCounter(ctx context.Context, name string, filter *core.RelationshipFilter) error {
281282
ctx, closer := observe(ctx, "RegisterCounter", "", trace.WithAttributes(
282-
attribute.String("name", name),
283+
attribute.StringSlice(otelconv.AttrDatastoreNames, []string{name}),
283284
))
284285
defer closer()
285286

@@ -288,7 +289,7 @@ func (rwt *observableRWT) RegisterCounter(ctx context.Context, name string, filt
288289

289290
func (rwt *observableRWT) UnregisterCounter(ctx context.Context, name string) error {
290291
ctx, closer := observe(ctx, "UnregisterCounter", "", trace.WithAttributes(
291-
attribute.String("name", name),
292+
attribute.StringSlice(otelconv.AttrDatastoreNames, []string{name}),
292293
))
293294
defer closer()
294295

@@ -297,9 +298,9 @@ func (rwt *observableRWT) UnregisterCounter(ctx context.Context, name string) er
297298

298299
func (rwt *observableRWT) StoreCounterValue(ctx context.Context, name string, value int, computedAtRevision datastore.Revision) error {
299300
ctx, closer := observe(ctx, "StoreCounterValue", "", trace.WithAttributes(
300-
attribute.String("name", name),
301-
attribute.Int("value", value),
302-
attribute.String("revision", computedAtRevision.String()),
301+
attribute.StringSlice(otelconv.AttrDatastoreNames, []string{name}),
302+
attribute.Int(otelconv.AttrDatastoreValue, value),
303+
attribute.String(otelconv.AttrDatastoreRevision, computedAtRevision.String()),
303304
))
304305
defer closer()
305306

@@ -313,7 +314,7 @@ func (rwt *observableRWT) WriteCaveats(ctx context.Context, caveats []*core.Cave
313314
}
314315

315316
ctx, closer := observe(ctx, "WriteCaveats", "", trace.WithAttributes(
316-
attribute.StringSlice("names", caveatNames),
317+
attribute.StringSlice(otelconv.AttrDatastoreNames, caveatNames),
317318
))
318319
defer closer()
319320

@@ -322,7 +323,7 @@ func (rwt *observableRWT) WriteCaveats(ctx context.Context, caveats []*core.Cave
322323

323324
func (rwt *observableRWT) DeleteCaveats(ctx context.Context, names []string) error {
324325
ctx, closer := observe(ctx, "DeleteCaveats", "", trace.WithAttributes(
325-
attribute.StringSlice("names", names),
326+
attribute.StringSlice(otelconv.AttrDatastoreNames, names),
326327
))
327328
defer closer()
328329

@@ -331,7 +332,7 @@ func (rwt *observableRWT) DeleteCaveats(ctx context.Context, names []string) err
331332

332333
func (rwt *observableRWT) WriteRelationships(ctx context.Context, mutations []tuple.RelationshipUpdate) error {
333334
ctx, closer := observe(ctx, "WriteRelationships", "", trace.WithAttributes(
334-
attribute.Int("mutations", len(mutations)),
335+
attribute.Int(otelconv.AttrDatastoreMutations, len(mutations)),
335336
))
336337
defer closer()
337338

@@ -345,7 +346,7 @@ func (rwt *observableRWT) WriteNamespaces(ctx context.Context, newConfigs ...*co
345346
}
346347

347348
ctx, closer := observe(ctx, "WriteNamespaces", "", trace.WithAttributes(
348-
attribute.StringSlice("names", nsNames),
349+
attribute.StringSlice(otelconv.AttrDatastoreNames, nsNames),
349350
))
350351
defer closer()
351352

@@ -354,7 +355,7 @@ func (rwt *observableRWT) WriteNamespaces(ctx context.Context, newConfigs ...*co
354355

355356
func (rwt *observableRWT) DeleteNamespaces(ctx context.Context, nsNames ...string) error {
356357
ctx, closer := observe(ctx, "DeleteNamespaces", "", trace.WithAttributes(
357-
attribute.StringSlice("names", nsNames),
358+
attribute.StringSlice(otelconv.AttrDatastoreNames, nsNames),
358359
))
359360
defer closer()
360361

internal/datastore/revisions/optimized.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"golang.org/x/sync/singleflight"
1414

1515
log "github.com/authzed/spicedb/internal/logging"
16+
"github.com/authzed/spicedb/internal/telemetry/otelconv"
1617
"github.com/authzed/spicedb/pkg/datastore"
1718
)
1819

@@ -56,15 +57,14 @@ func (cor *CachedOptimizedRevisions) OptimizedRevision(ctx context.Context) (dat
5657
if candidate.validThrough.After(adjustedNow) {
5758
cor.RUnlock()
5859
log.Ctx(ctx).Debug().Time("now", localNow).Time("valid", candidate.validThrough).Msg("returning cached revision")
59-
span.AddEvent("returning cached revision")
60+
span.AddEvent(otelconv.EventDatastoreRevisionsCacheReturned)
6061
return candidate.revision, nil
6162
}
6263
}
6364
cor.RUnlock()
6465

6566
newQuantizedRevision, err, _ := cor.updateGroup.Do("", func() (any, error) {
6667
log.Ctx(ctx).Debug().Time("now", localNow).Msg("computing new revision")
67-
span.AddEvent("computing new revision")
6868

6969
optimized, validFor, err := cor.optimizedFunc(ctx)
7070
if err != nil {
@@ -88,6 +88,7 @@ func (cor *CachedOptimizedRevisions) OptimizedRevision(ctx context.Context) (dat
8888
cor.candidates = append(cor.candidates, validRevision{optimized, rvt})
8989
cor.Unlock()
9090

91+
span.AddEvent(otelconv.EventDatastoreRevisionsComputed)
9192
log.Ctx(ctx).Debug().Time("now", localNow).Time("valid", rvt).Stringer("validFor", validFor).Msg("setting valid through")
9293
return optimized, nil
9394
})

internal/datastore/spanner/reader.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
"github.com/authzed/spicedb/internal/datastore/common"
1515
"github.com/authzed/spicedb/internal/datastore/revisions"
16+
"github.com/authzed/spicedb/internal/telemetry/otelconv"
1617
"github.com/authzed/spicedb/pkg/datastore"
1718
"github.com/authzed/spicedb/pkg/datastore/options"
1819
core "github.com/authzed/spicedb/pkg/proto/core/v1"
@@ -187,7 +188,6 @@ func queryExecutor(txSource txFactory) common.ExecuteReadRelsQueryFunc {
187188
return func(ctx context.Context, builder common.RelationshipsQueryBuilder) (datastore.RelationshipIterator, error) {
188189
return func(yield func(tuple.Relationship, error) bool) {
189190
span := trace.SpanFromContext(ctx)
190-
span.AddEvent("Query issued to database")
191191

192192
sql, args, err := builder.SelectSQL()
193193
if err != nil {
@@ -197,12 +197,10 @@ func queryExecutor(txSource txFactory) common.ExecuteReadRelsQueryFunc {
197197

198198
iter := txSource().Query(ctx, statementFromSQL(sql, args))
199199
defer iter.Stop()
200-
201-
span.AddEvent("start reading iterator")
202-
defer span.AddEvent("finished reading iterator")
200+
span.AddEvent(otelconv.EventDatastoreSpannerQueryIssued)
203201

204202
relCount := 0
205-
defer span.SetAttributes(attribute.Int("count", relCount))
203+
defer span.SetAttributes(attribute.Int(otelconv.AttrDatastoreRelationCount, relCount))
206204

207205
var resourceObjectType string
208206
var resourceObjectID string
@@ -238,6 +236,8 @@ func queryExecutor(txSource txFactory) common.ExecuteReadRelsQueryFunc {
238236
return
239237
}
240238

239+
span.AddEvent(otelconv.EventDatastoreSpannerIteratorStarted)
240+
defer span.AddEvent(otelconv.EventDatastoreSpannerIteratorFinished)
241241
if err := iter.Do(func(row *spanner.Row) error {
242242
err := row.Columns(colsToSelect...)
243243
if err != nil {
@@ -362,7 +362,7 @@ func (sr spannerReader) LookupNamespacesWithNames(ctx context.Context, nsNames [
362362

363363
func readAllNamespaces(iter *spanner.RowIterator, span trace.Span) ([]datastore.RevisionedNamespace, error) {
364364
var allNamespaces []datastore.RevisionedNamespace
365-
span.AddEvent("start reading iterator")
365+
span.AddEvent(otelconv.EventDatastoreSpannerIteratorStarted)
366366
if err := iter.Do(func(row *spanner.Row) error {
367367
var serialized []byte
368368
var updated time.Time
@@ -384,8 +384,8 @@ func readAllNamespaces(iter *spanner.RowIterator, span trace.Span) ([]datastore.
384384
}); err != nil {
385385
return nil, err
386386
}
387-
span.AddEvent("finished reading iterator", trace.WithAttributes(attribute.Int("namespaceCount", len(allNamespaces))))
388-
span.SetAttributes(attribute.Int("count", len(allNamespaces)))
387+
span.AddEvent(otelconv.EventDatastoreSpannerIteratorFinished, trace.WithAttributes(attribute.Int(otelconv.AttrDatastoreNamespaceCount, len(allNamespaces))))
388+
span.SetAttributes(attribute.Int(otelconv.AttrDatastoreRelationCount, len(allNamespaces)))
389389
return allNamespaces, nil
390390
}
391391

0 commit comments

Comments
 (0)