Skip to content

Commit

Permalink
add xtel/exporters sub-module
Browse files Browse the repository at this point in the history
  • Loading branch information
ajatprabha committed Sep 12, 2023
1 parent c6284b2 commit 8f102c1
Show file tree
Hide file tree
Showing 9 changed files with 767 additions and 0 deletions.
2 changes: 2 additions & 0 deletions xtel/exporter/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package exporter contains basic exporters for xtel like stdout and otlp.
package exporter
22 changes: 22 additions & 0 deletions xtel/exporter/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package exporter_test

import (
"fmt"

"github.com/gojekfarm/xtools/xtel"
"github.com/gojekfarm/xtools/xtel/exporter"
)

func ExampleNewOTLP() {
_, err := xtel.NewProvider("eg-service", exporter.NewOTLP(exporter.WithTracesExporterInsecure))
if err != nil {
fmt.Printf("failed exporting traces to exporter: %s\n", err)
}
}

func ExampleNewSTDOut() {
_, err := xtel.NewProvider("eg-service", exporter.NewSTDOut(exporter.STDOutOptions{PrettyPrint: true}))
if err != nil {
fmt.Printf("failed printing traces to terminal: %s\n", err)
}
}
41 changes: 41 additions & 0 deletions xtel/exporter/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module github.com/gojekfarm/xtools/xtel/exporter

go 1.19

require (
github.com/gojekfarm/xtools/xtel v0.0.0-20230911104033-e5e7b07b8c02
github.com/stretchr/testify v1.8.4
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0
go.opentelemetry.io/otel/sdk v1.17.0
)

require (
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.43.0 // indirect
go.opentelemetry.io/otel v1.17.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.17.0 // indirect
go.opentelemetry.io/otel/trace v1.17.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
google.golang.org/grpc v1.55.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace github.com/gojekfarm/xtools/xtel => ../
463 changes: 463 additions & 0 deletions xtel/exporter/go.sum

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions xtel/exporter/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package exporter

import (
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
)

// Option defines the implementation of the configurations.
type Option interface{ apply(*config) }

const defaultExporterEndpoint = "127.0.0.1:4317"

type config struct {
mode Mode
exporterEndpoint string
tracesExporterEndpointInsecure bool
headers map[string]string
}

func newConfig(opts ...Option) *config {
c := &config{
headers: make(map[string]string),
exporterEndpoint: defaultExporterEndpoint,
}

for _, opt := range opts {
opt.apply(c)
}

return c
}

func (c *config) grpcOptions() []otlptracegrpc.Option {
res := []otlptracegrpc.Option{
otlptracegrpc.WithEndpoint(c.exporterEndpoint),
otlptracegrpc.WithHeaders(c.headers),
}

if c.tracesExporterEndpointInsecure {
res = append(res, otlptracegrpc.WithInsecure())
}

return res
}

func (c *config) httpOptions() []otlptracehttp.Option {
res := []otlptracehttp.Option{
otlptracehttp.WithEndpoint(c.exporterEndpoint),
otlptracehttp.WithHeaders(c.headers),
}

if c.tracesExporterEndpointInsecure {
res = append(res, otlptracehttp.WithInsecure())
}

return res
}
66 changes: 66 additions & 0 deletions xtel/exporter/otlp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package exporter

import (
"context"

"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/sdk/trace"

"github.com/gojekfarm/xtools/xtel"
)

// Mode is the used to control the export configuration of the otlptrace package exporters.
type Mode int

const (
// GRPC is the default exporters configurations for the Exporter.
GRPC Mode = iota
// HTTP can set as the configuration for the Exporter.
HTTP
)

// WithTracesExporterEndpoint configures the endpoint for sending traces via OTLP.
func WithTracesExporterEndpoint(url string) Option {
return optionFunc(func(c *config) { c.exporterEndpoint = url })
}

// WithTracesExporterInsecure permits connecting to the
// trace endpoint without a certificate.
var WithTracesExporterInsecure = &insecure{}

// NewOTLP returns a new exporter and starts it. It configs the new exporter with the given Options.
func NewOTLP(opts ...Option) xtel.ProviderOption {
return xtel.WithExporter(func() (trace.SpanExporter, error) {
cfg := newConfig(opts...)

var client otlptrace.Client
switch cfg.mode {
case GRPC:
client = otlptracegrpc.NewClient(cfg.grpcOptions()...)
case HTTP:
client = otlptracehttp.NewClient(cfg.httpOptions()...)
}

traceExporter, err := newTraceExporter(context.Background(), client)
if err != nil {
return nil, err
}

return traceExporter, nil
})
}

var newTraceExporter = otlptrace.New

func (m Mode) apply(c *config) { c.mode = m }

type insecure struct {
}

func (i *insecure) apply(c *config) { c.tracesExporterEndpointInsecure = true }

type optionFunc func(*config)

func (f optionFunc) apply(c *config) { f(c) }
73 changes: 73 additions & 0 deletions xtel/exporter/otlp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package exporter

import (
"context"
"errors"
"testing"

"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"

"github.com/gojekfarm/xtools/xtel"
)

func TestNewOTLP(t *testing.T) {
tests := []struct {
name string
option []Option
}{
{
name: "Default",
option: []Option{WithTracesExporterInsecure},
},
{
name: "HTTP",
option: []Option{HTTP, WithTracesExporterInsecure},
},
{
name: "Without Insecure Transport Credentials",
option: []Option{HTTP},
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
p, err := xtel.NewProvider("test", NewOTLP(tc.option...))
assert.NoError(t, err)
assert.NotNil(t, p)
})
}
}

