Skip to content

Commit

Permalink
Golang opentelemetry-go draft API (incomplete) (#9)
Browse files Browse the repository at this point in the history
* Work in progress from https://github.com/lightstep/opentelemetry-golang-prototype

* Renames

* Rename

* Finish rename

* Rename packages

* README
  • Loading branch information
jmacd authored and rghetia committed Jun 14, 2019
1 parent 1429272 commit e17f446
Show file tree
Hide file tree
Showing 43 changed files with 2,888 additions and 0 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
This is a prototype *intended to be modified* into the opentelemetry-go implementation. The `api` directory here should be used as a starting point to introduce a new OpenTelemetry exporter, wherease the existing `exporter/observer` streaming model should be help verify the api

To run the examples, first build the stderr tracer plugin (requires Linux or OS X):

```
(cd ./exporter/stdout/plugin && make)
(cd ./exporter/spanlog/plugin && make)
```

Then set the `OPENTELEMETRY_LIB` environment variable to the .so file in that directory, e.g.,

```
OPENTELEMETRY_LIB=./exporter/stderr/plugin/stderr.so go run ./example/server/server.go
```

and

```
OPENTELEMETRY_LIB=./exporter/spanlog/plugin/spanlog.so go run ./example/client/client.go
```
179 changes: 179 additions & 0 deletions api/core/core.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package core

import (
"context"
"fmt"

"github.com/open-telemetry/opentelemetry-go/api/unit"
)

type (
ScopeID struct {
EventID
SpanContext
}

SpanContext struct {
TraceIDHigh uint64
TraceIDLow uint64
SpanID uint64
}

EventID uint64

BaseMeasure interface {
Name() string
Description() string
Unit() unit.Unit

DefinitionID() EventID
}

Measure interface {
BaseMeasure

M(float64) Measurement
V(float64) KeyValue
}

Measurement struct {
// NOTE: If we add a ScopeID field this can carry
// pre-aggregated measures via the stats.Record API.
Measure Measure
Value float64
ScopeID ScopeID
}

Key interface {
BaseMeasure

Value(ctx context.Context) KeyValue

Bool(v bool) KeyValue

Int(v int) KeyValue
Int32(v int32) KeyValue
Int64(v int64) KeyValue

Uint(v uint) KeyValue
Uint32(v uint32) KeyValue
Uint64(v uint64) KeyValue

Float32(v float32) KeyValue
Float64(v float64) KeyValue

String(v string) KeyValue
Bytes(v []byte) KeyValue
}

KeyValue struct {
Key Key
Value Value
}

ValueType int

Value struct {
Type ValueType
Bool bool
Int64 int64
Uint64 uint64
Float64 float64
String string
Bytes []byte

// TODO Lazy value type?
}

MutatorOp int

Mutator struct {
MutatorOp
KeyValue
MeasureMetadata
}

MeasureMetadata struct {
MaxHops int // -1 == infinite, 0 == do not propagate

// TODO time to live?
}
)

const (
INVALID ValueType = iota
BOOL
INT32
INT64
UINT32
UINT64
FLOAT32
FLOAT64
STRING
BYTES

INSERT MutatorOp = iota
UPDATE
UPSERT
DELETE
)

func (sc SpanContext) HasTraceID() bool {
return sc.TraceIDHigh != 0 || sc.TraceIDLow != 0
}

func (sc SpanContext) HasSpanID() bool {
return sc.SpanID != 0
}

func (sc SpanContext) SpanIDString() string {
p := fmt.Sprintf("%.16x", sc.SpanID)
return p[0:3] + ".." + p[13:16]
}

func (sc SpanContext) TraceIDString() string {
p1 := fmt.Sprintf("%.16x", sc.TraceIDHigh)
p2 := fmt.Sprintf("%.16x", sc.TraceIDLow)
return p1[0:3] + ".." + p2[13:16]
}

// TODO make this a lazy one-time conversion.
func (v Value) Emit() string {
switch v.Type {
case BOOL:
return fmt.Sprint(v.Bool)
case INT32, INT64:
return fmt.Sprint(v.Int64)
case UINT32, UINT64:
return fmt.Sprint(v.Uint64)
case FLOAT32, FLOAT64:
return fmt.Sprint(v.Float64)
case STRING:
return v.String
case BYTES:
return string(v.Bytes)
}
return "unknown"
}

func (m Mutator) WithMaxHops(hops int) Mutator {
m.MaxHops = hops
return m
}

func (e EventID) Scope() ScopeID {
return ScopeID{
EventID: e,
}
}

func (s SpanContext) Scope() ScopeID {
return ScopeID{
SpanContext: s,
}
}

func (m Measurement) With(id ScopeID) Measurement {
m.ScopeID = id
return m
}
52 changes: 52 additions & 0 deletions api/log/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package log

import (
"context"

"github.com/open-telemetry/opentelemetry-go/api/core"
"github.com/open-telemetry/opentelemetry-go/api/scope"
"github.com/open-telemetry/opentelemetry-go/exporter/observer"
)

type (
Interface interface {
Log(ctx context.Context, msg string, fields ...core.KeyValue)
Logf(ctx context.Context, fmt string, args ...interface{})
}

Logger struct {
scope.Scope
}
)

func With(scope scope.Scope) Logger {
return Logger{scope}
}

func Log(ctx context.Context, msg string, fields ...core.KeyValue) {
With(scope.Active(ctx)).Log(ctx, msg, fields...)
}

func Logf(ctx context.Context, fmt string, args ...interface{}) {
With(scope.Active(ctx)).Logf(ctx, fmt, args...)
}

func (l Logger) Log(ctx context.Context, msg string, fields ...core.KeyValue) {
observer.Record(observer.Event{
Type: observer.LOG_EVENT,
Scope: l.ScopeID(),
String: msg,
Attributes: fields,
Context: ctx,
})
}

func (l Logger) Logf(ctx context.Context, fmt string, args ...interface{}) {
observer.Record(observer.Event{
Type: observer.LOGF_EVENT,
Scope: l.ScopeID(),
String: fmt,
Arguments: args,
Context: ctx,
})
}
60 changes: 60 additions & 0 deletions api/metric/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package metric

import (
"github.com/open-telemetry/opentelemetry-go/api/core"
"github.com/open-telemetry/opentelemetry-go/api/tag"
"github.com/open-telemetry/opentelemetry-go/api/unit"
)

type (
Metric interface {
Measure() core.Measure

DefinitionID() core.EventID

Type() MetricType
Fields() []core.Key
Err() error

base() *baseMetric
}

MetricType int
)

const (
Invalid MetricType = iota
GaugeInt64
GaugeFloat64
DerivedGaugeInt64
DerivedGaugeFloat64
CumulativeInt64
CumulativeFloat64
DerivedCumulativeInt64
DerivedCumulativeFloat64
)

type (
Option func(*baseMetric, *[]tag.Option)
)

// WithDescription applies provided description.
func WithDescription(desc string) Option {
return func(_ *baseMetric, to *[]tag.Option) {
*to = append(*to, tag.WithDescription(desc))
}
}

// WithUnit applies provided unit.
func WithUnit(unit unit.Unit) Option {
return func(_ *baseMetric, to *[]tag.Option) {
*to = append(*to, tag.WithUnit(unit))
}
}

// WithKeys applies the provided dimension keys.
func WithKeys(keys ...core.Key) Option {
return func(bm *baseMetric, _ *[]tag.Option) {
bm.keys = keys
}
}
74 changes: 74 additions & 0 deletions api/metric/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package metric

import (
"github.com/open-telemetry/opentelemetry-go/api/core"
"github.com/open-telemetry/opentelemetry-go/api/scope"
"github.com/open-telemetry/opentelemetry-go/api/tag"
"github.com/open-telemetry/opentelemetry-go/exporter/observer"
)

type (
baseMetric struct {
measure core.Measure

mtype MetricType
keys []core.Key
eventID core.EventID
status error // Indicates registry conflict
}

baseEntry struct {
base *baseMetric
metric Metric
eventID core.EventID
}
)

func initBaseMetric(name string, mtype MetricType, opts []Option, init Metric) Metric {
var tagOpts []tag.Option
bm := init.base()

for _, opt := range opts {
opt(bm, &tagOpts)
}

bm.measure = tag.NewMeasure(name, tagOpts...)
bm.mtype = mtype

bm.eventID = observer.Record(observer.Event{
Type: observer.NEW_METRIC,
Scope: bm.measure.DefinitionID().Scope(),
})

other, err := GetRegistry().RegisterMetric(init)
if err != nil {
bm.status = err
}
return other
}

func (bm *baseMetric) base() *baseMetric {
return bm
}

func (bm *baseMetric) Measure() core.Measure {
return bm.measure
}

func (bm *baseMetric) Type() MetricType {
return bm.mtype
}

func (bm *baseMetric) Fields() []core.Key {
return bm.keys
}

func (bm *baseMetric) Err() error {
return bm.status
}

func (e *baseEntry) init(m Metric, values []core.KeyValue) {
e.base = m.base()
e.metric = m
e.eventID = scope.New(core.ScopeID{}, values...).ScopeID().EventID
}
Loading

0 comments on commit e17f446

Please sign in to comment.