-
Notifications
You must be signed in to change notification settings - Fork 3
/
backend_trace.go
78 lines (63 loc) · 2.3 KB
/
backend_trace.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package zikade
import (
"context"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)
// tracedBackend wraps a [Backend] in calls to open telemetry tracing
// directives. In [New] all backends configured in [Config] or automatically
// configured if none are given will be wrapped with this tracedBackend.
type tracedBackend struct {
namespace string // the namespace the backend operates in. Used as a tracing attribute.
backend Backend // the [Backend] to be traced
tracer trace.Tracer // the tracer to be used
}
var _ Backend = (*tracedBackend)(nil)
func traceWrapBackend(namespace string, backend Backend, tracer trace.Tracer) Backend {
return &tracedBackend{
namespace: namespace,
backend: backend,
tracer: tracer,
}
}
// Store implements the [Backend] interface, forwards the call to the wrapped
// backend and manages the trace span.
func (t *tracedBackend) Store(ctx context.Context, key string, value any) (any, error) {
ctx, span := t.tracer.Start(ctx, "Store", t.traceAttributes(key))
defer span.End()
result, err := t.backend.Store(ctx, key, value)
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
}
return result, err
}
// Fetch implements the [Backend] interface, forwards the call to the wrapped
// backend and manages the trace span.
func (t *tracedBackend) Fetch(ctx context.Context, key string) (any, error) {
ctx, span := t.tracer.Start(ctx, "Fetch", t.traceAttributes(key))
defer span.End()
result, err := t.backend.Fetch(ctx, key)
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
}
return result, err
}
func (t *tracedBackend) Validate(ctx context.Context, key string, values ...any) (int, error) {
ctx, span := t.tracer.Start(ctx, "Validate", t.traceAttributes(key))
defer span.End()
idx, err := t.backend.Validate(ctx, key, values...)
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
} else {
span.SetAttributes(attribute.Int("idx", idx))
}
return idx, err
}
// traceAttributes is a helper to build the trace attributes.
func (t *tracedBackend) traceAttributes(key string) trace.SpanStartEventOption {
return trace.WithAttributes(attribute.String("namespace", t.namespace), attribute.String("key", key))
}