func TestDefaultConfig(t *testing.T) {
cfg := newConfig()
expected := &config{exporterEndpoint: defaultExporterEndpoint, headers: map[string]string{}}

assert.Equal(t, expected, cfg)
}

func TestNewTraceExporter(t *testing.T) {
newTraceExporter = func(ctx context.Context, client otlptrace.Client) (*otlptrace.Exporter, error) {
return nil, errors.New("context already closed")
}
defer func() { newTraceExporter = otlptrace.New }()

p, err := xtel.NewProvider("test-service", NewOTLP())
assert.Error(t, err)
assert.Nil(t, p)
}

func TestConfigurationOverrides(t *testing.T) {
conf := newConfig(
WithTracesExporterEndpoint("override-satellite-url"),
WithTracesExporterInsecure,
)
emptyconfig := newConfig()
assert.NotNil(t, emptyconfig)
expected := &config{
exporterEndpoint: "override-satellite-url",
tracesExporterEndpointInsecure: true,
headers: map[string]string{},
}
assert.Equal(t, expected, conf)
}
28 changes: 28 additions & 0 deletions xtel/exporter/stdout.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package exporter

import (
"os"

"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/sdk/trace"

"github.com/gojekfarm/xtools/xtel"
)

// STDOutOptions handles the configuration of STDOUT output. It handles the PrettyPrint parameter of the application.
type STDOutOptions struct {
PrettyPrint bool
}

// NewSTDOut exports and writes exported tracing telemetry information in JSON for the given STDOutOptions.
func NewSTDOut(opts STDOutOptions) xtel.ProviderOption {
return xtel.WithExporter(func() (trace.SpanExporter, error) {
o := []stdouttrace.Option{stdouttrace.WithWriter(os.Stdout)}

if opts.PrettyPrint {
o = append(o, stdouttrace.WithPrettyPrint())
}

return stdouttrace.New(o...)
})
}
15 changes: 15 additions & 0 deletions xtel/exporter/stdout_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package exporter

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/gojekfarm/xtools/xtel"
)

func TestNewSTDOut(t *testing.T) {
p, err := xtel.NewProvider("test-service", NewSTDOut(STDOutOptions{PrettyPrint: true}))
assert.NoError(t, err)
assert.NotNil(t, p)
}

0 comments on commit 8f102c1

Please sign in to comment.