Skip to content

Commit fa7d053

Browse files
Steven Karisrghetia
authored andcommitted
Add stdout trace exporter (#153)
* Add stdout trace exporter (#134) * Update go.mod and go.sum * Do not use assert in tests
1 parent 0eb7332 commit fa7d053

File tree

7 files changed

+189
-32
lines changed

7 files changed

+189
-32
lines changed

example/README.md

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,32 +28,20 @@ Example uses
2828
GO111MODULE="" go get -d go.opentelemetry.io
2929
```
3030

31-
#### 2 Start All-in-one Jaeger
32-
33-
```
34-
docker run -d --name jaeger \
35-
-p 16686:16686 \
36-
-p 14268:14268 \
37-
jaegertracing/all-in-one:1.8
38-
```
39-
40-
#### 3 Start Server
31+
#### 2 Start Server
4132
```
4233
cd $GOPATH/src/go.opentelemetry.io/example/http/
4334
go run ./server/server.go
4435
```
4536

46-
#### 4 Start Client
37+
#### 3 Start Client
4738
```
4839
cd $GOPATH/src/go.opentelemetry.io/example/http/
4940
go run ./client/client.go
5041
```
5142

52-
#### 5 Check traces on Jaeger UI
53-
54-
Visit http://localhost:16686 with a web browser
55-
Click on 'Find' to see traces.
43+
#### 4 Check traces in stdout
5644

57-
[Sample Snapshot](http/images/JaegarTraceExample.png)
45+
The spans should be visible in stdout in the order that they were exported.
5846

5947

example/http/client/client.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
"go.opentelemetry.io/api/key"
2929
"go.opentelemetry.io/api/tag"
3030
"go.opentelemetry.io/api/trace"
31-
"go.opentelemetry.io/exporter/trace/jaeger"
31+
"go.opentelemetry.io/exporter/trace/stdout"
3232
"go.opentelemetry.io/plugin/httptrace"
3333
sdktrace "go.opentelemetry.io/sdk/trace"
3434
)
@@ -37,14 +37,9 @@ func initTracer() {
3737
// Register SDK as trace provider.
3838
sdktrace.Register()
3939

40-
// Create Jaeger exporter to be able to retrieve
40+
// Create stdout exporter to be able to retrieve
4141
// the collected spans.
42-
exporter, err := jaeger.NewExporter(jaeger.Options{
43-
CollectorEndpoint: "http://localhost:14268/api/traces",
44-
Process: jaeger.Process{
45-
ServiceName: "trace-demo",
46-
},
47-
})
42+
exporter, err := stdout.NewExporter(stdout.Options{PrettyPrint: true})
4843
if err != nil {
4944
log.Fatal(err)
5045
}
@@ -94,5 +89,5 @@ func main() {
9489
fmt.Printf("Response Received: %s\n\n\n", body)
9590
fmt.Printf("Waiting for few seconds to export spans ...\n\n")
9691
time.Sleep(10 * time.Second)
97-
fmt.Printf("Check traces on http://localhost:16686\n")
92+
fmt.Printf("Inspect traces on stdout")
9893
}

example/http/go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
8484
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
8585
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
8686
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
87+
github.com/magiconair/properties v1.7.6 h1:U+1DqNen04MdEPgFiIwdOUiqZ8qPa37xgogX/sd3+54=
8788
github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
8889
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
8990
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=

example/http/server/server.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121

2222
"go.opentelemetry.io/api/tag"
2323
"go.opentelemetry.io/api/trace"
24-
"go.opentelemetry.io/exporter/trace/jaeger"
24+
"go.opentelemetry.io/exporter/trace/stdout"
2525
"go.opentelemetry.io/plugin/httptrace"
2626
sdktrace "go.opentelemetry.io/sdk/trace"
2727
)
@@ -31,12 +31,7 @@ func initTracer() {
3131

3232
// Create Jaeger exporter to be able to retrieve
3333
// the collected spans.
34-
exporter, err := jaeger.NewExporter(jaeger.Options{
35-
CollectorEndpoint: "http://localhost:14268/api/traces",
36-
Process: jaeger.Process{
37-
ServiceName: "trace-demo",
38-
},
39-
})
34+
exporter, err := stdout.NewExporter(stdout.Options{PrettyPrint: true})
4035
if err != nil {
4136
log.Fatal(err)
4237
}

exporter/trace/stdout/doc.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2019, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Package stdout contains an OpenTelemetry tracing exporter for writing to stdout.
16+
package stdout // import "go.opentelemetry.io/exporter/trace/stdout"

exporter/trace/stdout/stdout.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2019, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package stdout
16+
17+
import (
18+
"encoding/json"
19+
"io"
20+
"os"
21+
22+
"go.opentelemetry.io/sdk/trace"
23+
)
24+
25+
// Options are the options to be used when initializing a stdout exporter.
26+
type Options struct {
27+
// PrettyPrint will pretty the json representation of the span,
28+
// making it print "pretty". Default is false.
29+
PrettyPrint bool
30+
}
31+
32+
// Exporter is an implementation of trace.Exporter that writes spans to stdout.
33+
type Exporter struct {
34+
pretty bool
35+
outputWriter io.Writer
36+
}
37+
38+
func NewExporter(o Options) (*Exporter, error) {
39+
return &Exporter{
40+
pretty: o.PrettyPrint,
41+
outputWriter: os.Stdout,
42+
}, nil
43+
}
44+
45+
// ExportSpan writes a SpanData in json format to stdout.
46+
func (e *Exporter) ExportSpan(data *trace.SpanData) {
47+
var jsonSpan []byte
48+
var err error
49+
if e.pretty {
50+
jsonSpan, err = json.MarshalIndent(data, "", "\t")
51+
} else {
52+
jsonSpan, err = json.Marshal(data)
53+
}
54+
if err != nil {
55+
// ignore writer failures for now
56+
_, _ = e.outputWriter.Write([]byte("Error converting spanData to json: " + err.Error()))
57+
return
58+
}
59+
// ignore writer failures for now
60+
_, _ = e.outputWriter.Write(append(jsonSpan, byte('\n')))
61+
}

exporter/trace/stdout/stdout_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2019, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package stdout
16+
17+
import (
18+
"bytes"
19+
"encoding/json"
20+
"testing"
21+
"time"
22+
23+
"google.golang.org/grpc/codes"
24+
25+
"go.opentelemetry.io/api/core"
26+
"go.opentelemetry.io/sdk/trace"
27+
)
28+
29+
func TestExporter_ExportSpan(t *testing.T) {
30+
exporter, err := NewExporter(Options{})
31+
if err != nil {
32+
t.Errorf("Error constructing stdout exporter %s", err)
33+
}
34+
35+
// override output writer for testing
36+
var b bytes.Buffer
37+
exporter.outputWriter = &b
38+
39+
// setup test span
40+
now := time.Now()
41+
traceID := core.TraceID{High: 0x0102030405060708, Low: 0x090a0b0c0d0e0f10}
42+
spanID := uint64(0x0102030405060708)
43+
keyValue := "value"
44+
doubleValue := float64(123.456)
45+
46+
testSpan := &trace.SpanData{
47+
SpanContext: core.SpanContext{
48+
TraceID: traceID,
49+
SpanID: spanID,
50+
},
51+
Name: "/foo",
52+
StartTime: now,
53+
EndTime: now,
54+
Attributes: []core.KeyValue{
55+
{
56+
Key: core.Key{Name: "key"},
57+
Value: core.Value{Type: core.STRING, String: keyValue},
58+
},
59+
{
60+
Key: core.Key{Name: "double"},
61+
Value: core.Value{Type: core.FLOAT64, Float64: doubleValue},
62+
},
63+
},
64+
Status: codes.Unknown,
65+
}
66+
exporter.ExportSpan(testSpan)
67+
68+
expectedSerializedNow, _ := json.Marshal(now)
69+
70+
got := b.String()
71+
expectedOutput := `{"SpanContext":{` +
72+
`"TraceID":{"High":72623859790382856,"Low":651345242494996240},` +
73+
`"SpanID":72623859790382856,"TraceFlags":0},` +
74+
`"ParentSpanID":0,` +
75+
`"SpanKind":0,` +
76+
`"Name":"/foo",` +
77+
`"StartTime":` + string(expectedSerializedNow) + "," +
78+
`"EndTime":` + string(expectedSerializedNow) + "," +
79+
`"Attributes":[` +
80+
`{` +
81+
`"Key":{"Name":"key"},` +
82+
`"Value":{"Type":8,"Bool":false,"Int64":0,"Uint64":0,"Float64":0,"String":"value","Bytes":null}` +
83+
`},` +
84+
`{` +
85+
`"Key":{"Name":"double"},` +
86+
`"Value":{"Type":7,"Bool":false,"Int64":0,"Uint64":0,"Float64":123.456,"String":"","Bytes":null}` +
87+
`}` +
88+
`],` +
89+
`"MessageEvents":null,` +
90+
`"Links":null,` +
91+
`"Status":2,` +
92+
`"HasRemoteParent":false,` +
93+
`"DroppedAttributeCount":0,` +
94+
`"DroppedMessageEventCount":0,` +
95+
`"DroppedLinkCount":0,` +
96+
`"ChildSpanCount":0}` + "\n"
97+
98+
if got != expectedOutput {
99+
t.Errorf("Want: %v but got: %v", expectedOutput, got)
100+
}
101+
}

0 commit comments

Comments
 (0)