package loop import ( "context" "git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/trace" ) // span starts a named span of the given kind when a Tracer is configured, else // returns a nil no-op span. The returned context carries the span as the current // one so nested spans chain as children. When a FlowPublisher is configured the // span's session (threaded via ctx) is stamped as a prop and a running placeholder // node is published immediately, so the flow graph shows work in flight. func (l *Loop) span(ctx context.Context, name string, kind trace.SpanKind) (context.Context, *trace.Span) { if l.tracer == nil { return ctx, nil } sctx, sp := l.tracer.StartSpan(ctx, name, kind) if sid := loopSession(ctx); sid != "" { _ = sp.SetProp("session", sid) if l.flow != nil { l.flow.SpanStarted(sid, sp) } } return sctx, sp } // finishSpan closes a span with the given status, ignoring a nil span. After the // span closes (immutable) the finished record is folded into the flow graph and // published, flipping the node to its final status. func (l *Loop) finishSpan(sp *trace.Span, status trace.SpanStatus) { if sp == nil { return } sp.Finish(status) if l.flow != nil { if sid, ok := sp.Props["session"].(string); ok && sid != "" { l.flow.SpanFinished(sid, sp) } } } // spanProp attaches a structured property to a span, ignoring a nil span and any // mutation-after-close error. func (l *Loop) spanProp(sp *trace.Span, key string, value any) { if sp == nil { return } _ = sp.SetProp(key, value) }