Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Global initialization and resources proposal: demonstration #3

Closed
wants to merge 14 commits into from
25 changes: 14 additions & 11 deletions ...reaming/exporter/stderr/plugin/package.go → api/core/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package main
package core

import (
"go.opentelemetry.io/experimental/streaming/exporter/observer"
"go.opentelemetry.io/experimental/streaming/exporter/stderr"
"bytes"
"encoding/json"
"fmt"
)

var (
stderrObs = stderr.New()
)

func Observer() observer.Observer {
return stderrObs
func applyEncoder(e Encoder) []byte {
var buf bytes.Buffer
e(&buf)
return buf.Bytes()
}

func main() {
_ = Observer()
func encodeStruct(v interface{}) []byte {
d, e := json.Marshal(v)
if e != nil {
d = []byte(fmt.Sprintf("%q", e))
}
return d
}
72 changes: 66 additions & 6 deletions api/core/key.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
// 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 core

import (
"fmt"
"io"
"unsafe"

"go.opentelemetry.io/api/registry"
Expand All @@ -18,6 +33,8 @@ type KeyValue struct {

type ValueType int

type Encoder func(io.Writer) error

type Value struct {
Type ValueType
Bool bool
Expand All @@ -26,8 +43,8 @@ type Value struct {
Float64 float64
String string
Bytes []byte

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a type that we have in the OpenTelemetry specs.


// TODO Lazy value type?
Struct interface{}
Encoder Encoder
}

const (
Expand All @@ -41,6 +58,8 @@ const (
FLOAT64
STRING
BYTES
STRUCT // Struct or Bytes, whichever is non-nil.
ENCODER // Encoder or Bytes, whichever is non-nil.
)

func (k Key) Bool(v bool) KeyValue {
Expand Down Expand Up @@ -147,11 +166,50 @@ func (k Key) Uint(v uint) KeyValue {
return k.Uint64(uint64(v))
}

func (k Key) Struct(v interface{}) KeyValue {
return KeyValue{
Key: k,
Value: Value{
Type: STRUCT,
Struct: v,
},
}
}

func (k Key) Encode(v func(io.Writer) error) KeyValue {
return KeyValue{
Key: k,
Value: Value{
Type: ENCODER,
Encoder: v,
},
}
}

func (k Key) Defined() bool {
return k.Variable.Defined()
}

// TODO make this a lazy one-time conversion.
func (v Value) Evaluate() Value {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue of making a copy of the Value object was brought up in the #59 too. So just to keep track of that I'll mention it here: the BYTES case should also be handled here by making a new slice and copying a contents of the original slice into the new slice.

switch v.Type {
case STRUCT:
if v.Struct != nil {
return Value{
Type: STRUCT,
Bytes: encodeStruct(v.Struct),
}
}
case ENCODER:
if v.Encoder != nil {
return Value{
Type: STRUCT,
Bytes: applyEncoder(v.Encoder),
}
}
}
return v
}

func (v Value) Emit() string {
switch v.Type {
case BOOL:
Expand All @@ -164,8 +222,10 @@ func (v Value) Emit() string {
return fmt.Sprint(v.Float64)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we only emit strings?

case STRING:
return v.String
case BYTES:
return string(v.Bytes)
case BYTES, STRUCT, ENCODER:
// Note: In case of a fully synchronous SDK, this call
// could be the first to evaluate a struct/encoder value.
return string(v.Evaluate().Bytes)
}
return "unknown"
return "invalid"
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package main
package internal

import (
"go.opentelemetry.io/experimental/streaming/exporter/observer"
"go.opentelemetry.io/experimental/streaming/exporter/stdout"
"sync/atomic"
)

var (
stdoutObs = stdout.New()
)

func Observer() observer.Observer {
return stdoutObs
}

func main() {
_ = Observer()
}
var GlobalTracer atomic.Value
var GlobalMeter atomic.Value
33 changes: 0 additions & 33 deletions api/metric/global.go

This file was deleted.

48 changes: 48 additions & 0 deletions api/metric/global/global.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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 metric

import (
"context"

"go.opentelemetry.io/api/core"
"go.opentelemetry.io/api/internal"
"go.opentelemetry.io/api/metric"
)

// Meter returns the global Meter instance. Before opentelemetry.Init() is
// called, this returns an "indirect" No-op implementation, that will be updated
// once the SDK is initialized.
func Meter() metric.Meter {
if t := internal.GlobalMeter.Load(); t != nil {
return t.(metric.Meter)
}
return metric.NoopMeter{}
}

// IndirectMeter implements Meter, allows callers of Meter() before Init()
// to forward to the installed SDK.
type IndirectMeter struct{}

var globalIndirect metric.Meter = &IndirectMeter{}

// GetFloat64Gauge implements Meter
func (*IndirectMeter) GetFloat64Gauge(
ctx context.Context,
gauge *metric.Float64GaugeHandle,
labels ...core.KeyValue,
) metric.Float64Gauge {
return Meter().GetFloat64Gauge(ctx, gauge, labels...)
}
6 changes: 3 additions & 3 deletions api/metric/noop_meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import (
"go.opentelemetry.io/api/core"
)

type noopMeter struct{}
type NoopMeter struct{}

type noopMetric struct{}

var _ Meter = noopMeter{}
var _ Meter = NoopMeter{}

var _ Float64Gauge = noopMetric{}

func (noopMeter) GetFloat64Gauge(ctx context.Context, gauge *Float64GaugeHandle, labels ...core.KeyValue) Float64Gauge {
func (NoopMeter) GetFloat64Gauge(ctx context.Context, gauge *Float64GaugeHandle, labels ...core.KeyValue) Float64Gauge {
return noopMetric{}
}

Expand Down
23 changes: 23 additions & 0 deletions api/package.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package opentelemetry

import (
"sync"

"go.opentelemetry.io/api/internal"
"go.opentelemetry.io/api/metric"
"go.opentelemetry.io/api/trace"
)

var once sync.Once

type SDK interface {
trace.Tracer
metric.Meter
}

func Init(sdk SDK) {
once.Do(func() {
internal.GlobalTracer.Store(sdk.(trace.Tracer))
internal.GlobalMeter.Store(sdk.(metric.Meter))
})
}
57 changes: 57 additions & 0 deletions api/resource/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// 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 resource

import (
"go.opentelemetry.io/api/core"
"go.opentelemetry.io/api/key"
"go.opentelemetry.io/api/tag"
)

var (
ComponentKey = key.New("component")
ServiceKey = key.New("service")
)

type Map struct {
labels tag.Map
}

func Service(name string) Map {
return Map{tag.NewMap(tag.MapUpdate{SingleKV: ServiceKey.String(name)})}
}

func Component(name string) Map {
return Map{tag.NewMap(tag.MapUpdate{SingleKV: ComponentKey.String(name)})}
}

func New(labels ...core.KeyValue) Map {
return Map{tag.NewMap(tag.MapUpdate{MultiKV: labels})}
}

func (m Map) Foreach(kv func (core.KeyValue) bool) {
m.labels.Foreach(kv)
}

func Merge(maps ...Map) Map {
var all []core.KeyValue
for _, m := range maps {
m.labels.Foreach(func(kv core.KeyValue) bool {
all = append(all, kv)
return true
})
}
return Map{tag.NewMap(tag.MapUpdate{MultiKV: all})}
}
6 changes: 3 additions & 3 deletions api/tag/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ func (t tagMap) Apply(update MapUpdate) Map {
}
if update.SingleKV.Key.Defined() {
m[update.SingleKV.Key] = tagContent{
value: update.SingleKV.Value,
value: update.SingleKV.Value.Evaluate(),
}
}
for _, kv := range update.MultiKV {
m[kv.Key] = tagContent{
value: kv.Value,
value: kv.Value.Evaluate(),
}
}
if update.SingleMutator.Key.Defined() {
Expand Down Expand Up @@ -88,7 +88,7 @@ func (m tagMap) apply(mutator Mutator) {
}
key := mutator.KeyValue.Key
content := tagContent{
value: mutator.KeyValue.Value,
value: mutator.KeyValue.Value.Evaluate(),
meta: mutator.MeasureMetadata,
}
switch mutator.MutatorOp {
Expand Down
Loading