feat(trace): 深追踪(Span 生命周期/父子链/JSONL recorder,支持 llm/tool/state 等类别)

This commit is contained in:
Aska committed 2026-09-06 05:06:41 +08:00
1 parent 011d25a53d
commit e33b005612
4 files changed
+661

No files matched your search

+41
View File
@@ -0,0 +1,41 @@
package trace
import (
"encoding/json"
"fmt"
"io"
"sync"
)
// Writer persists a completed span. Implementations must be safe for concurrent
// use, as WriteSpan may be called from several goroutines. A Writer such as
// *JSONRecorder provides structured local logging for the M9 panel.
type Writer interface {
// WriteSpan persists a single completed span and returns any encoding or
// write error.
WriteSpan(rec SpanRecord) error
}
// JSONRecorder writes each completed span as one line of JSON (JSONL) to an
// underlying io.Writer. It is safe for concurrent use.
type JSONRecorder struct {
mu sync.Mutex
enc *json.Encoder
}
// NewJSONRecorder builds a JSONRecorder that appends one JSON object per span to
// out.
func NewJSONRecorder(out io.Writer) *JSONRecorder {
return &JSONRecorder{enc: json.NewEncoder(out)}
}
// WriteSpan encodes rec as JSON followed by a newline. Concurrent calls are
// serialized so a single span object is never interleaved with another.
func (r *JSONRecorder) WriteSpan(rec SpanRecord) error {
r.mu.Lock()
defer r.mu.Unlock()
if err := r.enc.Encode(rec); err != nil {
return fmt.Errorf("trace: encode span %q: %w", rec.ID, err)
}
return nil
}