Skip to content

Commit

Permalink
Encode JSON objects to stdout one by one; not wrapped in lists
Browse files Browse the repository at this point in the history
  • Loading branch information
luxas committed Aug 20, 2021
1 parent e3dcf3b commit ac38b09
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 170 deletions.
38 changes: 0 additions & 38 deletions exporters/stdout/stdouttrace/exporter.go

This file was deleted.

58 changes: 36 additions & 22 deletions exporters/stdout/stdouttrace/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package stdouttrace // import "go.opentelemetry.io/otel/exporters/stdout/stdoutt
import (
"context"
"encoding/json"
"fmt"
"sync"
"time"

Expand All @@ -27,16 +26,37 @@ import (

var zeroTime time.Time

var _ trace.SpanExporter = &Exporter{}

// New creates an Exporter with the passed options.
func New(options ...Option) (*Exporter, error) {
cfg, err := newConfig(options...)
if err != nil {
return nil, err
}

enc := json.NewEncoder(cfg.Writer)
if cfg.PrettyPrint {
enc.SetIndent("", "\t")
}

return &Exporter{
encoder: enc,
timestamps: cfg.Timestamps,
}, nil
}

// Exporter is an implementation of trace.SpanSyncer that writes spans to stdout.
type traceExporter struct {
config config
type Exporter struct {
encoder *json.Encoder
timestamps bool

stoppedMu sync.RWMutex
stopped bool
}

// ExportSpans writes spans in json format to stdout.
func (e *traceExporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan) error {
func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan) error {
e.stoppedMu.RLock()
stopped := e.stopped
e.stoppedMu.RUnlock()
Expand All @@ -47,29 +67,31 @@ func (e *traceExporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlyS
if len(spans) == 0 {
return nil
}

stubs := tracetest.SpanStubsFromReadOnlySpans(spans)
if !e.config.Timestamps {
for i := range stubs {
stub := &stubs[i]

for i := range stubs {
stub := &stubs[i]
// Remove timestamps
if !e.timestamps {
stub.StartTime = zeroTime
stub.EndTime = zeroTime
for j := range stub.Events {
ev := &stub.Events[j]
ev.Time = zeroTime
}
}
}

out, err := e.marshal(stubs)
if err != nil {
return err
// Encode span stubs, one by one
if err := e.encoder.Encode(stub); err != nil {
return err
}
}
_, err = fmt.Fprintln(e.config.Writer, string(out))
return err
return nil
}

// Shutdown is called to stop the exporter, it preforms no action.
func (e *traceExporter) Shutdown(ctx context.Context) error {
func (e *Exporter) Shutdown(ctx context.Context) error {
e.stoppedMu.Lock()
e.stopped = true
e.stoppedMu.Unlock()
Expand All @@ -81,11 +103,3 @@ func (e *traceExporter) Shutdown(ctx context.Context) error {
}
return nil
}

// marshal v with approriate indentation.
func (e *traceExporter) marshal(v interface{}) ([]byte, error) {
if e.config.PrettyPrint {
return json.MarshalIndent(v, "", "\t")
}
return json.Marshal(v)
}
217 changes: 107 additions & 110 deletions exporters/stdout/stdouttrace/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,30 @@ func TestExporter_ExportSpan(t *testing.T) {
doubleValue := 123.456
resource := resource.NewSchemaless(attribute.String("rk1", "rv11"))

ro := tracetest.SpanStubs{
{
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: traceID,
SpanID: spanID,
TraceState: traceState,
}),
Name: "/foo",
StartTime: now,
EndTime: now,
Attributes: []attribute.KeyValue{
attribute.String("key", keyValue),
attribute.Float64("double", doubleValue),
},
Events: []tracesdk.Event{
{Name: "foo", Attributes: []attribute.KeyValue{attribute.String("key", keyValue)}, Time: now},
{Name: "bar", Attributes: []attribute.KeyValue{attribute.Float64("double", doubleValue)}, Time: now},
},
SpanKind: trace.SpanKindInternal,
Status: tracesdk.Status{
Code: codes.Error,
Description: "interesting",
},
Resource: resource,
ss := tracetest.SpanStub{
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: traceID,
SpanID: spanID,
TraceState: traceState,
}),
Name: "/foo",
StartTime: now,
EndTime: now,
Attributes: []attribute.KeyValue{
attribute.String("key", keyValue),
attribute.Float64("double", doubleValue),
},
Events: []tracesdk.Event{
{Name: "foo", Attributes: []attribute.KeyValue{attribute.String("key", keyValue)}, Time: now},
{Name: "bar", Attributes: []attribute.KeyValue{attribute.Float64("double", doubleValue)}, Time: now},
},
SpanKind: trace.SpanKindInternal,
Status: tracesdk.Status{
Code: codes.Error,
Description: "interesting",
},
}.Snapshots()
Resource: resource,
}

tests := []struct {
opts []stdouttrace.Option
Expand All @@ -91,107 +89,106 @@ func TestExporter_ExportSpan(t *testing.T) {
ex, err := stdouttrace.New(append(tt.opts, stdouttrace.WithWriter(&b))...)
require.Nil(t, err)

err = ex.ExportSpans(ctx, ro)
err = ex.ExportSpans(ctx, tracetest.SpanStubs{ss, ss}.Snapshots())
require.Nil(t, err)

got := b.String()
assert.Equal(t, expectedJSON(tt.expectNow), got)
wantone := expectedJSON(tt.expectNow)
assert.Equal(t, wantone+wantone, got)
}
}

func expectedJSON(now time.Time) string {
serializedNow, _ := json.Marshal(now)
return `[
{
"Name": "/foo",
"SpanContext": {
"TraceID": "0102030405060708090a0b0c0d0e0f10",
"SpanID": "0102030405060708",
"TraceFlags": "00",
"TraceState": "key=val",
"Remote": false
},
"Parent": {
"TraceID": "00000000000000000000000000000000",
"SpanID": "0000000000000000",
"TraceFlags": "00",
"TraceState": "",
"Remote": false
return `{
"Name": "/foo",
"SpanContext": {
"TraceID": "0102030405060708090a0b0c0d0e0f10",
"SpanID": "0102030405060708",
"TraceFlags": "00",
"TraceState": "key=val",
"Remote": false
},
"Parent": {
"TraceID": "00000000000000000000000000000000",
"SpanID": "0000000000000000",
"TraceFlags": "00",
"TraceState": "",
"Remote": false
},
"SpanKind": 1,
"StartTime": ` + string(serializedNow) + `,
"EndTime": ` + string(serializedNow) + `,
"Attributes": [
{
"Key": "key",
"Value": {
"Type": "STRING",
"Value": "value"
}
},
"SpanKind": 1,
"StartTime": ` + string(serializedNow) + `,
"EndTime": ` + string(serializedNow) + `,
"Attributes": [
{
"Key": "key",
"Value": {
"Type": "STRING",
"Value": "value"
}
},
{
"Key": "double",
"Value": {
"Type": "FLOAT64",
"Value": 123.456
}
{
"Key": "double",
"Value": {
"Type": "FLOAT64",
"Value": 123.456
}
],
"Events": [
{
"Name": "foo",
"Attributes": [
{
"Key": "key",
"Value": {
"Type": "STRING",
"Value": "value"
}
}
],
"DroppedAttributeCount": 0,
"Time": ` + string(serializedNow) + `
},
{
"Name": "bar",
"Attributes": [
{
"Key": "double",
"Value": {
"Type": "FLOAT64",
"Value": 123.456
}
}
],
"Events": [
{
"Name": "foo",
"Attributes": [
{
"Key": "key",
"Value": {
"Type": "STRING",
"Value": "value"
}
],
"DroppedAttributeCount": 0,
"Time": ` + string(serializedNow) + `
}
],
"Links": null,
"Status": {
"Code": "Error",
"Description": "interesting"
}
],
"DroppedAttributeCount": 0,
"Time": ` + string(serializedNow) + `
},
"DroppedAttributes": 0,
"DroppedEvents": 0,
"DroppedLinks": 0,
"ChildSpanCount": 0,
"Resource": [
{
"Key": "rk1",
"Value": {
"Type": "STRING",
"Value": "rv11"
{
"Name": "bar",
"Attributes": [
{
"Key": "double",
"Value": {
"Type": "FLOAT64",
"Value": 123.456
}
}
],
"DroppedAttributeCount": 0,
"Time": ` + string(serializedNow) + `
}
],
"Links": null,
"Status": {
"Code": "Error",
"Description": "interesting"
},
"DroppedAttributes": 0,
"DroppedEvents": 0,
"DroppedLinks": 0,
"ChildSpanCount": 0,
"Resource": [
{
"Key": "rk1",
"Value": {
"Type": "STRING",
"Value": "rv11"
}
],
"InstrumentationLibrary": {
"Name": "",
"Version": "",
"SchemaURL": ""
}
],
"InstrumentationLibrary": {
"Name": "",
"Version": "",
"SchemaURL": ""
}
]
}
`
}

Expand Down

0 comments on commit ac38b09

Please sign in to comment.