Skip to content

Commit 995309a

Browse files
sengjeasengjea
andauthored
Add more span attributes for tracing (#4)
ConditionalTasks that do not meet the conditions for execution are opaque and hard to debug. This change adds spans attributes in both the conditional tasks and regular tasks to make it easier to track down issues with the graph execution. Tasks with Absent key bindings will be attached to the spans Conditional Tasks with failed conditionals will have their keys reported --------- Co-authored-by: sengjea <sengjea@thoughtmachine.net>
1 parent 9915cca commit 995309a

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

graph.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
set "github.com/deckarep/golang-set/v2"
15+
"go.opentelemetry.io/otel/attribute"
1516
"go.opentelemetry.io/otel/trace"
1617
"go.opentelemetry.io/otel/trace/noop"
1718
"golang.org/x/sync/errgroup"
@@ -123,6 +124,10 @@ type graphNode struct {
123124
tracer trace.Tracer
124125
}
125126

127+
const (
128+
traceTaskgraphAbsentKeysPrefix = "taskgraph.absent_keys."
129+
)
130+
126131
// Execute the task against the binder provided in the runState.
127132
//
128133
// This assumes that all of the task's dependencies have been bound; it is the responsibility of the
@@ -169,6 +174,14 @@ func (gn *graphNode) execute(ctx context.Context, rs *runState) (err error) {
169174
if !providesSet.Contains(binding.ID()) {
170175
extra = append(extra, binding.ID().String())
171176
}
177+
if binding.Status() == Absent {
178+
span.SetAttributes(
179+
attribute.String(
180+
traceTaskgraphAbsentKeysPrefix+binding.ID().String(),
181+
fmt.Sprintf("%v", binding.Error()),
182+
),
183+
)
184+
}
172185
}
173186
if len(extra) > 0 || len(missing) > 0 {
174187
return wrapStackErrorf(

task.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55

66
set "github.com/deckarep/golang-set/v2"
7+
"go.opentelemetry.io/otel/attribute"
8+
"go.opentelemetry.io/otel/trace"
79
)
810

911
// A TaskSet defines a nestable collection of tasks. A Task fulfils the TaskSet interface, acting as
@@ -192,6 +194,8 @@ type Condition interface {
192194
Evaluate(ctx context.Context, b Binder) (bool, error)
193195
// Deps should return the IDs of the keys used by the Evaluate function.
194196
Deps() []ID
197+
// Keys returns the keys in the conditional
198+
Keys() []ReadOnlyKey[bool]
195199
}
196200

197201
// ConditionAnd evaluates to true if and only if all of the keys it contains are bound to true.
@@ -220,6 +224,11 @@ func (ca ConditionAnd) Deps() []ID {
220224
return deps
221225
}
222226

227+
// Keys returns the keys in the conditional
228+
func (ca ConditionAnd) Keys() []ReadOnlyKey[bool] {
229+
return ca
230+
}
231+
223232
// ConditionOr evaluates to true if any of the keys it contains are bound to true.
224233
type ConditionOr []ReadOnlyKey[bool]
225234

@@ -246,6 +255,11 @@ func (co ConditionOr) Deps() []ID {
246255
return deps
247256
}
248257

258+
// Keys returns the keys in the conditional
259+
func (co ConditionOr) Keys() []ReadOnlyKey[bool] {
260+
return co
261+
}
262+
249263
// Conditional wraps tasks such that they are only run if given Condition evaluates to true. If it
250264
// evaluates to false, the bindings in DefaultBindings are used, with any missing keys provided by
251265
// the wrapped tasks bound as absent.
@@ -270,6 +284,10 @@ func (c Conditional) Locate() Conditional {
270284
return c
271285
}
272286

287+
const (
288+
traceTaskgraphConditionalPrefix = "taskgraph.conditional."
289+
)
290+
273291
// Tasks satisfies TaskSet.Tasks.
274292
func (c Conditional) Tasks() []Task {
275293
defaultBindingsMap := map[ID]Binding{}
@@ -291,6 +309,25 @@ func (c Conditional) Tasks() []Task {
291309
if err != nil {
292310
return nil, err
293311
}
312+
span := trace.SpanFromContext(ctx)
313+
span.SetAttributes(
314+
attribute.Bool(traceTaskgraphConditionalPrefix+"execute", shouldExecute),
315+
)
316+
for _, k := range c.Condition.Keys() {
317+
v, err := k.Get(b)
318+
if err != nil {
319+
span.SetAttributes(
320+
attribute.String(
321+
traceTaskgraphConditionalPrefix+k.ID().String(),
322+
err.Error(),
323+
),
324+
)
325+
} else {
326+
span.SetAttributes(
327+
attribute.Bool(traceTaskgraphConditionalPrefix+k.ID().String(), v),
328+
)
329+
}
330+
}
294331
if shouldExecute {
295332
return t.Execute(ctx, b)
296333
}

0 commit comments

Comments
 (0)