Skip to content

Commit

Permalink
opentelemetry collector exporter
Browse files Browse the repository at this point in the history
- missing load test
- missing resources
  • Loading branch information
rghetia committed Feb 27, 2020
1 parent 29cd0c0 commit f7c392e
Show file tree
Hide file tree
Showing 13 changed files with 1,603 additions and 5 deletions.
26 changes: 21 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ ALL_DOCS := $(shell find . -name '*.md' -type f | sort)
ALL_GO_MOD_DIRS := $(filter-out $(TOOLS_MOD_DIR), $(shell find . -type f -name 'go.mod' -exec dirname {} \; | sort))
ALL_COVERAGE_MOD_DIRS := $(shell find . -type f -name 'go.mod' -exec dirname {} \; | egrep -v '^./example|^$(TOOLS_MOD_DIR)' | sort)


# Mac OS Catalina 10.5.x doesn't support 386. Hence skip 386 test
SKIP_386_TEST = false
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
SW_VERS := $(shell sw_vers -productVersion)
ifeq ($(shell echo $(SW_VERS) | egrep '^(10.1[5-9]|1[1-9]|[2-9])'), $(SW_VERS))
SKIP_386_TEST = true
endif
endif


GOTEST_MIN = go test -v -timeout 30s
GOTEST = $(GOTEST_MIN) -race
GOTEST_WITH_COVERAGE = $(GOTEST) -coverprofile=coverage.txt -covermode=atomic
Expand Down Expand Up @@ -73,11 +85,15 @@ test:

.PHONY: test-386
test-386:
set -e; for dir in $(ALL_GO_MOD_DIRS); do \
echo "go test ./... GOARCH 386 in $${dir}"; \
(cd "$${dir}" && \
GOARCH=386 $(GOTEST_MIN) ./...); \
done
if [ $(SKIP_386_TEST) = true ] ; then \
echo "skippin the test for GOARCH 386 as it is not supported on the current OS"; \
else \
set -e; for dir in $(ALL_GO_MOD_DIRS); do \
echo "go test ./... GOARCH 386 in $${dir}"; \
(cd "$${dir}" && \
GOARCH=386 $(GOTEST_MIN) ./...); \
done; \
fi

.PHONY: examples
examples:
Expand Down
24 changes: 24 additions & 0 deletions exporter/trace/otelcol/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# OpenTelemetry Collector Go Exporter

[![GoDoc][godoc-image]][godoc-url]


This repository contains the Go implementation of the OpenTelemetry Collector Exporter.
OpenTelemetry Agent is a deamon process running in a VM that can retrieve spans/stats/metrics from
OpenTelemetry Library and export them to other backends.

## Installation

```bash
$ go get -u go.opentelemetry.io/otel/exporter/otelcol
```

## Usage

```go
package main
// TBD
```

[godoc-url]: https://godoc.org/go.opentelemetry.io/otel/exporter/otelcol

113 changes: 113 additions & 0 deletions exporter/trace/otelcol/connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright 2020, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package otelcol

import (
"math/rand"
"sync/atomic"
"time"
"unsafe"
)

func (e *Exporter) lastConnectError() error {
errPtr := (*error)(atomic.LoadPointer(&e.lastConnectErrPtr))
if errPtr == nil {
return nil
}
return *errPtr
}

func (e *Exporter) saveLastConnectError(err error) {
var errPtr *error
if err != nil {
errPtr = &err
}
atomic.StorePointer(&e.lastConnectErrPtr, unsafe.Pointer(errPtr))
}

func (e *Exporter) setStateDisconnected(err error) {
e.saveLastConnectError(err)
select {
case e.disconnectedCh <- true:
default:
}
}

func (e *Exporter) setStateConnected() {
e.saveLastConnectError(nil)
}

func (e *Exporter) connected() bool {
return e.lastConnectError() == nil
}

const defaultConnReattemptPeriod = 10 * time.Second

