42 lines
1.2 KiB
Go
42 lines
1.2 KiB
Go
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
|
|
}
|