func (e *Exporter) indefiniteBackgroundConnection() error {
defer func() {
e.backgroundConnectionDoneCh <- true
}()

connReattemptPeriod := e.reconnectionPeriod
if connReattemptPeriod <= 0 {
connReattemptPeriod = defaultConnReattemptPeriod
}

// No strong seeding required, nano time can
// already help with pseudo uniqueness.
rng := rand.New(rand.NewSource(time.Now().UnixNano() + rand.Int63n(1024)))

// maxJitter: 1 + (70% of the connectionReattemptPeriod)
maxJitter := int64(1 + 0.7*float64(connReattemptPeriod))

for {
// Otherwise these will be the normal scenarios to enable
// reconnections if we trip out.
// 1. If we've stopped, return entirely
// 2. Otherwise block until we are disconnected, and
// then retry connecting
select {
case <-e.stopCh:
return errStopped

case <-e.disconnectedCh:
// Normal scenario that we'll wait for
}

if err := e.connect(); err == nil {
e.setStateConnected()
} else {
e.setStateDisconnected(err)
}

// Apply some jitter to avoid lockstep retrials of other
// collector-exporters. Lockstep retrials could result in an
// innocent DDOS, by clogging the machine's resources and network.
jitter := time.Duration(rng.Int63n(maxJitter))
select {
case <-e.stopCh:
return errStopped
case <-time.After(connReattemptPeriod + jitter):
}
}
}

func (e *Exporter) connect() error {
cc, err := e.dialToCollector()
if err != nil {
return err
}
return e.enableConnections(cc)
}
16 changes: 16 additions & 0 deletions exporter/trace/otelcol/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2019, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package otelcol contains an OpenTelemetry tracing exporter for OpenTelemetry Collector.
package otelcol // import "go.opentelemetry.io/otel/exporter/trace/otelcol"
103 changes: 103 additions & 0 deletions exporter/trace/otelcol/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2020, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package otelcol_test

import (
"context"
"fmt"
"log"
"time"

"google.golang.org/grpc/credentials"

"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/exporter/trace/otelcol"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

func Example_insecure() {
exp, err := otelcol.NewExporter(otelcol.WithInsecure(), otelcol.WithServiceName("engine"))
if err != nil {
log.Fatalf("Failed to create the collector exporter: %v", err)
}
defer func() {
_ = exp.Stop()
}()

tp, _ := sdktrace.NewProvider(
sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
sdktrace.WithBatcher(exp, // add following two options to ensure flush
sdktrace.WithScheduleDelayMillis(5),
sdktrace.WithMaxExportBatchSize(10),
))
if err != nil {
log.Fatalf("error creating trace provider: %v\n", err)
}

global.SetTraceProvider(tp)

tracer := global.TraceProvider().Tracer("test-tracer")

// Then use the OpenTelemetry tracing library, like we normally would.
ctx, span := tracer.Start(context.Background(), "CollectorExporter-Example")
defer span.End()

for i := 0; i < 10; i++ {
_, iSpan := tracer.Start(ctx, fmt.Sprintf("Sample-%d", i))
<-time.After(6 * time.Millisecond)
iSpan.End()
}
}

func Example_withTLS() {
// Please take at look at https://godoc.org/google.golang.org/grpc/credentials#TransportCredentials
// for ways on how to initialize gRPC TransportCredentials.
creds, err := credentials.NewClientTLSFromFile("my-cert.pem", "")
if err != nil {
log.Fatalf("failed to create gRPC client TLS credentials: %v", err)
}

exp, err := otelcol.NewExporter(otelcol.WithTLSCredentials(creds), otelcol.WithServiceName("engine"))
if err != nil {
log.Fatalf("failed to create the collector exporter: %v", err)
}
defer func() {
_ = exp.Stop()
}()

tp, err := sdktrace.NewProvider(
sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
sdktrace.WithBatcher(exp, // add following two options to ensure flush
sdktrace.WithScheduleDelayMillis(5),
sdktrace.WithMaxExportBatchSize(10),
))
if err != nil {
log.Fatalf("error creating trace provider: %v\n", err)
}

global.SetTraceProvider(tp)

tracer := global.TraceProvider().Tracer("test-tracer")

// Then use the OpenTelemetry tracing library, like we normally would.
ctx, span := tracer.Start(context.Background(), "Securely-Talking-To-Collector-Span")
defer span.End()

for i := 0; i < 10; i++ {
_, iSpan := tracer.Start(ctx, fmt.Sprintf("Sample-%d", i))
<-time.After(6 * time.Millisecond)
iSpan.End()
}
}
17 changes: 17 additions & 0 deletions exporter/trace/otelcol/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module go.opentelemetry.io/otel/exporter/trace/otelcol

replace go.opentelemetry.io/otel => ../../..

require (
github.com/golang/protobuf v1.3.2
github.com/google/go-cmp v0.3.1
github.com/open-telemetry/opentelemetry-proto v0.0.0-20200219184922-5e1d5bc66d5a
github.com/stretchr/testify v1.4.0
go.opentelemetry.io/otel v0.0.0-00010101000000-000000000000
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 // indirect
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 // indirect
golang.org/x/text v0.3.2 // indirect
google.golang.org/grpc v1.27.1
)

go 1.13

0 comments on commit f7c392e

Please sign in to comment.