feat(telemetry): instrument inference duration and frame age
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"github.com/cyrilix/robocar-base/cli"
|
"github.com/cyrilix/robocar-base/cli"
|
||||||
|
"github.com/cyrilix/robocar-steering-tflite-edgetpu/pkg/metrics"
|
||||||
"github.com/cyrilix/robocar-steering-tflite-edgetpu/pkg/steering"
|
"github.com/cyrilix/robocar-steering-tflite-edgetpu/pkg/steering"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"log"
|
"log"
|
||||||
@@ -59,6 +61,9 @@ func main() {
|
|||||||
}()
|
}()
|
||||||
zap.ReplaceGlobals(lgr)
|
zap.ReplaceGlobals(lgr)
|
||||||
|
|
||||||
|
cleanup := metrics.Init(context.Background())
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
if modelPath == "" {
|
if modelPath == "" {
|
||||||
zap.L().Error("model path is mandatory")
|
zap.L().Error("model path is mandatory")
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
|
|||||||
9
go.mod
9
go.mod
@@ -9,15 +9,24 @@ require (
|
|||||||
github.com/eclipse/paho.mqtt.golang v1.3.5
|
github.com/eclipse/paho.mqtt.golang v1.3.5
|
||||||
github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf v1.5.2
|
||||||
github.com/mattn/go-tflite v1.0.2-0.20210524070808-ba19dc99415b
|
github.com/mattn/go-tflite v1.0.2-0.20210524070808-ba19dc99415b
|
||||||
|
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.25.0
|
||||||
|
go.opentelemetry.io/otel/metric v0.25.0
|
||||||
|
go.opentelemetry.io/otel/sdk/export/metric v0.25.0
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v0.25.0
|
||||||
go.uber.org/zap v1.19.1
|
go.uber.org/zap v1.19.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gorilla/websocket v1.4.2 // indirect
|
github.com/gorilla/websocket v1.4.2 // indirect
|
||||||
github.com/mattn/go-pointer v0.0.1 // indirect
|
github.com/mattn/go-pointer v0.0.1 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.2.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/internal/metric v0.25.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk v1.2.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.2.0 // indirect
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.7.0 // indirect
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 // indirect
|
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 // indirect
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect
|
||||||
google.golang.org/protobuf v1.26.0 // indirect
|
google.golang.org/protobuf v1.26.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
24
go.sum
24
go.sum
@@ -3,8 +3,9 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX
|
|||||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
|
||||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
|
github.com/benbjohnson/clock v1.2.0 h1:9Re3G2TWxkE06LdMWMpcY6KV81GLXMGiYpPYUPkFAws=
|
||||||
|
github.com/benbjohnson/clock v1.2.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
@@ -53,8 +54,9 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
|||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||||
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
@@ -112,6 +114,22 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM
|
|||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
github.com/vincent-petithory/dataurl v0.0.0-20191104211930-d1553a71de50/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U=
|
github.com/vincent-petithory/dataurl v0.0.0-20191104211930-d1553a71de50/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ=
|
||||||
|
go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I=
|
||||||
|
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.25.0 h1:XyBEWc22bxYllvyeG3bmW0G4esJ8Wi6P2m0e/tIuMsE=
|
||||||
|
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.25.0/go.mod h1:Mn5lMLB4mIMKZ1IR4qCoYspC4lEbfK6pD7bI3SSAMKk=
|
||||||
|
go.opentelemetry.io/otel/internal/metric v0.25.0 h1:w/7RXe16WdPylaIXDgcYM6t/q0K5lXgSdZOEbIEyliE=
|
||||||
|
go.opentelemetry.io/otel/internal/metric v0.25.0/go.mod h1:Nhuw26QSX7d6n4duoqAFi5KOQR4AuzyMcl5eXOgwxtc=
|
||||||
|
go.opentelemetry.io/otel/metric v0.25.0 h1:7cXOnCADUsR3+EOqxPaSKwhEuNu0gz/56dRN1hpIdKw=
|
||||||
|
go.opentelemetry.io/otel/metric v0.25.0/go.mod h1:E884FSpQfnJOMMUaq+05IWlJ4rjZpk2s/F1Ju+TEEm8=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.2.0 h1:wKN260u4DesJYhyjxDa7LRFkuhH7ncEVKU37LWcyNIo=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U=
|
||||||
|
go.opentelemetry.io/otel/sdk/export/metric v0.25.0 h1:6UjAFmVB5Fza3K5qUJpYWGrk8QMPIqlSnya5FI46VBY=
|
||||||
|
go.opentelemetry.io/otel/sdk/export/metric v0.25.0/go.mod h1:Ej7NOa+WpN49EIcr1HMUYRvxXXCCnQCg2+ovdt2z8Pk=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v0.25.0 h1:J+Ta+4IAA5W9AdWhGQLfciEpavBqqSkBzTDeYvJLFNU=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v0.25.0/go.mod h1:G4xzj4LvC6xDDSsVXpvRVclQCbofGGg4ZU2VKKtDRfg=
|
||||||
|
go.opentelemetry.io/otel/trace v1.2.0 h1:Ys3iqbqZhcf28hHzrm5WAquMkDHNZTUkw7KHbuNjej0=
|
||||||
|
go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0=
|
||||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
|
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
|
||||||
@@ -157,6 +175,8 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|||||||
69
pkg/metrics/metrics.go
Normal file
69
pkg/metrics/metrics.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
stdout "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
"go.opentelemetry.io/otel/metric/global"
|
||||||
|
"go.opentelemetry.io/otel/metric/unit"
|
||||||
|
controller "go.opentelemetry.io/otel/sdk/metric/controller/basic"
|
||||||
|
processor "go.opentelemetry.io/otel/sdk/metric/processor/basic"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/selector/simple"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
FrameAge metric.Int64Histogram
|
||||||
|
InferenceDuration metric.Int64Histogram
|
||||||
|
)
|
||||||
|
|
||||||
|
func initMeter(ctx context.Context) func() {
|
||||||
|
zap.S().Info("init telemetry")
|
||||||
|
exporter, err := stdout.New(
|
||||||
|
stdout.WithPrettyPrint(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
zap.S().Panicf("failed to initialize prometheus exporter %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pusher := controller.New(
|
||||||
|
processor.NewFactory(
|
||||||
|
simple.NewWithInexpensiveDistribution(),
|
||||||
|
//simple.NewWithHistogramDistribution(
|
||||||
|
// histogram.WithExplicitBoundaries(
|
||||||
|
// []float64{.005, .5, 1, 2.5, 5, 10, 20, 50, 100},
|
||||||
|
// ),
|
||||||
|
//),
|
||||||
|
exporter,
|
||||||
|
),
|
||||||
|
controller.WithExporter(exporter),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err = pusher.Start(ctx); err != nil {
|
||||||
|
zap.S().Fatalf("starting push controller: %v", err)
|
||||||
|
}
|
||||||
|
global.SetMeterProvider(pusher)
|
||||||
|
return func() {
|
||||||
|
if err := pusher.Stop(ctx); err != nil {
|
||||||
|
zap.S().Fatalf("stopping push controller: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init(ctx context.Context) func() {
|
||||||
|
cleaner := initMeter(ctx)
|
||||||
|
|
||||||
|
meter := global.Meter("robocar/rc-steering")
|
||||||
|
|
||||||
|
FrameAge = metric.Must(meter).NewInt64Histogram(
|
||||||
|
"robocar.frame_age",
|
||||||
|
metric.WithUnit(unit.Milliseconds),
|
||||||
|
metric.WithDescription("time before frame processing"))
|
||||||
|
InferenceDuration = metric.Must(meter).NewInt64Histogram(
|
||||||
|
"robocar.inference_duration",
|
||||||
|
metric.WithUnit(unit.Milliseconds),
|
||||||
|
metric.WithDescription("tensorflow inference duration"))
|
||||||
|
|
||||||
|
return cleaner
|
||||||
|
}
|
||||||
@@ -2,9 +2,11 @@ package steering
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/cyrilix/robocar-base/service"
|
"github.com/cyrilix/robocar-base/service"
|
||||||
"github.com/cyrilix/robocar-protobuf/go/events"
|
"github.com/cyrilix/robocar-protobuf/go/events"
|
||||||
|
"github.com/cyrilix/robocar-steering-tflite-edgetpu/pkg/metrics"
|
||||||
"github.com/disintegration/imaging"
|
"github.com/disintegration/imaging"
|
||||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
@@ -14,6 +16,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
_ "image/jpeg"
|
_ "image/jpeg"
|
||||||
"sort"
|
"sort"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewPart(client mqtt.Client, modelPath, steeringTopic, cameraTopic string, edgeVerbosity int, imgWidth, imgHeight, horizon int) *Part {
|
func NewPart(client mqtt.Client, modelPath, steeringTopic, cameraTopic string, edgeVerbosity int, imgWidth, imgHeight, horizon int) *Part {
|
||||||
@@ -130,6 +133,11 @@ func (p *Part) onFrame(_ mqtt.Client, message mqtt.Message) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
now := time.Now().UnixMilli()
|
||||||
|
frameAge := now - msg.Id.CreatedAt.AsTime().UnixMilli()
|
||||||
|
go metrics.FrameAge.Record(context.Background(), frameAge)
|
||||||
|
|
||||||
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(msg.GetFrame()))
|
img, _, err := image.Decode(bytes.NewReader(msg.GetFrame()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.L().Error("unable to decode frame, skip frame", zap.Error(err))
|
zap.L().Error("unable to decode frame, skip frame", zap.Error(err))
|
||||||
@@ -137,6 +145,9 @@ func (p *Part) onFrame(_ mqtt.Client, message mqtt.Message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
steering, confidence, err := p.Value(img)
|
steering, confidence, err := p.Value(img)
|
||||||
|
inferenceDuration := time.Now().UnixMilli() - now
|
||||||
|
go metrics.InferenceDuration.Record(context.Background(), inferenceDuration)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.S().Errorw("unable to compute sterring",
|
zap.S().Errorw("unable to compute sterring",
|
||||||
"frame", msg.GetId().GetId(),
|
"frame", msg.GetId().GetId(),
|
||||||
|
|||||||
3
vendor/go.opentelemetry.io/otel/.gitattributes
generated
vendored
Normal file
3
vendor/go.opentelemetry.io/otel/.gitattributes
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
* text=auto eol=lf
|
||||||
|
*.{cmd,[cC][mM][dD]} text eol=crlf
|
||||||
|
*.{bat,[bB][aA][tT]} text eol=crlf
|
||||||
21
vendor/go.opentelemetry.io/otel/.gitignore
generated
vendored
Normal file
21
vendor/go.opentelemetry.io/otel/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
.tools/
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.iml
|
||||||
|
*.so
|
||||||
|
coverage.*
|
||||||
|
|
||||||
|
gen/
|
||||||
|
|
||||||
|
/example/fib/fib
|
||||||
|
/example/jaeger/jaeger
|
||||||
|
/example/namedtracer/namedtracer
|
||||||
|
/example/opencensus/opencensus
|
||||||
|
/example/passthrough/passthrough
|
||||||
|
/example/prometheus/prometheus
|
||||||
|
/example/prom-collector/prom-collector
|
||||||
|
/example/zipkin/zipkin
|
||||||
|
/example/otel-collector/otel-collector
|
||||||
3
vendor/go.opentelemetry.io/otel/.gitmodules
generated
vendored
Normal file
3
vendor/go.opentelemetry.io/otel/.gitmodules
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "opentelemetry-proto"]
|
||||||
|
path = exporters/otlp/internal/opentelemetry-proto
|
||||||
|
url = https://github.com/open-telemetry/opentelemetry-proto
|
||||||
32
vendor/go.opentelemetry.io/otel/.golangci.yml
generated
vendored
Normal file
32
vendor/go.opentelemetry.io/otel/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# See https://github.com/golangci/golangci-lint#config-file
|
||||||
|
run:
|
||||||
|
issues-exit-code: 1 #Default
|
||||||
|
tests: true #Default
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- misspell
|
||||||
|
- goimports
|
||||||
|
- revive
|
||||||
|
- gofmt
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
# helpers in tests often (rightfully) pass a *testing.T as their first argument
|
||||||
|
- path: _test\.go
|
||||||
|
text: "context.Context should be the first parameter of a function"
|
||||||
|
linters:
|
||||||
|
- revive
|
||||||
|
# Yes, they are, but it's okay in a test
|
||||||
|
- path: _test\.go
|
||||||
|
text: "exported func.*returns unexported type.*which can be annoying to use"
|
||||||
|
linters:
|
||||||
|
- revive
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
ignore-words:
|
||||||
|
- cancelled
|
||||||
|
goimports:
|
||||||
|
local-prefixes: go.opentelemetry.io
|
||||||
16
vendor/go.opentelemetry.io/otel/.markdown-link.json
generated
vendored
Normal file
16
vendor/go.opentelemetry.io/otel/.markdown-link.json
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"ignorePatterns": [
|
||||||
|
{
|
||||||
|
"pattern": "^http(s)?://localhost"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"replacementPatterns": [
|
||||||
|
{
|
||||||
|
"pattern": "^/registry",
|
||||||
|
"replacement": "https://opentelemetry.io/registry"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"retryOn429": true,
|
||||||
|
"retryCount": 5,
|
||||||
|
"fallbackRetryDelay": "30s"
|
||||||
|
}
|
||||||
29
vendor/go.opentelemetry.io/otel/.markdownlint.yaml
generated
vendored
Normal file
29
vendor/go.opentelemetry.io/otel/.markdownlint.yaml
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Default state for all rules
|
||||||
|
default: true
|
||||||
|
|
||||||
|
# ul-style
|
||||||
|
MD004: false
|
||||||
|
|
||||||
|
# hard-tabs
|
||||||
|
MD010: false
|
||||||
|
|
||||||
|
# line-length
|
||||||
|
MD013: false
|
||||||
|
|
||||||
|
# no-duplicate-header
|
||||||
|
MD024:
|
||||||
|
siblings_only: true
|
||||||
|
|
||||||
|
#single-title
|
||||||
|
MD025: false
|
||||||
|
|
||||||
|
# ol-prefix
|
||||||
|
MD029:
|
||||||
|
style: ordered
|
||||||
|
|
||||||
|
# no-inline-html
|
||||||
|
MD033: false
|
||||||
|
|
||||||
|
# fenced-code-language
|
||||||
|
MD040: false
|
||||||
|
|
||||||
1638
vendor/go.opentelemetry.io/otel/CHANGELOG.md
generated
vendored
Normal file
1638
vendor/go.opentelemetry.io/otel/CHANGELOG.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
17
vendor/go.opentelemetry.io/otel/CODEOWNERS
generated
vendored
Normal file
17
vendor/go.opentelemetry.io/otel/CODEOWNERS
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#####################################################
|
||||||
|
#
|
||||||
|
# List of approvers for this repository
|
||||||
|
#
|
||||||
|
#####################################################
|
||||||
|
#
|
||||||
|
# Learn about membership in OpenTelemetry community:
|
||||||
|
# https://github.com/open-telemetry/community/blob/main/community-membership.md
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Learn about CODEOWNERS file format:
|
||||||
|
# https://help.github.com/en/articles/about-code-owners
|
||||||
|
#
|
||||||
|
|
||||||
|
* @jmacd @MrAlias @Aneurysm9 @evantorrie @XSAM @dashpole @paivagustavo @MadVikingGod @pellared
|
||||||
|
|
||||||
|
CODEOWNERS @MrAlias @Aneurysm9
|
||||||
495
vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
generated
vendored
Normal file
495
vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,495 @@
|
|||||||
|
# Contributing to opentelemetry-go
|
||||||
|
|
||||||
|
The Go special interest group (SIG) meets regularly. See the
|
||||||
|
OpenTelemetry
|
||||||
|
[community](https://github.com/open-telemetry/community#golang-sdk)
|
||||||
|
repo for information on this and other language SIGs.
|
||||||
|
|
||||||
|
See the [public meeting
|
||||||
|
notes](https://docs.google.com/document/d/1A63zSWX0x2CyCK_LoNhmQC4rqhLpYXJzXbEPDUQ2n6w/edit#heading=h.9tngw7jdwd6b)
|
||||||
|
for a summary description of past meetings. To request edit access,
|
||||||
|
join the meeting or get in touch on
|
||||||
|
[Slack](https://cloud-native.slack.com/archives/C01NPAXACKT).
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
You can view and edit the source code by cloning this repository:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/open-telemetry/opentelemetry-go.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `make test` to run the tests instead of `go test`.
|
||||||
|
|
||||||
|
There are some generated files checked into the repo. To make sure
|
||||||
|
that the generated files are up-to-date, run `make` (or `make
|
||||||
|
precommit` - the `precommit` target is the default).
|
||||||
|
|
||||||
|
The `precommit` target also fixes the formatting of the code and
|
||||||
|
checks the status of the go module files.
|
||||||
|
|
||||||
|
If after running `make precommit` the output of `git status` contains
|
||||||
|
`nothing to commit, working tree clean` then it means that everything
|
||||||
|
is up-to-date and properly formatted.
|
||||||
|
|
||||||
|
## Pull Requests
|
||||||
|
|
||||||
|
### How to Send Pull Requests
|
||||||
|
|
||||||
|
Everyone is welcome to contribute code to `opentelemetry-go` via
|
||||||
|
GitHub pull requests (PRs).
|
||||||
|
|
||||||
|
To create a new PR, fork the project in GitHub and clone the upstream
|
||||||
|
repo:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
go get -d go.opentelemetry.io/otel
|
||||||
|
```
|
||||||
|
|
||||||
|
(This may print some warning about "build constraints exclude all Go
|
||||||
|
files", just ignore it.)
|
||||||
|
|
||||||
|
This will put the project in `${GOPATH}/src/go.opentelemetry.io/otel`. You
|
||||||
|
can alternatively use `git` directly with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/open-telemetry/opentelemetry-go
|
||||||
|
```
|
||||||
|
|
||||||
|
(Note that `git clone` is *not* using the `go.opentelemetry.io/otel` name -
|
||||||
|
that name is a kind of a redirector to GitHub that `go get` can
|
||||||
|
understand, but `git` does not.)
|
||||||
|
|
||||||
|
This would put the project in the `opentelemetry-go` directory in
|
||||||
|
current working directory.
|
||||||
|
|
||||||
|
Enter the newly created directory and add your fork as a new remote:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git remote add <YOUR_FORK> git@github.com:<YOUR_GITHUB_USERNAME>/opentelemetry-go
|
||||||
|
```
|
||||||
|
|
||||||
|
Check out a new branch, make modifications, run linters and tests, update
|
||||||
|
`CHANGELOG.md`, and push the branch to your fork:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git checkout -b <YOUR_BRANCH_NAME>
|
||||||
|
# edit files
|
||||||
|
# update changelog
|
||||||
|
make precommit
|
||||||
|
git add -p
|
||||||
|
git commit
|
||||||
|
git push <YOUR_FORK> <YOUR_BRANCH_NAME>
|
||||||
|
```
|
||||||
|
|
||||||
|
Open a pull request against the main `opentelemetry-go` repo. Be sure to add the pull
|
||||||
|
request ID to the entry you added to `CHANGELOG.md`.
|
||||||
|
|
||||||
|
### How to Receive Comments
|
||||||
|
|
||||||
|
* If the PR is not ready for review, please put `[WIP]` in the title,
|
||||||
|
tag it as `work-in-progress`, or mark it as
|
||||||
|
[`draft`](https://github.blog/2019-02-14-introducing-draft-pull-requests/).
|
||||||
|
* Make sure CLA is signed and CI is clear.
|
||||||
|
|
||||||
|
### How to Get PRs Merged
|
||||||
|
|
||||||
|
A PR is considered to be **ready to merge** when:
|
||||||
|
|
||||||
|
* It has received two approvals from Collaborators/Maintainers (at
|
||||||
|
different companies). This is not enforced through technical means
|
||||||
|
and a PR may be **ready to merge** with a single approval if the change
|
||||||
|
and its approach have been discussed and consensus reached.
|
||||||
|
* Feedback has been addressed.
|
||||||
|
* Any substantive changes to your PR will require that you clear any prior
|
||||||
|
Approval reviews, this includes changes resulting from other feedback. Unless
|
||||||
|
the approver explicitly stated that their approval will persist across
|
||||||
|
changes it should be assumed that the PR needs their review again. Other
|
||||||
|
project members (e.g. approvers, maintainers) can help with this if there are
|
||||||
|
any questions or if you forget to clear reviews.
|
||||||
|
* It has been open for review for at least one working day. This gives
|
||||||
|
people reasonable time to review.
|
||||||
|
* Trivial changes (typo, cosmetic, doc, etc.) do not have to wait for
|
||||||
|
one day and may be merged with a single Maintainer's approval.
|
||||||
|
* `CHANGELOG.md` has been updated to reflect what has been
|
||||||
|
added, changed, removed, or fixed.
|
||||||
|
* `README.md` has been updated if necessary.
|
||||||
|
* Urgent fix can take exception as long as it has been actively
|
||||||
|
communicated.
|
||||||
|
|
||||||
|
Any Maintainer can merge the PR once it is **ready to merge**.
|
||||||
|
|
||||||
|
## Design Choices
|
||||||
|
|
||||||
|
As with other OpenTelemetry clients, opentelemetry-go follows the
|
||||||
|
[opentelemetry-specification](https://github.com/open-telemetry/opentelemetry-specification).
|
||||||
|
|
||||||
|
It's especially valuable to read through the [library
|
||||||
|
guidelines](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/library-guidelines.md).
|
||||||
|
|
||||||
|
### Focus on Capabilities, Not Structure Compliance
|
||||||
|
|
||||||
|
OpenTelemetry is an evolving specification, one where the desires and
|
||||||
|
use cases are clear, but the method to satisfy those uses cases are
|
||||||
|
not.
|
||||||
|
|
||||||
|
As such, Contributions should provide functionality and behavior that
|
||||||
|
conforms to the specification, but the interface and structure is
|
||||||
|
flexible.
|
||||||
|
|
||||||
|
It is preferable to have contributions follow the idioms of the
|
||||||
|
language rather than conform to specific API names or argument
|
||||||
|
patterns in the spec.
|
||||||
|
|
||||||
|
For a deeper discussion, see
|
||||||
|
[this](https://github.com/open-telemetry/opentelemetry-specification/issues/165).
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Each non-example Go Module should have its own `README.md` containing:
|
||||||
|
|
||||||
|
- A pkg.go.dev badge which can be generated [here](https://pkg.go.dev/badge/).
|
||||||
|
- Brief description.
|
||||||
|
- Installation instructions (and requirements if applicable).
|
||||||
|
- Hyperlink to an example. Depending on the component the example can be:
|
||||||
|
- An `example_test.go` like [here](exporters/stdout/stdouttrace/example_test.go).
|
||||||
|
- A sample Go application with its own `README.md`, like [here](example/zipkin).
|
||||||
|
- Additional documentation sections such us:
|
||||||
|
- Configuration,
|
||||||
|
- Contributing,
|
||||||
|
- References.
|
||||||
|
|
||||||
|
[Here](exporters/jaeger/README.md) is an example of a concise `README.md`.
|
||||||
|
|
||||||
|
Moreover, it should be possible to navigate to any `README.md` from the
|
||||||
|
root `README.md`.
|
||||||
|
|
||||||
|
## Style Guide
|
||||||
|
|
||||||
|
One of the primary goals of this project is that it is actually used by
|
||||||
|
developers. With this goal in mind the project strives to build
|
||||||
|
user-friendly and idiomatic Go code adhering to the Go community's best
|
||||||
|
practices.
|
||||||
|
|
||||||
|
For a non-comprehensive but foundational overview of these best practices
|
||||||
|
the [Effective Go](https://golang.org/doc/effective_go.html) documentation
|
||||||
|
is an excellent starting place.
|
||||||
|
|
||||||
|
As a convenience for developers building this project the `make precommit`
|
||||||
|
will format, lint, validate, and in some cases fix the changes you plan to
|
||||||
|
submit. This check will need to pass for your changes to be able to be
|
||||||
|
merged.
|
||||||
|
|
||||||
|
In addition to idiomatic Go, the project has adopted certain standards for
|
||||||
|
implementations of common patterns. These standards should be followed as a
|
||||||
|
default, and if they are not followed documentation needs to be included as
|
||||||
|
to the reasons why.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
When creating an instantiation function for a complex `type T struct`, it is
|
||||||
|
useful to allow variable number of options to be applied. However, the strong
|
||||||
|
type system of Go restricts the function design options. There are a few ways
|
||||||
|
to solve this problem, but we have landed on the following design.
|
||||||
|
|
||||||
|
#### `config`
|
||||||
|
|
||||||
|
Configuration should be held in a `struct` named `config`, or prefixed with
|
||||||
|
specific type name this Configuration applies to if there are multiple
|
||||||
|
`config` in the package. This type must contain configuration options.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// config contains configuration options for a thing.
|
||||||
|
type config struct {
|
||||||
|
// options ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In general the `config` type will not need to be used externally to the
|
||||||
|
package and should be unexported. If, however, it is expected that the user
|
||||||
|
will likely want to build custom options for the configuration, the `config`
|
||||||
|
should be exported. Please, include in the documentation for the `config`
|
||||||
|
how the user can extend the configuration.
|
||||||
|
|
||||||
|
It is important that internal `config` are not shared across package boundaries.
|
||||||
|
Meaning a `config` from one package should not be directly used by another. The
|
||||||
|
one exception is the API packages. The configs from the base API, eg.
|
||||||
|
`go.opentelemetry.io/otel/trace.TracerConfig` and
|
||||||
|
`go.opentelemetry.io/otel/metric.InstrumentConfig`, are intended to be consumed
|
||||||
|
by the SDK therefor it is expected that these are exported.
|
||||||
|
|
||||||
|
When a config is exported we want to maintain forward and backward
|
||||||
|
compatibility, to achieve this no fields should be exported but should
|
||||||
|
instead be accessed by methods.
|
||||||
|
|
||||||
|
Optionally, it is common to include a `newConfig` function (with the same
|
||||||
|
naming scheme). This function wraps any defaults setting and looping over
|
||||||
|
all options to create a configured `config`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// newConfig returns an appropriately configured config.
|
||||||
|
func newConfig([]Option) config {
|
||||||
|
// Set default values for config.
|
||||||
|
config := config{/* […] */}
|
||||||
|
for _, option := range options {
|
||||||
|
option.apply(&config)
|
||||||
|
}
|
||||||
|
// Preform any validation here.
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If validation of the `config` options is also preformed this can return an
|
||||||
|
error as well that is expected to be handled by the instantiation function
|
||||||
|
or propagated to the user.
|
||||||
|
|
||||||
|
Given the design goal of not having the user need to work with the `config`,
|
||||||
|
the `newConfig` function should also be unexported.
|
||||||
|
|
||||||
|
#### `Option`
|
||||||
|
|
||||||
|
To set the value of the options a `config` contains, a corresponding
|
||||||
|
`Option` interface type should be used.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Option interface {
|
||||||
|
apply(*config)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Having `apply` unexported makes sure that it will not be used externally.
|
||||||
|
Moreover, the interface becomes sealed so the user cannot easily implement
|
||||||
|
the interface on its own.
|
||||||
|
|
||||||
|
The name of the interface should be prefixed in the same way the
|
||||||
|
corresponding `config` is (if at all).
|
||||||
|
|
||||||
|
#### Options
|
||||||
|
|
||||||
|
All user configurable options for a `config` must have a related unexported
|
||||||
|
implementation of the `Option` interface and an exported configuration
|
||||||
|
function that wraps this implementation.
|
||||||
|
|
||||||
|
The wrapping function name should be prefixed with `With*` (or in the
|
||||||
|
special case of a boolean options `Without*`) and should have the following
|
||||||
|
function signature.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func With*(…) Option { … }
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `bool` Options
|
||||||
|
|
||||||
|
```go
|
||||||
|
type defaultFalseOption bool
|
||||||
|
|
||||||
|
func (o defaultFalseOption) apply(c *config) {
|
||||||
|
c.Bool = bool(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithOption sets a T to have an option included.
|
||||||
|
func WithOption() Option {
|
||||||
|
return defaultFalseOption(true)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
type defaultTrueOption bool
|
||||||
|
|
||||||
|
func (o defaultTrueOption) apply(c *config) {
|
||||||
|
c.Bool = bool(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithoutOption sets a T to have Bool option excluded.
|
||||||
|
func WithoutOption() Option {
|
||||||
|
return defaultTrueOption(false)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Declared Type Options
|
||||||
|
|
||||||
|
```go
|
||||||
|
type myTypeOption struct {
|
||||||
|
MyType MyType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o myTypeOption) apply(c *config) {
|
||||||
|
c.MyType = o.MyType
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMyType sets T to have include MyType.
|
||||||
|
func WithMyType(t MyType) Option {
|
||||||
|
return myTypeOption{t}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Functional Options
|
||||||
|
|
||||||
|
```go
|
||||||
|
type optionFunc func(*config)
|
||||||
|
|
||||||
|
func (fn optionFunc) apply(c *config) {
|
||||||
|
fn(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMyType sets t as MyType.
|
||||||
|
func WithMyType(t MyType) Option {
|
||||||
|
return optionFunc(func(c *config) {
|
||||||
|
c.MyType = t
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Instantiation
|
||||||
|
|
||||||
|
Using this configuration pattern to configure instantiation with a `NewT`
|
||||||
|
function.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func NewT(options ...Option) T {…}
|
||||||
|
```
|
||||||
|
|
||||||
|
Any required parameters can be declared before the variadic `options`.
|
||||||
|
|
||||||
|
#### Dealing with Overlap
|
||||||
|
|
||||||
|
Sometimes there are multiple complex `struct` that share common
|
||||||
|
configuration and also have distinct configuration. To avoid repeated
|
||||||
|
portions of `config`s, a common `config` can be used with the union of
|
||||||
|
options being handled with the `Option` interface.
|
||||||
|
|
||||||
|
For example.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// config holds options for all animals.
|
||||||
|
type config struct {
|
||||||
|
Weight float64
|
||||||
|
Color string
|
||||||
|
MaxAltitude float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// DogOption apply Dog specific options.
|
||||||
|
type DogOption interface {
|
||||||
|
applyDog(*config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BirdOption apply Bird specific options.
|
||||||
|
type BirdOption interface {
|
||||||
|
applyBird(*config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option apply options for all animals.
|
||||||
|
type Option interface {
|
||||||
|
BirdOption
|
||||||
|
DogOption
|
||||||
|
}
|
||||||
|
|
||||||
|
type weightOption float64
|
||||||
|
func (o weightOption) applyDog(c *config) { c.Weight = float64(o) }
|
||||||
|
func (o weightOption) applyBird(c *config) { c.Weight = float64(o) }
|
||||||
|
func WithWeight(w float64) Option { return weightOption(w) }
|
||||||
|
|
||||||
|
type furColorOption string
|
||||||
|
func (o furColorOption) applyDog(c *config) { c.Color = string(o) }
|
||||||
|
func WithFurColor(c string) DogOption { return furColorOption(c) }
|
||||||
|
|
||||||
|
type maxAltitudeOption float64
|
||||||
|
func (o maxAltitudeOption) applyBird(c *config) { c.MaxAltitude = float64(o) }
|
||||||
|
func WithMaxAltitude(a float64) BirdOption { return maxAltitudeOption(a) }
|
||||||
|
|
||||||
|
func NewDog(name string, o ...DogOption) Dog {…}
|
||||||
|
func NewBird(name string, o ...BirdOption) Bird {…}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Interfaces
|
||||||
|
|
||||||
|
To allow other developers to better comprehend the code, it is important
|
||||||
|
to ensure it is sufficiently documented. One simple measure that contributes
|
||||||
|
to this aim is self-documenting by naming method parameters. Therefore,
|
||||||
|
where appropriate, methods of every exported interface type should have
|
||||||
|
their parameters appropriately named.
|
||||||
|
|
||||||
|
#### Interface Stability
|
||||||
|
|
||||||
|
All exported stable interfaces that include the following warning in their
|
||||||
|
doumentation are allowed to be extended with additional methods.
|
||||||
|
|
||||||
|
> Warning: methods may be added to this interface in minor releases.
|
||||||
|
|
||||||
|
Otherwise, stable interfaces MUST NOT be modified.
|
||||||
|
|
||||||
|
If new functionality is needed for an interface that cannot be changed it MUST
|
||||||
|
be added by including an additional interface. That added interface can be a
|
||||||
|
simple interface for the specific functionality that you want to add or it can
|
||||||
|
be a super-set of the original interface. For example, if you wanted to a
|
||||||
|
`Close` method to the `Exporter` interface:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Exporter interface {
|
||||||
|
Export()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A new interface, `Closer`, can be added:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Closer interface {
|
||||||
|
Close()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Code that is passed the `Exporter` interface can now check to see if the passed
|
||||||
|
value also satisfies the new interface. E.g.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func caller(e Exporter) {
|
||||||
|
/* ... */
|
||||||
|
if c, ok := e.(Closer); ok {
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, a new type that is the super-set of an `Exporter` can be created.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type ClosingExporter struct {
|
||||||
|
Exporter
|
||||||
|
Close()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This new type can be used similar to the simple interface above in that a
|
||||||
|
passed `Exporter` type can be asserted to satisfy the `ClosingExporter` type
|
||||||
|
and the `Close` method called.
|
||||||
|
|
||||||
|
This super-set approach can be useful if there is explicit behavior that needs
|
||||||
|
to be coupled with the original type and passed as a unified type to a new
|
||||||
|
function, but, because of this coupling, it also limits the applicability of
|
||||||
|
the added functionality. If there exist other interfaces where this
|
||||||
|
functionality should be added, each one will need their own super-set
|
||||||
|
interfaces and will duplicate the pattern. For this reason, the simple targeted
|
||||||
|
interface that defines the specific functionality should be preferred.
|
||||||
|
|
||||||
|
## Approvers and Maintainers
|
||||||
|
|
||||||
|
Approvers:
|
||||||
|
|
||||||
|
- [Evan Torrie](https://github.com/evantorrie), Verizon Media
|
||||||
|
- [Josh MacDonald](https://github.com/jmacd), LightStep
|
||||||
|
- [Sam Xie](https://github.com/XSAM)
|
||||||
|
- [David Ashpole](https://github.com/dashpole), Google
|
||||||
|
- [Gustavo Silva Paiva](https://github.com/paivagustavo), LightStep
|
||||||
|
- [Aaron Clawson](https://github.com/MadVikingGod)
|
||||||
|
- [Robert Pająk](https://github.com/pellared), Splunk
|
||||||
|
|
||||||
|
Maintainers:
|
||||||
|
|
||||||
|
- [Anthony Mirabella](https://github.com/Aneurysm9), AWS
|
||||||
|
- [Tyler Yahn](https://github.com/MrAlias), Splunk
|
||||||
|
|
||||||
|
### Become an Approver or a Maintainer
|
||||||
|
|
||||||
|
See the [community membership document in OpenTelemetry community
|
||||||
|
repo](https://github.com/open-telemetry/community/blob/main/community-membership.md).
|
||||||
201
vendor/go.opentelemetry.io/otel/LICENSE
generated
vendored
Normal file
201
vendor/go.opentelemetry.io/otel/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
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.
|
||||||
207
vendor/go.opentelemetry.io/otel/Makefile
generated
vendored
Normal file
207
vendor/go.opentelemetry.io/otel/Makefile
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
# Copyright The 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.
|
||||||
|
|
||||||
|
EXAMPLES := $(shell ./get_main_pkgs.sh ./example)
|
||||||
|
TOOLS_MOD_DIR := ./internal/tools
|
||||||
|
|
||||||
|
# All source code and documents. Used in spell check.
|
||||||
|
ALL_DOCS := $(shell find . -name '*.md' -type f | sort)
|
||||||
|
# All directories with go.mod files related to opentelemetry library. Used for building, testing and linting.
|
||||||
|
ALL_GO_MOD_DIRS := $(filter-out $(TOOLS_MOD_DIR), $(shell find . -type f -name 'go.mod' -exec dirname {} \; | egrep -v '^./example' | sort)) $(shell find ./example -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)
|
||||||
|
|
||||||
|
GO = go
|
||||||
|
TIMEOUT = 60
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := precommit
|
||||||
|
|
||||||
|
.PHONY: precommit ci
|
||||||
|
precommit: dependabot-check license-check lint build examples test-default
|
||||||
|
ci: precommit check-clean-work-tree test-coverage
|
||||||
|
|
||||||
|
# Tools
|
||||||
|
|
||||||
|
TOOLS = $(CURDIR)/.tools
|
||||||
|
|
||||||
|
$(TOOLS):
|
||||||
|
@mkdir -p $@
|
||||||
|
$(TOOLS)/%: | $(TOOLS)
|
||||||
|
cd $(TOOLS_MOD_DIR) && \
|
||||||
|
$(GO) build -o $@ $(PACKAGE)
|
||||||
|
|
||||||
|
MULTIMOD = $(TOOLS)/multimod
|
||||||
|
$(TOOLS)/multimod: PACKAGE=go.opentelemetry.io/build-tools/multimod
|
||||||
|
|
||||||
|
SEMCONVGEN = $(TOOLS)/semconvgen
|
||||||
|
$(TOOLS)/semconvgen: PACKAGE=go.opentelemetry.io/build-tools/semconvgen
|
||||||
|
|
||||||
|
CROSSLINK = $(TOOLS)/crosslink
|
||||||
|
$(TOOLS)/crosslink: PACKAGE=go.opentelemetry.io/otel/$(TOOLS_MOD_DIR)/crosslink
|
||||||
|
|
||||||
|
GOLANGCI_LINT = $(TOOLS)/golangci-lint
|
||||||
|
$(TOOLS)/golangci-lint: PACKAGE=github.com/golangci/golangci-lint/cmd/golangci-lint
|
||||||
|
|
||||||
|
MISSPELL = $(TOOLS)/misspell
|
||||||
|
$(TOOLS)/misspell: PACKAGE=github.com/client9/misspell/cmd/misspell
|
||||||
|
|
||||||
|
GOCOVMERGE = $(TOOLS)/gocovmerge
|
||||||
|
$(TOOLS)/gocovmerge: PACKAGE=github.com/wadey/gocovmerge
|
||||||
|
|
||||||
|
STRINGER = $(TOOLS)/stringer
|
||||||
|
$(TOOLS)/stringer: PACKAGE=golang.org/x/tools/cmd/stringer
|
||||||
|
|
||||||
|
PORTO = $(TOOLS)/porto
|
||||||
|
$(TOOLS)/porto: PACKAGE=github.com/jcchavezs/porto/cmd/porto
|
||||||
|
|
||||||
|
GOJQ = $(TOOLS)/gojq
|
||||||
|
$(TOOLS)/gojq: PACKAGE=github.com/itchyny/gojq/cmd/gojq
|
||||||
|
|
||||||
|
.PHONY: tools
|
||||||
|
tools: $(CROSSLINK) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(GOJQ) $(SEMCONVGEN) $(MULTIMOD)
|
||||||
|
|
||||||
|
# Build
|
||||||
|
|
||||||
|
.PHONY: examples generate build
|
||||||
|
examples:
|
||||||
|
@set -e; for dir in $(EXAMPLES); do \
|
||||||
|
echo "$(GO) build $${dir}/..."; \
|
||||||
|
(cd "$${dir}" && \
|
||||||
|
$(GO) build .); \
|
||||||
|
done
|
||||||
|
|
||||||
|
generate: $(STRINGER) $(PORTO)
|
||||||
|
set -e; for dir in $(ALL_GO_MOD_DIRS); do \
|
||||||
|
echo "$(GO) generate $${dir}/..."; \
|
||||||
|
(cd "$${dir}" && \
|
||||||
|
PATH="$(TOOLS):$${PATH}" $(GO) generate ./... && \
|
||||||
|
$(PORTO) -w .); \
|
||||||
|
done
|
||||||
|
|
||||||
|
build: generate
|
||||||
|
# Build all package code including testing code.
|
||||||
|
set -e; for dir in $(ALL_GO_MOD_DIRS); do \
|
||||||
|
echo "$(GO) build $${dir}/..."; \
|
||||||
|
(cd "$${dir}" && \
|
||||||
|
$(GO) build ./... && \
|
||||||
|
$(GO) list ./... \
|
||||||
|
| grep -v third_party \
|
||||||
|
| xargs $(GO) test -vet=off -run xxxxxMatchNothingxxxxx >/dev/null); \
|
||||||
|
done
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
|
||||||
|
TEST_TARGETS := test-default test-bench test-short test-verbose test-race
|
||||||
|
.PHONY: $(TEST_TARGETS) test
|
||||||
|
test-default: ARGS=-v -race
|
||||||
|
test-bench: ARGS=-run=xxxxxMatchNothingxxxxx -test.benchtime=1ms -bench=.
|
||||||
|
test-short: ARGS=-short
|
||||||
|
test-verbose: ARGS=-v
|
||||||
|
test-race: ARGS=-race
|
||||||
|
$(TEST_TARGETS): test
|
||||||
|
test:
|
||||||
|
@set -e; for dir in $(ALL_GO_MOD_DIRS); do \
|
||||||
|
echo "$(GO) test -timeout $(TIMEOUT)s $(ARGS) $${dir}/..."; \
|
||||||
|
(cd "$${dir}" && \
|
||||||
|
$(GO) list ./... \
|
||||||
|
| grep -v third_party \
|
||||||
|
| xargs $(GO) test -timeout $(TIMEOUT)s $(ARGS)); \
|
||||||
|
done
|
||||||
|
|
||||||
|
COVERAGE_MODE = atomic
|
||||||
|
COVERAGE_PROFILE = coverage.out
|
||||||
|
.PHONY: test-coverage
|
||||||
|
test-coverage: | $(GOCOVMERGE)
|
||||||
|
@set -e; \
|
||||||
|
printf "" > coverage.txt; \
|
||||||
|
for dir in $(ALL_COVERAGE_MOD_DIRS); do \
|
||||||
|
echo "$(GO) test -coverpkg=go.opentelemetry.io/otel/... -covermode=$(COVERAGE_MODE) -coverprofile="$(COVERAGE_PROFILE)" $${dir}/..."; \
|
||||||
|
(cd "$${dir}" && \
|
||||||
|
$(GO) list ./... \
|
||||||
|
| grep -v third_party \
|
||||||
|
| xargs $(GO) test -coverpkg=./... -covermode=$(COVERAGE_MODE) -coverprofile="$(COVERAGE_PROFILE)" && \
|
||||||
|
$(GO) tool cover -html=coverage.out -o coverage.html); \
|
||||||
|
done; \
|
||||||
|
$(GOCOVMERGE) $$(find . -name coverage.out) > coverage.txt
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: misspell lint-modules | $(GOLANGCI_LINT)
|
||||||
|
set -e; for dir in $(ALL_GO_MOD_DIRS); do \
|
||||||
|
echo "golangci-lint in $${dir}"; \
|
||||||
|
(cd "$${dir}" && \
|
||||||
|
$(GOLANGCI_LINT) run --fix && \
|
||||||
|
$(GOLANGCI_LINT) run); \
|
||||||
|
done
|
||||||
|
|
||||||
|
.PHONY: vanity-import-check
|
||||||
|
vanity-import-check: | $(PORTO)
|
||||||
|
$(PORTO) --include-internal -l .
|
||||||
|
|
||||||
|
.PHONY: misspell
|
||||||
|
misspell: | $(MISSPELL)
|
||||||
|
$(MISSPELL) -w $(ALL_DOCS)
|
||||||
|
|
||||||
|
.PHONY: lint-modules
|
||||||
|
lint-modules: | $(CROSSLINK)
|
||||||
|
set -e; for dir in $(ALL_GO_MOD_DIRS) $(TOOLS_MOD_DIR); do \
|
||||||
|
echo "$(GO) mod tidy in $${dir}"; \
|
||||||
|
(cd "$${dir}" && \
|
||||||
|
$(GO) mod tidy); \
|
||||||
|
done
|
||||||
|
echo "cross-linking all go modules"
|
||||||
|
$(CROSSLINK)
|
||||||
|
|
||||||
|
.PHONY: license-check
|
||||||
|
license-check:
|
||||||
|
@licRes=$$(for f in $$(find . -type f \( -iname '*.go' -o -iname '*.sh' \) ! -path '**/third_party/*') ; do \
|
||||||
|
awk '/Copyright The OpenTelemetry Authors|generated|GENERATED/ && NR<=3 { found=1; next } END { if (!found) print FILENAME }' $$f; \
|
||||||
|
done); \
|
||||||
|
if [ -n "$${licRes}" ]; then \
|
||||||
|
echo "license header checking failed:"; echo "$${licRes}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: dependabot-check
|
||||||
|
dependabot-check:
|
||||||
|
@result=$$( \
|
||||||
|
for f in $$( find . -type f -name go.mod -exec dirname {} \; | sed 's/^.//' ); \
|
||||||
|
do grep -q "directory: \+$$f" .github/dependabot.yml \
|
||||||
|
|| echo "$$f"; \
|
||||||
|
done; \
|
||||||
|
); \
|
||||||
|
if [ -n "$$result" ]; then \
|
||||||
|
echo "missing go.mod dependabot check:"; echo "$$result"; \
|
||||||
|
echo "new modules need to be added to the .github/dependabot.yml file"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: check-clean-work-tree
|
||||||
|
check-clean-work-tree:
|
||||||
|
@if ! git diff --quiet; then \
|
||||||
|
echo; \
|
||||||
|
echo 'Working tree is not clean, did you forget to run "make precommit"?'; \
|
||||||
|
echo; \
|
||||||
|
git status; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: prerelease
|
||||||
|
prerelease: | $(MULTIMOD)
|
||||||
|
@[ "${MODSET}" ] || ( echo ">> env var MODSET is not set"; exit 1 )
|
||||||
|
$(MULTIMOD) verify && $(MULTIMOD) prerelease -m ${MODSET}
|
||||||
|
|
||||||
|
COMMIT ?= "HEAD"
|
||||||
|
.PHONY: add-tags
|
||||||
|
add-tags: | $(MULTIMOD)
|
||||||
|
@[ "${MODSET}" ] || ( echo ">> env var MODSET is not set"; exit 1 )
|
||||||
|
$(MULTIMOD) verify && $(MULTIMOD) tag -m ${MODSET} -c ${COMMIT}
|
||||||
100
vendor/go.opentelemetry.io/otel/README.md
generated
vendored
Normal file
100
vendor/go.opentelemetry.io/otel/README.md
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# OpenTelemetry-Go
|
||||||
|
|
||||||
|
[](https://github.com/open-telemetry/opentelemetry-go/actions?query=workflow%3Aci+branch%3Amain)
|
||||||
|
[](https://app.codecov.io/gh/open-telemetry/opentelemetry-go?branch=main)
|
||||||
|
[](https://pkg.go.dev/go.opentelemetry.io/otel)
|
||||||
|
[](https://goreportcard.com/report/go.opentelemetry.io/otel)
|
||||||
|
[](https://cloud-native.slack.com/archives/C01NPAXACKT)
|
||||||
|
|
||||||
|
OpenTelemetry-Go is the [Go](https://golang.org/) implementation of [OpenTelemetry](https://opentelemetry.io/).
|
||||||
|
It provides a set of APIs to directly measure performance and behavior of your software and send this data to observability platforms.
|
||||||
|
|
||||||
|
## Project Status
|
||||||
|
|
||||||
|
| Signal | Status | Project |
|
||||||
|
| ------- | ---------- | ------- |
|
||||||
|
| Traces | Stable | N/A |
|
||||||
|
| Metrics | Alpha | N/A |
|
||||||
|
| Logs | Frozen [1] | N/A |
|
||||||
|
|
||||||
|
- [1]: The Logs signal development is halted for this project while we develop both Traces and Metrics.
|
||||||
|
No Logs Pull Requests are currently being accepted.
|
||||||
|
|
||||||
|
Progress and status specific to this repository is tracked in our local
|
||||||
|
[project boards](https://github.com/open-telemetry/opentelemetry-go/projects)
|
||||||
|
and
|
||||||
|
[milestones](https://github.com/open-telemetry/opentelemetry-go/milestones).
|
||||||
|
|
||||||
|
Project versioning information and stability guarantees can be found in the
|
||||||
|
[versioning documentation](./VERSIONING.md).
|
||||||
|
|
||||||
|
### Compatibility
|
||||||
|
|
||||||
|
This project is tested on the following systems.
|
||||||
|
|
||||||
|
| OS | Go Version | Architecture |
|
||||||
|
| ------- | ---------- | ------------ |
|
||||||
|
| Ubuntu | 1.17 | amd64 |
|
||||||
|
| Ubuntu | 1.16 | amd64 |
|
||||||
|
| Ubuntu | 1.15 | amd64 |
|
||||||
|
| Ubuntu | 1.17 | 386 |
|
||||||
|
| Ubuntu | 1.16 | 386 |
|
||||||
|
| Ubuntu | 1.15 | 386 |
|
||||||
|
| MacOS | 1.17 | amd64 |
|
||||||
|
| MacOS | 1.16 | amd64 |
|
||||||
|
| MacOS | 1.15 | amd64 |
|
||||||
|
| Windows | 1.17 | amd64 |
|
||||||
|
| Windows | 1.16 | amd64 |
|
||||||
|
| Windows | 1.15 | amd64 |
|
||||||
|
| Windows | 1.17 | 386 |
|
||||||
|
| Windows | 1.16 | 386 |
|
||||||
|
| Windows | 1.15 | 386 |
|
||||||
|
|
||||||
|
While this project should work for other systems, no compatibility guarantees
|
||||||
|
are made for those systems currently.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
You can find a getting started guide on [opentelemetry.io](https://opentelemetry.io/docs/go/getting-started/).
|
||||||
|
|
||||||
|
OpenTelemetry's goal is to provide a single set of APIs to capture distributed
|
||||||
|
traces and metrics from your application and send them to an observability
|
||||||
|
platform. This project allows you to do just that for applications written in
|
||||||
|
Go. There are two steps to this process: instrument your application, and
|
||||||
|
configure an exporter.
|
||||||
|
|
||||||
|
### Instrumentation
|
||||||
|
|
||||||
|
To start capturing distributed traces and metric events from your application
|
||||||
|
it first needs to be instrumented. The easiest way to do this is by using an
|
||||||
|
instrumentation library for your code. Be sure to check out [the officially
|
||||||
|
supported instrumentation
|
||||||
|
libraries](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation).
|
||||||
|
|
||||||
|
If you need to extend the telemetry an instrumentation library provides or want
|
||||||
|
to build your own instrumentation for your application directly you will need
|
||||||
|
to use the
|
||||||
|
[go.opentelemetry.io/otel/api](https://pkg.go.dev/go.opentelemetry.io/otel/api)
|
||||||
|
package. The included [examples](./example/) are a good way to see some
|
||||||
|
practical uses of this process.
|
||||||
|
|
||||||
|
### Export
|
||||||
|
|
||||||
|
Now that your application is instrumented to collect telemetry, it needs an
|
||||||
|
export pipeline to send that telemetry to an observability platform.
|
||||||
|
|
||||||
|
All officially supported exporters for the OpenTelemetry project are contained in the [exporters directory](./exporters).
|
||||||
|
|
||||||
|
| Exporter | Metrics | Traces |
|
||||||
|
| :-----------------------------------: | :-----: | :----: |
|
||||||
|
| [Jaeger](./exporters/jaeger/) | | ✓ |
|
||||||
|
| [OTLP](./exporters/otlp/) | ✓ | ✓ |
|
||||||
|
| [Prometheus](./exporters/prometheus/) | ✓ | |
|
||||||
|
| [stdout](./exporters/stdout/) | ✓ | ✓ |
|
||||||
|
| [Zipkin](./exporters/zipkin/) | | ✓ |
|
||||||
|
|
||||||
|
Additionally, OpenTelemetry community supported exporters can be found in the [contrib repository](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/exporters).
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
See the [contributing documentation](CONTRIBUTING.md).
|
||||||
133
vendor/go.opentelemetry.io/otel/RELEASING.md
generated
vendored
Normal file
133
vendor/go.opentelemetry.io/otel/RELEASING.md
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
# Release Process
|
||||||
|
|
||||||
|
## Semantic Convention Generation
|
||||||
|
|
||||||
|
If a new version of the OpenTelemetry Specification has been released it will be necessary to generate a new
|
||||||
|
semantic convention package from the YAML definitions in the specification repository. There is a `semconvgen` utility
|
||||||
|
installed by `make tools` that can be used to generate the a package with the name matching the specification
|
||||||
|
version number under the `semconv` package. This will ideally be done soon after the specification release is
|
||||||
|
tagged. Make sure that the specification repo contains a checkout of the the latest tagged release so that the
|
||||||
|
generated files match the released semantic conventions.
|
||||||
|
|
||||||
|
There are currently two categories of semantic conventions that must be generated, `resource` and `trace`.
|
||||||
|
|
||||||
|
```
|
||||||
|
.tools/semconvgen -i /path/to/specification/repo/semantic_conventions/resource -t semconv/template.j2
|
||||||
|
.tools/semconvgen -i /path/to/specification/repo/semantic_conventions/trace -t semconv/template.j2
|
||||||
|
```
|
||||||
|
|
||||||
|
Using default values for all options other than `input` will result in using the `template.j2` template to
|
||||||
|
generate `resource.go` and `trace.go` in `/path/to/otelgo/repo/semconv/<version>`.
|
||||||
|
|
||||||
|
There are several ancillary files that are not generated and should be copied into the new package from the
|
||||||
|
prior package, with updates made as appropriate to canonical import path statements and constant values.
|
||||||
|
These files include:
|
||||||
|
|
||||||
|
* doc.go
|
||||||
|
* exception.go
|
||||||
|
* http(_test)?.go
|
||||||
|
* schema.go
|
||||||
|
|
||||||
|
Uses of the previous schema version in this repository should be updated to use the newly generated version.
|
||||||
|
No tooling for this exists at present, so use find/replace in your editor of choice or craft a `grep | sed`
|
||||||
|
pipeline if you like living on the edge.
|
||||||
|
|
||||||
|
## Pre-Release
|
||||||
|
|
||||||
|
First, decide which module sets will be released and update their versions
|
||||||
|
in `versions.yaml`. Commit this change to a new branch.
|
||||||
|
|
||||||
|
Update go.mod for submodules to depend on the new release which will happen in the next step.
|
||||||
|
|
||||||
|
1. Run the `prerelease` make target. It creates a branch
|
||||||
|
`prerelease_<module set>_<new tag>` that will contain all release changes.
|
||||||
|
|
||||||
|
```
|
||||||
|
make prerelease MODSET=<module set>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verify the changes.
|
||||||
|
|
||||||
|
```
|
||||||
|
git diff ...prerelease_<module set>_<new tag>
|
||||||
|
```
|
||||||
|
|
||||||
|
This should have changed the version for all modules to be `<new tag>`.
|
||||||
|
If these changes look correct, merge them into your pre-release branch:
|
||||||
|
|
||||||
|
```go
|
||||||
|
git merge prerelease_<module set>_<new tag>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Update the [Changelog](./CHANGELOG.md).
|
||||||
|
- Make sure all relevant changes for this release are included and are in language that non-contributors to the project can understand.
|
||||||
|
To verify this, you can look directly at the commits since the `<last tag>`.
|
||||||
|
|
||||||
|
```
|
||||||
|
git --no-pager log --pretty=oneline "<last tag>..HEAD"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Move all the `Unreleased` changes into a new section following the title scheme (`[<new tag>] - <date of release>`).
|
||||||
|
- Update all the appropriate links at the bottom.
|
||||||
|
|
||||||
|
4. Push the changes to upstream and create a Pull Request on GitHub.
|
||||||
|
Be sure to include the curated changes from the [Changelog](./CHANGELOG.md) in the description.
|
||||||
|
|
||||||
|
## Tag
|
||||||
|
|
||||||
|
Once the Pull Request with all the version changes has been approved and merged it is time to tag the merged commit.
|
||||||
|
|
||||||
|
***IMPORTANT***: It is critical you use the same tag that you used in the Pre-Release step!
|
||||||
|
Failure to do so will leave things in a broken state. As long as you do not
|
||||||
|
change `versions.yaml` between pre-release and this step, things should be fine.
|
||||||
|
|
||||||
|
***IMPORTANT***: [There is currently no way to remove an incorrectly tagged version of a Go module](https://github.com/golang/go/issues/34189).
|
||||||
|
It is critical you make sure the version you push upstream is correct.
|
||||||
|
[Failure to do so will lead to minor emergencies and tough to work around](https://github.com/open-telemetry/opentelemetry-go/issues/331).
|
||||||
|
|
||||||
|
1. For each module set that will be released, run the `add-tags` make target
|
||||||
|
using the `<commit-hash>` of the commit on the main branch for the merged Pull Request.
|
||||||
|
|
||||||
|
```
|
||||||
|
make add-tags MODSET=<module set> COMMIT=<commit hash>
|
||||||
|
```
|
||||||
|
|
||||||
|
It should only be necessary to provide an explicit `COMMIT` value if the
|
||||||
|
current `HEAD` of your working directory is not the correct commit.
|
||||||
|
|
||||||
|
2. Push tags to the upstream remote (not your fork: `github.com/open-telemetry/opentelemetry-go.git`).
|
||||||
|
Make sure you push all sub-modules as well.
|
||||||
|
|
||||||
|
```
|
||||||
|
git push upstream <new tag>
|
||||||
|
git push upstream <submodules-path/new tag>
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Release
|
||||||
|
|
||||||
|
Finally create a Release for the new `<new tag>` on GitHub.
|
||||||
|
The release body should include all the release notes from the Changelog for this release.
|
||||||
|
Additionally, the `tag.sh` script generates commit logs since last release which can be used to supplement the release notes.
|
||||||
|
|
||||||
|
## Verify Examples
|
||||||
|
|
||||||
|
After releasing verify that examples build outside of the repository.
|
||||||
|
|
||||||
|
```
|
||||||
|
./verify_examples.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The script copies examples into a different directory removes any `replace` declarations in `go.mod` and builds them.
|
||||||
|
This ensures they build with the published release, not the local copy.
|
||||||
|
|
||||||
|
## Post-Release
|
||||||
|
|
||||||
|
### Contrib Repository
|
||||||
|
|
||||||
|
Once verified be sure to [make a release for the `contrib` repository](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/RELEASING.md) that uses this release.
|
||||||
|
|
||||||
|
### Website Documentation
|
||||||
|
|
||||||
|
Update [the documentation](./website_docs) for [the OpenTelemetry website](https://opentelemetry.io/docs/go/).
|
||||||
|
Importantly, bump any package versions referenced to be the latest one you just released and ensure all code examples still compile and are accurate.
|
||||||
224
vendor/go.opentelemetry.io/otel/VERSIONING.md
generated
vendored
Normal file
224
vendor/go.opentelemetry.io/otel/VERSIONING.md
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
# Versioning
|
||||||
|
|
||||||
|
This document describes the versioning policy for this repository. This policy
|
||||||
|
is designed so the following goals can be achieved.
|
||||||
|
|
||||||
|
**Users are provided a codebase of value that is stable and secure.**
|
||||||
|
|
||||||
|
## Policy
|
||||||
|
|
||||||
|
* Versioning of this project will be idiomatic of a Go project using [Go
|
||||||
|
modules](https://github.com/golang/go/wiki/Modules).
|
||||||
|
* [Semantic import
|
||||||
|
versioning](https://github.com/golang/go/wiki/Modules#semantic-import-versioning)
|
||||||
|
will be used.
|
||||||
|
* Versions will comply with [semver
|
||||||
|
2.0](https://semver.org/spec/v2.0.0.html) with the following exceptions.
|
||||||
|
* New methods may be added to exported API interfaces. All exported
|
||||||
|
interfaces that fall within this exception will include the following
|
||||||
|
paragraph in their public documentation.
|
||||||
|
|
||||||
|
> Warning: methods may be added to this interface in minor releases.
|
||||||
|
|
||||||
|
* If a module is version `v2` or higher, the major version of the module
|
||||||
|
must be included as a `/vN` at the end of the module paths used in
|
||||||
|
`go.mod` files (e.g., `module go.opentelemetry.io/otel/v2`, `require
|
||||||
|
go.opentelemetry.io/otel/v2 v2.0.1`) and in the package import path
|
||||||
|
(e.g., `import "go.opentelemetry.io/otel/v2/trace"`). This includes the
|
||||||
|
paths used in `go get` commands (e.g., `go get
|
||||||
|
go.opentelemetry.io/otel/v2@v2.0.1`. Note there is both a `/v2` and a
|
||||||
|
`@v2.0.1` in that example. One way to think about it is that the module
|
||||||
|
name now includes the `/v2`, so include `/v2` whenever you are using the
|
||||||
|
module name).
|
||||||
|
* If a module is version `v0` or `v1`, do not include the major version in
|
||||||
|
either the module path or the import path.
|
||||||
|
* Modules will be used to encapsulate signals and components.
|
||||||
|
* Experimental modules still under active development will be versioned at
|
||||||
|
`v0` to imply the stability guarantee defined by
|
||||||
|
[semver](https://semver.org/spec/v2.0.0.html#spec-item-4).
|
||||||
|
|
||||||
|
> Major version zero (0.y.z) is for initial development. Anything MAY
|
||||||
|
> change at any time. The public API SHOULD NOT be considered stable.
|
||||||
|
|
||||||
|
* Mature modules for which we guarantee a stable public API will be versioned
|
||||||
|
with a major version greater than `v0`.
|
||||||
|
* The decision to make a module stable will be made on a case-by-case
|
||||||
|
basis by the maintainers of this project.
|
||||||
|
* Experimental modules will start their versioning at `v0.0.0` and will
|
||||||
|
increment their minor version when backwards incompatible changes are
|
||||||
|
released and increment their patch version when backwards compatible
|
||||||
|
changes are released.
|
||||||
|
* All stable modules that use the same major version number will use the
|
||||||
|
same entire version number.
|
||||||
|
* Stable modules may be released with an incremented minor or patch
|
||||||
|
version even though that module has not been changed, but rather so
|
||||||
|
that it will remain at the same version as other stable modules that
|
||||||
|
did undergo change.
|
||||||
|
* When an experimental module becomes stable a new stable module version
|
||||||
|
will be released and will include this now stable module. The new
|
||||||
|
stable module version will be an increment of the minor version number
|
||||||
|
and will be applied to all existing stable modules as well as the newly
|
||||||
|
stable module being released.
|
||||||
|
* Versioning of the associated [contrib
|
||||||
|
repository](https://github.com/open-telemetry/opentelemetry-go-contrib) of
|
||||||
|
this project will be idiomatic of a Go project using [Go
|
||||||
|
modules](https://github.com/golang/go/wiki/Modules).
|
||||||
|
* [Semantic import
|
||||||
|
versioning](https://github.com/golang/go/wiki/Modules#semantic-import-versioning)
|
||||||
|
will be used.
|
||||||
|
* Versions will comply with [semver 2.0](https://semver.org/spec/v2.0.0.html).
|
||||||
|
* If a module is version `v2` or higher, the
|
||||||
|
major version of the module must be included as a `/vN` at the end of the
|
||||||
|
module paths used in `go.mod` files (e.g., `module
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/host/v2`, `require
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/host/v2 v2.0.1`) and in the
|
||||||
|
package import path (e.g., `import
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/host/v2"`). This includes
|
||||||
|
the paths used in `go get` commands (e.g., `go get
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/host/v2@v2.0.1`. Note there
|
||||||
|
is both a `/v2` and a `@v2.0.1` in that example. One way to think about
|
||||||
|
it is that the module name now includes the `/v2`, so include `/v2`
|
||||||
|
whenever you are using the module name).
|
||||||
|
* If a module is version `v0` or `v1`, do not include the major version
|
||||||
|
in either the module path or the import path.
|
||||||
|
* In addition to public APIs, telemetry produced by stable instrumentation
|
||||||
|
will remain stable and backwards compatible. This is to avoid breaking
|
||||||
|
alerts and dashboard.
|
||||||
|
* Modules will be used to encapsulate instrumentation, detectors, exporters,
|
||||||
|
propagators, and any other independent sets of related components.
|
||||||
|
* Experimental modules still under active development will be versioned at
|
||||||
|
`v0` to imply the stability guarantee defined by
|
||||||
|
[semver](https://semver.org/spec/v2.0.0.html#spec-item-4).
|
||||||
|
|
||||||
|
> Major version zero (0.y.z) is for initial development. Anything MAY
|
||||||
|
> change at any time. The public API SHOULD NOT be considered stable.
|
||||||
|
|
||||||
|
* Mature modules for which we guarantee a stable public API and telemetry will
|
||||||
|
be versioned with a major version greater than `v0`.
|
||||||
|
* Experimental modules will start their versioning at `v0.0.0` and will
|
||||||
|
increment their minor version when backwards incompatible changes are
|
||||||
|
released and increment their patch version when backwards compatible
|
||||||
|
changes are released.
|
||||||
|
* Stable contrib modules cannot depend on experimental modules from this
|
||||||
|
project.
|
||||||
|
* All stable contrib modules of the same major version with this project
|
||||||
|
will use the same entire version as this project.
|
||||||
|
* Stable modules may be released with an incremented minor or patch
|
||||||
|
version even though that module's code has not been changed. Instead
|
||||||
|
the only change that will have been included is to have updated that
|
||||||
|
modules dependency on this project's stable APIs.
|
||||||
|
* When an experimental module in contrib becomes stable a new stable
|
||||||
|
module version will be released and will include this now stable
|
||||||
|
module. The new stable module version will be an increment of the minor
|
||||||
|
version number and will be applied to all existing stable contrib
|
||||||
|
modules, this project's modules, and the newly stable module being
|
||||||
|
released.
|
||||||
|
* Contrib modules will be kept up to date with this project's releases.
|
||||||
|
* Due to the dependency contrib modules will implicitly have on this
|
||||||
|
project's modules the release of stable contrib modules to match the
|
||||||
|
released version number will be staggered after this project's release.
|
||||||
|
There is no explicit time guarantee for how long after this projects
|
||||||
|
release the contrib release will be. Effort should be made to keep them
|
||||||
|
as close in time as possible.
|
||||||
|
* No additional stable release in this project can be made until the
|
||||||
|
contrib repository has a matching stable release.
|
||||||
|
* No release can be made in the contrib repository after this project's
|
||||||
|
stable release except for a stable release of the contrib repository.
|
||||||
|
* GitHub releases will be made for all releases.
|
||||||
|
* Go modules will be made available at Go package mirrors.
|
||||||
|
|
||||||
|
## Example Versioning Lifecycle
|
||||||
|
|
||||||
|
To better understand the implementation of the above policy the following
|
||||||
|
example is provided. This project is simplified to include only the following
|
||||||
|
modules and their versions:
|
||||||
|
|
||||||
|
* `otel`: `v0.14.0`
|
||||||
|
* `otel/trace`: `v0.14.0`
|
||||||
|
* `otel/metric`: `v0.14.0`
|
||||||
|
* `otel/baggage`: `v0.14.0`
|
||||||
|
* `otel/sdk/trace`: `v0.14.0`
|
||||||
|
* `otel/sdk/metric`: `v0.14.0`
|
||||||
|
|
||||||
|
These modules have been developed to a point where the `otel/trace`,
|
||||||
|
`otel/baggage`, and `otel/sdk/trace` modules have reached a point that they
|
||||||
|
should be considered for a stable release. The `otel/metric` and
|
||||||
|
`otel/sdk/metric` are still under active development and the `otel` module
|
||||||
|
depends on both `otel/trace` and `otel/metric`.
|
||||||
|
|
||||||
|
The `otel` package is refactored to remove its dependencies on `otel/metric` so
|
||||||
|
it can be released as stable as well. With that done the following release
|
||||||
|
candidates are made:
|
||||||
|
|
||||||
|
* `otel`: `v1.0.0-RC1`
|
||||||
|
* `otel/trace`: `v1.0.0-RC1`
|
||||||
|
* `otel/baggage`: `v1.0.0-RC1`
|
||||||
|
* `otel/sdk/trace`: `v1.0.0-RC1`
|
||||||
|
|
||||||
|
The `otel/metric` and `otel/sdk/metric` modules remain at `v0.14.0`.
|
||||||
|
|
||||||
|
A few minor issues are discovered in the `otel/trace` package. These issues are
|
||||||
|
resolved with some minor, but backwards incompatible, changes and are released
|
||||||
|
as a second release candidate:
|
||||||
|
|
||||||
|
* `otel`: `v1.0.0-RC2`
|
||||||
|
* `otel/trace`: `v1.0.0-RC2`
|
||||||
|
* `otel/baggage`: `v1.0.0-RC2`
|
||||||
|
* `otel/sdk/trace`: `v1.0.0-RC2`
|
||||||
|
|
||||||
|
Notice that all module version numbers are incremented to adhere to our
|
||||||
|
versioning policy.
|
||||||
|
|
||||||
|
After these release candidates have been evaluated to satisfaction, they are
|
||||||
|
released as version `v1.0.0`.
|
||||||
|
|
||||||
|
* `otel`: `v1.0.0`
|
||||||
|
* `otel/trace`: `v1.0.0`
|
||||||
|
* `otel/baggage`: `v1.0.0`
|
||||||
|
* `otel/sdk/trace`: `v1.0.0`
|
||||||
|
|
||||||
|
Since both the `go` utility and the Go module system support [the semantic
|
||||||
|
versioning definition of
|
||||||
|
precedence](https://semver.org/spec/v2.0.0.html#spec-item-11), this release
|
||||||
|
will correctly be interpreted as the successor to the previous release
|
||||||
|
candidates.
|
||||||
|
|
||||||
|
Active development of this project continues. The `otel/metric` module now has
|
||||||
|
backwards incompatible changes to its API that need to be released and the
|
||||||
|
`otel/baggage` module has a minor bug fix that needs to be released. The
|
||||||
|
following release is made:
|
||||||
|
|
||||||
|
* `otel`: `v1.0.1`
|
||||||
|
* `otel/trace`: `v1.0.1`
|
||||||
|
* `otel/metric`: `v0.15.0`
|
||||||
|
* `otel/baggage`: `v1.0.1`
|
||||||
|
* `otel/sdk/trace`: `v1.0.1`
|
||||||
|
* `otel/sdk/metric`: `v0.15.0`
|
||||||
|
|
||||||
|
Notice that, again, all stable module versions are incremented in unison and
|
||||||
|
the `otel/sdk/metric` package, which depends on the `otel/metric` package, also
|
||||||
|
bumped its version. This bump of the `otel/sdk/metric` package makes sense
|
||||||
|
given their coupling, though it is not explicitly required by our versioning
|
||||||
|
policy.
|
||||||
|
|
||||||
|
As we progress, the `otel/metric` and `otel/sdk/metric` packages have reached a
|
||||||
|
point where they should be evaluated for stability. The `otel` module is
|
||||||
|
reintegrated with the `otel/metric` package and the following release is made:
|
||||||
|
|
||||||
|
* `otel`: `v1.1.0-RC1`
|
||||||
|
* `otel/trace`: `v1.1.0-RC1`
|
||||||
|
* `otel/metric`: `v1.1.0-RC1`
|
||||||
|
* `otel/baggage`: `v1.1.0-RC1`
|
||||||
|
* `otel/sdk/trace`: `v1.1.0-RC1`
|
||||||
|
* `otel/sdk/metric`: `v1.1.0-RC1`
|
||||||
|
|
||||||
|
All the modules are evaluated and determined to a viable stable release. They
|
||||||
|
are then released as version `v1.1.0` (the minor version is incremented to
|
||||||
|
indicate the addition of new signal).
|
||||||
|
|
||||||
|
* `otel`: `v1.1.0`
|
||||||
|
* `otel/trace`: `v1.1.0`
|
||||||
|
* `otel/metric`: `v1.1.0`
|
||||||
|
* `otel/baggage`: `v1.1.0`
|
||||||
|
* `otel/sdk/trace`: `v1.1.0`
|
||||||
|
* `otel/sdk/metric`: `v1.1.0`
|
||||||
16
vendor/go.opentelemetry.io/otel/attribute/doc.go
generated
vendored
Normal file
16
vendor/go.opentelemetry.io/otel/attribute/doc.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright The 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 attribute provides key and value attributes.
|
||||||
|
package attribute // import "go.opentelemetry.io/otel/attribute"
|
||||||
150
vendor/go.opentelemetry.io/otel/attribute/encoder.go
generated
vendored
Normal file
150
vendor/go.opentelemetry.io/otel/attribute/encoder.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
// Copyright The 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 attribute // import "go.opentelemetry.io/otel/attribute"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Encoder is a mechanism for serializing a label set into a
|
||||||
|
// specific string representation that supports caching, to
|
||||||
|
// avoid repeated serialization. An example could be an
|
||||||
|
// exporter encoding the label set into a wire representation.
|
||||||
|
Encoder interface {
|
||||||
|
// Encode returns the serialized encoding of the label
|
||||||
|
// set using its Iterator. This result may be cached
|
||||||
|
// by a attribute.Set.
|
||||||
|
Encode(iterator Iterator) string
|
||||||
|
|
||||||
|
// ID returns a value that is unique for each class of
|
||||||
|
// label encoder. Label encoders allocate these using
|
||||||
|
// `NewEncoderID`.
|
||||||
|
ID() EncoderID
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncoderID is used to identify distinct Encoder
|
||||||
|
// implementations, for caching encoded results.
|
||||||
|
EncoderID struct {
|
||||||
|
value uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultLabelEncoder uses a sync.Pool of buffers to reduce
|
||||||
|
// the number of allocations used in encoding labels. This
|
||||||
|
// implementation encodes a comma-separated list of key=value,
|
||||||
|
// with '/'-escaping of '=', ',', and '\'.
|
||||||
|
defaultLabelEncoder struct {
|
||||||
|
// pool is a pool of labelset builders. The buffers in this
|
||||||
|
// pool grow to a size that most label encodings will not
|
||||||
|
// allocate new memory.
|
||||||
|
pool sync.Pool // *bytes.Buffer
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// escapeChar is used to ensure uniqueness of the label encoding where
|
||||||
|
// keys or values contain either '=' or ','. Since there is no parser
|
||||||
|
// needed for this encoding and its only requirement is to be unique,
|
||||||
|
// this choice is arbitrary. Users will see these in some exporters
|
||||||
|
// (e.g., stdout), so the backslash ('\') is used as a conventional choice.
|
||||||
|
const escapeChar = '\\'
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ Encoder = &defaultLabelEncoder{}
|
||||||
|
|
||||||
|
// encoderIDCounter is for generating IDs for other label
|
||||||
|
// encoders.
|
||||||
|
encoderIDCounter uint64
|
||||||
|
|
||||||
|
defaultEncoderOnce sync.Once
|
||||||
|
defaultEncoderID = NewEncoderID()
|
||||||
|
defaultEncoderInstance *defaultLabelEncoder
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewEncoderID returns a unique label encoder ID. It should be
|
||||||
|
// called once per each type of label encoder. Preferably in init() or
|
||||||
|
// in var definition.
|
||||||
|
func NewEncoderID() EncoderID {
|
||||||
|
return EncoderID{value: atomic.AddUint64(&encoderIDCounter, 1)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultEncoder returns a label encoder that encodes labels
|
||||||
|
// in such a way that each escaped label's key is followed by an equal
|
||||||
|
// sign and then by an escaped label's value. All key-value pairs are
|
||||||
|
// separated by a comma.
|
||||||
|
//
|
||||||
|
// Escaping is done by prepending a backslash before either a
|
||||||
|
// backslash, equal sign or a comma.
|
||||||
|
func DefaultEncoder() Encoder {
|
||||||
|
defaultEncoderOnce.Do(func() {
|
||||||
|
defaultEncoderInstance = &defaultLabelEncoder{
|
||||||
|
pool: sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return &bytes.Buffer{}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return defaultEncoderInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode is a part of an implementation of the LabelEncoder
|
||||||
|
// interface.
|
||||||
|
func (d *defaultLabelEncoder) Encode(iter Iterator) string {
|
||||||
|
buf := d.pool.Get().(*bytes.Buffer)
|
||||||
|
defer d.pool.Put(buf)
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
for iter.Next() {
|
||||||
|
i, keyValue := iter.IndexedLabel()
|
||||||
|
if i > 0 {
|
||||||
|
_, _ = buf.WriteRune(',')
|
||||||
|
}
|
||||||
|
copyAndEscape(buf, string(keyValue.Key))
|
||||||
|
|
||||||
|
_, _ = buf.WriteRune('=')
|
||||||
|
|
||||||
|
if keyValue.Value.Type() == STRING {
|
||||||
|
copyAndEscape(buf, keyValue.Value.AsString())
|
||||||
|
} else {
|
||||||
|
_, _ = buf.WriteString(keyValue.Value.Emit())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID is a part of an implementation of the LabelEncoder interface.
|
||||||
|
func (*defaultLabelEncoder) ID() EncoderID {
|
||||||
|
return defaultEncoderID
|
||||||
|
}
|
||||||
|
|
||||||
|
// copyAndEscape escapes `=`, `,` and its own escape character (`\`),
|
||||||
|
// making the default encoding unique.
|
||||||
|
func copyAndEscape(buf *bytes.Buffer, val string) {
|
||||||
|
for _, ch := range val {
|
||||||
|
switch ch {
|
||||||
|
case '=', ',', escapeChar:
|
||||||
|
buf.WriteRune(escapeChar)
|
||||||
|
}
|
||||||
|
buf.WriteRune(ch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid returns true if this encoder ID was allocated by
|
||||||
|
// `NewEncoderID`. Invalid encoder IDs will not be cached.
|
||||||
|
func (id EncoderID) Valid() bool {
|
||||||
|
return id.value != 0
|
||||||
|
}
|
||||||
143
vendor/go.opentelemetry.io/otel/attribute/iterator.go
generated
vendored
Normal file
143
vendor/go.opentelemetry.io/otel/attribute/iterator.go
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
// Copyright The 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 attribute // import "go.opentelemetry.io/otel/attribute"
|
||||||
|
|
||||||
|
// Iterator allows iterating over the set of labels in order,
|
||||||
|
// sorted by key.
|
||||||
|
type Iterator struct {
|
||||||
|
storage *Set
|
||||||
|
idx int
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeIterator supports iterating over two sets of labels while
|
||||||
|
// eliminating duplicate values from the combined set. The first
|
||||||
|
// iterator value takes precedence.
|
||||||
|
type MergeIterator struct {
|
||||||
|
one oneIterator
|
||||||
|
two oneIterator
|
||||||
|
current KeyValue
|
||||||
|
}
|
||||||
|
|
||||||
|
type oneIterator struct {
|
||||||
|
iter Iterator
|
||||||
|
done bool
|
||||||
|
label KeyValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next position. Returns false if there
|
||||||
|
// are no more labels.
|
||||||
|
func (i *Iterator) Next() bool {
|
||||||
|
i.idx++
|
||||||
|
return i.idx < i.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label returns current KeyValue. Must be called only after Next returns
|
||||||
|
// true.
|
||||||
|
func (i *Iterator) Label() KeyValue {
|
||||||
|
kv, _ := i.storage.Get(i.idx)
|
||||||
|
return kv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attribute is a synonym for Label().
|
||||||
|
func (i *Iterator) Attribute() KeyValue {
|
||||||
|
return i.Label()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexedLabel returns current index and attribute. Must be called only
|
||||||
|
// after Next returns true.
|
||||||
|
func (i *Iterator) IndexedLabel() (int, KeyValue) {
|
||||||
|
return i.idx, i.Label()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns a number of labels in the iterator's `*Set`.
|
||||||
|
func (i *Iterator) Len() int {
|
||||||
|
return i.storage.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToSlice is a convenience function that creates a slice of labels
|
||||||
|
// from the passed iterator. The iterator is set up to start from the
|
||||||
|
// beginning before creating the slice.
|
||||||
|
func (i *Iterator) ToSlice() []KeyValue {
|
||||||
|
l := i.Len()
|
||||||
|
if l == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
i.idx = -1
|
||||||
|
slice := make([]KeyValue, 0, l)
|
||||||
|
for i.Next() {
|
||||||
|
slice = append(slice, i.Label())
|
||||||
|
}
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMergeIterator returns a MergeIterator for merging two label sets
|
||||||
|
// Duplicates are resolved by taking the value from the first set.
|
||||||
|
func NewMergeIterator(s1, s2 *Set) MergeIterator {
|
||||||
|
mi := MergeIterator{
|
||||||
|
one: makeOne(s1.Iter()),
|
||||||
|
two: makeOne(s2.Iter()),
|
||||||
|
}
|
||||||
|
return mi
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeOne(iter Iterator) oneIterator {
|
||||||
|
oi := oneIterator{
|
||||||
|
iter: iter,
|
||||||
|
}
|
||||||
|
oi.advance()
|
||||||
|
return oi
|
||||||
|
}
|
||||||
|
|
||||||
|
func (oi *oneIterator) advance() {
|
||||||
|
if oi.done = !oi.iter.Next(); !oi.done {
|
||||||
|
oi.label = oi.iter.Label()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns true if there is another label available.
|
||||||
|
func (m *MergeIterator) Next() bool {
|
||||||
|
if m.one.done && m.two.done {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if m.one.done {
|
||||||
|
m.current = m.two.label
|
||||||
|
m.two.advance()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if m.two.done {
|
||||||
|
m.current = m.one.label
|
||||||
|
m.one.advance()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if m.one.label.Key == m.two.label.Key {
|
||||||
|
m.current = m.one.label // first iterator label value wins
|
||||||
|
m.one.advance()
|
||||||
|
m.two.advance()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if m.one.label.Key < m.two.label.Key {
|
||||||
|
m.current = m.one.label
|
||||||
|
m.one.advance()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
m.current = m.two.label
|
||||||
|
m.two.advance()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label returns the current value after Next() returns true.
|
||||||
|
func (m *MergeIterator) Label() KeyValue {
|
||||||
|
return m.current
|
||||||
|
}
|
||||||
134
vendor/go.opentelemetry.io/otel/attribute/key.go
generated
vendored
Normal file
134
vendor/go.opentelemetry.io/otel/attribute/key.go
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
// Copyright The 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 attribute // import "go.opentelemetry.io/otel/attribute"
|
||||||
|
|
||||||
|
// Key represents the key part in key-value pairs. It's a string. The
|
||||||
|
// allowed character set in the key depends on the use of the key.
|
||||||
|
type Key string
|
||||||
|
|
||||||
|
// Bool creates a KeyValue instance with a BOOL Value.
|
||||||
|
//
|
||||||
|
// If creating both a key and value at the same time, use the provided
|
||||||
|
// convenience function instead -- Bool(name, value).
|
||||||
|
func (k Key) Bool(v bool) KeyValue {
|
||||||
|
return KeyValue{
|
||||||
|
Key: k,
|
||||||
|
Value: BoolValue(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSlice creates a KeyValue instance with a BOOLSLICE Value.
|
||||||
|
//
|
||||||
|
// If creating both a key and value at the same time, use the provided
|
||||||
|
// convenience function instead -- BoolSlice(name, value).
|
||||||
|
func (k Key) BoolSlice(v []bool) KeyValue {
|
||||||
|
return KeyValue{
|
||||||
|
Key: k,
|
||||||
|
Value: BoolSliceValue(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int creates a KeyValue instance with an INT64 Value.
|
||||||
|
//
|
||||||
|
// If creating both a key and value at the same time, use the provided
|
||||||
|
// convenience function instead -- Int(name, value).
|
||||||
|
func (k Key) Int(v int) KeyValue {
|
||||||
|
return KeyValue{
|
||||||
|
Key: k,
|
||||||
|
Value: IntValue(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntSlice creates a KeyValue instance with an INT64SLICE Value.
|
||||||
|
//
|
||||||
|
// If creating both a key and value at the same time, use the provided
|
||||||
|
// convenience function instead -- IntSlice(name, value).
|
||||||
|
func (k Key) IntSlice(v []int) KeyValue {
|
||||||
|
return KeyValue{
|
||||||
|
Key: k,
|
||||||
|
Value: IntSliceValue(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 creates a KeyValue instance with an INT64 Value.
|
||||||
|
//
|
||||||
|
// If creating both a key and value at the same time, use the provided
|
||||||
|
// convenience function instead -- Int64(name, value).
|
||||||
|
func (k Key) Int64(v int64) KeyValue {
|
||||||
|
return KeyValue{
|
||||||
|
Key: k,
|
||||||
|
Value: Int64Value(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Slice creates a KeyValue instance with an INT64SLICE Value.
|
||||||
|
//
|
||||||
|
// If creating both a key and value at the same time, use the provided
|
||||||
|
// convenience function instead -- Int64Slice(name, value).
|
||||||
|
func (k Key) Int64Slice(v []int64) KeyValue {
|
||||||
|
return KeyValue{
|
||||||
|
Key: k,
|
||||||
|
Value: Int64SliceValue(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 creates a KeyValue instance with a FLOAT64 Value.
|
||||||
|
//
|
||||||
|
// If creating both a key and value at the same time, use the provided
|
||||||
|
// convenience function instead -- Float64(name, value).
|
||||||
|
func (k Key) Float64(v float64) KeyValue {
|
||||||
|
return KeyValue{
|
||||||
|
Key: k,
|
||||||
|
Value: Float64Value(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Slice creates a KeyValue instance with a FLOAT64SLICE Value.
|
||||||
|
//
|
||||||
|
// If creating both a key and value at the same time, use the provided
|
||||||
|
// convenience function instead -- Float64(name, value).
|
||||||
|
func (k Key) Float64Slice(v []float64) KeyValue {
|
||||||
|
return KeyValue{
|
||||||
|
Key: k,
|
||||||
|
Value: Float64SliceValue(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String creates a KeyValue instance with a STRING Value.
|
||||||
|
//
|
||||||
|
// If creating both a key and value at the same time, use the provided
|
||||||
|
// convenience function instead -- String(name, value).
|
||||||
|
func (k Key) String(v string) KeyValue {
|
||||||
|
return KeyValue{
|
||||||
|
Key: k,
|
||||||
|
Value: StringValue(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSlice creates a KeyValue instance with a STRINGSLICE Value.
|
||||||
|
//
|
||||||
|
// If creating both a key and value at the same time, use the provided
|
||||||
|
// convenience function instead -- StringSlice(name, value).
|
||||||
|
func (k Key) StringSlice(v []string) KeyValue {
|
||||||
|
return KeyValue{
|
||||||
|
Key: k,
|
||||||
|
Value: StringSliceValue(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defined returns true for non-empty keys.
|
||||||
|
func (k Key) Defined() bool {
|
||||||
|
return len(k) != 0
|
||||||
|
}
|
||||||
86
vendor/go.opentelemetry.io/otel/attribute/kv.go
generated
vendored
Normal file
86
vendor/go.opentelemetry.io/otel/attribute/kv.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
// Copyright The 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 attribute // import "go.opentelemetry.io/otel/attribute"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// KeyValue holds a key and value pair.
|
||||||
|
type KeyValue struct {
|
||||||
|
Key Key
|
||||||
|
Value Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid returns if kv is a valid OpenTelemetry attribute.
|
||||||
|
func (kv KeyValue) Valid() bool {
|
||||||
|
return kv.Key != "" && kv.Value.Type() != INVALID
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool creates a KeyValue with a BOOL Value type.
|
||||||
|
func Bool(k string, v bool) KeyValue {
|
||||||
|
return Key(k).Bool(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSlice creates a KeyValue with a BOOLSLICE Value type.
|
||||||
|
func BoolSlice(k string, v []bool) KeyValue {
|
||||||
|
return Key(k).BoolSlice(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int creates a KeyValue with an INT64 Value type.
|
||||||
|
func Int(k string, v int) KeyValue {
|
||||||
|
return Key(k).Int(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntSlice creates a KeyValue with an INT64SLICE Value type.
|
||||||
|
func IntSlice(k string, v []int) KeyValue {
|
||||||
|
return Key(k).IntSlice(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 creates a KeyValue with an INT64 Value type.
|
||||||
|
func Int64(k string, v int64) KeyValue {
|
||||||
|
return Key(k).Int64(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Slice creates a KeyValue with an INT64SLICE Value type.
|
||||||
|
func Int64Slice(k string, v []int64) KeyValue {
|
||||||
|
return Key(k).Int64Slice(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 creates a KeyValue with a FLOAT64 Value type.
|
||||||
|
func Float64(k string, v float64) KeyValue {
|
||||||
|
return Key(k).Float64(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Slice creates a KeyValue with a FLOAT64SLICE Value type.
|
||||||
|
func Float64Slice(k string, v []float64) KeyValue {
|
||||||
|
return Key(k).Float64Slice(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String creates a KeyValue with a STRING Value type.
|
||||||
|
func String(k, v string) KeyValue {
|
||||||
|
return Key(k).String(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSlice creates a KeyValue with a STRINGSLICE Value type.
|
||||||
|
func StringSlice(k string, v []string) KeyValue {
|
||||||
|
return Key(k).StringSlice(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stringer creates a new key-value pair with a passed name and a string
|
||||||
|
// value generated by the passed Stringer interface.
|
||||||
|
func Stringer(k string, v fmt.Stringer) KeyValue {
|
||||||
|
return Key(k).String(v.String())
|
||||||
|
}
|
||||||
426
vendor/go.opentelemetry.io/otel/attribute/set.go
generated
vendored
Normal file
426
vendor/go.opentelemetry.io/otel/attribute/set.go
generated
vendored
Normal file
@@ -0,0 +1,426 @@
|
|||||||
|
// Copyright The 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 attribute // import "go.opentelemetry.io/otel/attribute"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Set is the representation for a distinct label set. It
|
||||||
|
// manages an immutable set of labels, with an internal cache
|
||||||
|
// for storing label encodings.
|
||||||
|
//
|
||||||
|
// This type supports the `Equivalent` method of comparison
|
||||||
|
// using values of type `Distinct`.
|
||||||
|
//
|
||||||
|
// This type is used to implement:
|
||||||
|
// 1. Metric labels
|
||||||
|
// 2. Resource sets
|
||||||
|
// 3. Correlation map (TODO)
|
||||||
|
Set struct {
|
||||||
|
equivalent Distinct
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distinct wraps a variable-size array of `KeyValue`,
|
||||||
|
// constructed with keys in sorted order. This can be used as
|
||||||
|
// a map key or for equality checking between Sets.
|
||||||
|
Distinct struct {
|
||||||
|
iface interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter supports removing certain labels from label sets.
|
||||||
|
// When the filter returns true, the label will be kept in
|
||||||
|
// the filtered label set. When the filter returns false, the
|
||||||
|
// label is excluded from the filtered label set, and the
|
||||||
|
// label instead appears in the `removed` list of excluded labels.
|
||||||
|
Filter func(KeyValue) bool
|
||||||
|
|
||||||
|
// Sortable implements `sort.Interface`, used for sorting
|
||||||
|
// `KeyValue`. This is an exported type to support a
|
||||||
|
// memory optimization. A pointer to one of these is needed
|
||||||
|
// for the call to `sort.Stable()`, which the caller may
|
||||||
|
// provide in order to avoid an allocation. See
|
||||||
|
// `NewSetWithSortable()`.
|
||||||
|
Sortable []KeyValue
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// keyValueType is used in `computeDistinctReflect`.
|
||||||
|
keyValueType = reflect.TypeOf(KeyValue{})
|
||||||
|
|
||||||
|
// emptySet is returned for empty label sets.
|
||||||
|
emptySet = &Set{
|
||||||
|
equivalent: Distinct{
|
||||||
|
iface: [0]KeyValue{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// EmptySet returns a reference to a Set with no elements.
|
||||||
|
//
|
||||||
|
// This is a convenience provided for optimized calling utility.
|
||||||
|
func EmptySet() *Set {
|
||||||
|
return emptySet
|
||||||
|
}
|
||||||
|
|
||||||
|
// reflect abbreviates `reflect.ValueOf`.
|
||||||
|
func (d Distinct) reflect() reflect.Value {
|
||||||
|
return reflect.ValueOf(d.iface)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid returns true if this value refers to a valid `*Set`.
|
||||||
|
func (d Distinct) Valid() bool {
|
||||||
|
return d.iface != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of labels in this set.
|
||||||
|
func (l *Set) Len() int {
|
||||||
|
if l == nil || !l.equivalent.Valid() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return l.equivalent.reflect().Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the KeyValue at ordered position `idx` in this set.
|
||||||
|
func (l *Set) Get(idx int) (KeyValue, bool) {
|
||||||
|
if l == nil {
|
||||||
|
return KeyValue{}, false
|
||||||
|
}
|
||||||
|
value := l.equivalent.reflect()
|
||||||
|
|
||||||
|
if idx >= 0 && idx < value.Len() {
|
||||||
|
// Note: The Go compiler successfully avoids an allocation for
|
||||||
|
// the interface{} conversion here:
|
||||||
|
return value.Index(idx).Interface().(KeyValue), true
|
||||||
|
}
|
||||||
|
|
||||||
|
return KeyValue{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the value of a specified key in this set.
|
||||||
|
func (l *Set) Value(k Key) (Value, bool) {
|
||||||
|
if l == nil {
|
||||||
|
return Value{}, false
|
||||||
|
}
|
||||||
|
rValue := l.equivalent.reflect()
|
||||||
|
vlen := rValue.Len()
|
||||||
|
|
||||||
|
idx := sort.Search(vlen, func(idx int) bool {
|
||||||
|
return rValue.Index(idx).Interface().(KeyValue).Key >= k
|
||||||
|
})
|
||||||
|
if idx >= vlen {
|
||||||
|
return Value{}, false
|
||||||
|
}
|
||||||
|
keyValue := rValue.Index(idx).Interface().(KeyValue)
|
||||||
|
if k == keyValue.Key {
|
||||||
|
return keyValue.Value, true
|
||||||
|
}
|
||||||
|
return Value{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasValue tests whether a key is defined in this set.
|
||||||
|
func (l *Set) HasValue(k Key) bool {
|
||||||
|
if l == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, ok := l.Value(k)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iter returns an iterator for visiting the labels in this set.
|
||||||
|
func (l *Set) Iter() Iterator {
|
||||||
|
return Iterator{
|
||||||
|
storage: l,
|
||||||
|
idx: -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToSlice returns the set of labels belonging to this set, sorted,
|
||||||
|
// where keys appear no more than once.
|
||||||
|
func (l *Set) ToSlice() []KeyValue {
|
||||||
|
iter := l.Iter()
|
||||||
|
return iter.ToSlice()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equivalent returns a value that may be used as a map key. The
|
||||||
|
// Distinct type guarantees that the result will equal the equivalent
|
||||||
|
// Distinct value of any label set with the same elements as this,
|
||||||
|
// where sets are made unique by choosing the last value in the input
|
||||||
|
// for any given key.
|
||||||
|
func (l *Set) Equivalent() Distinct {
|
||||||
|
if l == nil || !l.equivalent.Valid() {
|
||||||
|
return emptySet.equivalent
|
||||||
|
}
|
||||||
|
return l.equivalent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equals returns true if the argument set is equivalent to this set.
|
||||||
|
func (l *Set) Equals(o *Set) bool {
|
||||||
|
return l.Equivalent() == o.Equivalent()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encoded returns the encoded form of this set, according to
|
||||||
|
// `encoder`.
|
||||||
|
func (l *Set) Encoded(encoder Encoder) string {
|
||||||
|
if l == nil || encoder == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return encoder.Encode(l.Iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
func empty() Set {
|
||||||
|
return Set{
|
||||||
|
equivalent: emptySet.equivalent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSet returns a new `Set`. See the documentation for
|
||||||
|
// `NewSetWithSortableFiltered` for more details.
|
||||||
|
//
|
||||||
|
// Except for empty sets, this method adds an additional allocation
|
||||||
|
// compared with calls that include a `*Sortable`.
|
||||||
|
func NewSet(kvs ...KeyValue) Set {
|
||||||
|
// Check for empty set.
|
||||||
|
if len(kvs) == 0 {
|
||||||
|
return empty()
|
||||||
|
}
|
||||||
|
s, _ := NewSetWithSortableFiltered(kvs, new(Sortable), nil)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSetWithSortable returns a new `Set`. See the documentation for
|
||||||
|
// `NewSetWithSortableFiltered` for more details.
|
||||||
|
//
|
||||||
|
// This call includes a `*Sortable` option as a memory optimization.
|
||||||
|
func NewSetWithSortable(kvs []KeyValue, tmp *Sortable) Set {
|
||||||
|
// Check for empty set.
|
||||||
|
if len(kvs) == 0 {
|
||||||
|
return empty()
|
||||||
|
}
|
||||||
|
s, _ := NewSetWithSortableFiltered(kvs, tmp, nil)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSetWithFiltered returns a new `Set`. See the documentation for
|
||||||
|
// `NewSetWithSortableFiltered` for more details.
|
||||||
|
//
|
||||||
|
// This call includes a `Filter` to include/exclude label keys from
|
||||||
|
// the return value. Excluded keys are returned as a slice of label
|
||||||
|
// values.
|
||||||
|
func NewSetWithFiltered(kvs []KeyValue, filter Filter) (Set, []KeyValue) {
|
||||||
|
// Check for empty set.
|
||||||
|
if len(kvs) == 0 {
|
||||||
|
return empty(), nil
|
||||||
|
}
|
||||||
|
return NewSetWithSortableFiltered(kvs, new(Sortable), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSetWithSortableFiltered returns a new `Set`.
|
||||||
|
//
|
||||||
|
// Duplicate keys are eliminated by taking the last value. This
|
||||||
|
// re-orders the input slice so that unique last-values are contiguous
|
||||||
|
// at the end of the slice.
|
||||||
|
//
|
||||||
|
// This ensures the following:
|
||||||
|
//
|
||||||
|
// - Last-value-wins semantics
|
||||||
|
// - Caller sees the reordering, but doesn't lose values
|
||||||
|
// - Repeated call preserve last-value wins.
|
||||||
|
//
|
||||||
|
// Note that methods are defined on `*Set`, although this returns `Set`.
|
||||||
|
// Callers can avoid memory allocations by:
|
||||||
|
//
|
||||||
|
// - allocating a `Sortable` for use as a temporary in this method
|
||||||
|
// - allocating a `Set` for storing the return value of this
|
||||||
|
// constructor.
|
||||||
|
//
|
||||||
|
// The result maintains a cache of encoded labels, by attribute.EncoderID.
|
||||||
|
// This value should not be copied after its first use.
|
||||||
|
//
|
||||||
|
// The second `[]KeyValue` return value is a list of labels that were
|
||||||
|
// excluded by the Filter (if non-nil).
|
||||||
|
func NewSetWithSortableFiltered(kvs []KeyValue, tmp *Sortable, filter Filter) (Set, []KeyValue) {
|
||||||
|
// Check for empty set.
|
||||||
|
if len(kvs) == 0 {
|
||||||
|
return empty(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
*tmp = kvs
|
||||||
|
|
||||||
|
// Stable sort so the following de-duplication can implement
|
||||||
|
// last-value-wins semantics.
|
||||||
|
sort.Stable(tmp)
|
||||||
|
|
||||||
|
*tmp = nil
|
||||||
|
|
||||||
|
position := len(kvs) - 1
|
||||||
|
offset := position - 1
|
||||||
|
|
||||||
|
// The requirements stated above require that the stable
|
||||||
|
// result be placed in the end of the input slice, while
|
||||||
|
// overwritten values are swapped to the beginning.
|
||||||
|
//
|
||||||
|
// De-duplicate with last-value-wins semantics. Preserve
|
||||||
|
// duplicate values at the beginning of the input slice.
|
||||||
|
for ; offset >= 0; offset-- {
|
||||||
|
if kvs[offset].Key == kvs[position].Key {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
position--
|
||||||
|
kvs[offset], kvs[position] = kvs[position], kvs[offset]
|
||||||
|
}
|
||||||
|
if filter != nil {
|
||||||
|
return filterSet(kvs[position:], filter)
|
||||||
|
}
|
||||||
|
return Set{
|
||||||
|
equivalent: computeDistinct(kvs[position:]),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// filterSet reorders `kvs` so that included keys are contiguous at
|
||||||
|
// the end of the slice, while excluded keys precede the included keys.
|
||||||
|
func filterSet(kvs []KeyValue, filter Filter) (Set, []KeyValue) {
|
||||||
|
var excluded []KeyValue
|
||||||
|
|
||||||
|
// Move labels that do not match the filter so
|
||||||
|
// they're adjacent before calling computeDistinct().
|
||||||
|
distinctPosition := len(kvs)
|
||||||
|
|
||||||
|
// Swap indistinct keys forward and distinct keys toward the
|
||||||
|
// end of the slice.
|
||||||
|
offset := len(kvs) - 1
|
||||||
|
for ; offset >= 0; offset-- {
|
||||||
|
if filter(kvs[offset]) {
|
||||||
|
distinctPosition--
|
||||||
|
kvs[offset], kvs[distinctPosition] = kvs[distinctPosition], kvs[offset]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
excluded = kvs[:distinctPosition]
|
||||||
|
|
||||||
|
return Set{
|
||||||
|
equivalent: computeDistinct(kvs[distinctPosition:]),
|
||||||
|
}, excluded
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter returns a filtered copy of this `Set`. See the
|
||||||
|
// documentation for `NewSetWithSortableFiltered` for more details.
|
||||||
|
func (l *Set) Filter(re Filter) (Set, []KeyValue) {
|
||||||
|
if re == nil {
|
||||||
|
return Set{
|
||||||
|
equivalent: l.equivalent,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: This could be refactored to avoid the temporary slice
|
||||||
|
// allocation, if it proves to be expensive.
|
||||||
|
return filterSet(l.ToSlice(), re)
|
||||||
|
}
|
||||||
|
|
||||||
|
// computeDistinct returns a `Distinct` using either the fixed- or
|
||||||
|
// reflect-oriented code path, depending on the size of the input.
|
||||||
|
// The input slice is assumed to already be sorted and de-duplicated.
|
||||||
|
func computeDistinct(kvs []KeyValue) Distinct {
|
||||||
|
iface := computeDistinctFixed(kvs)
|
||||||
|
if iface == nil {
|
||||||
|
iface = computeDistinctReflect(kvs)
|
||||||
|
}
|
||||||
|
return Distinct{
|
||||||
|
iface: iface,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// computeDistinctFixed computes a `Distinct` for small slices. It
|
||||||
|
// returns nil if the input is too large for this code path.
|
||||||
|
func computeDistinctFixed(kvs []KeyValue) interface{} {
|
||||||
|
switch len(kvs) {
|
||||||
|
case 1:
|
||||||
|
ptr := new([1]KeyValue)
|
||||||
|
copy((*ptr)[:], kvs)
|
||||||
|
return *ptr
|
||||||
|
case 2:
|
||||||
|
ptr := new([2]KeyValue)
|
||||||
|
copy((*ptr)[:], kvs)
|
||||||
|
return *ptr
|
||||||
|
case 3:
|
||||||
|
ptr := new([3]KeyValue)
|
||||||
|
copy((*ptr)[:], kvs)
|
||||||
|
return *ptr
|
||||||
|
case 4:
|
||||||
|
ptr := new([4]KeyValue)
|
||||||
|
copy((*ptr)[:], kvs)
|
||||||
|
return *ptr
|
||||||
|
case 5:
|
||||||
|
ptr := new([5]KeyValue)
|
||||||
|
copy((*ptr)[:], kvs)
|
||||||
|
return *ptr
|
||||||
|
case 6:
|
||||||
|
ptr := new([6]KeyValue)
|
||||||
|
copy((*ptr)[:], kvs)
|
||||||
|
return *ptr
|
||||||
|
case 7:
|
||||||
|
ptr := new([7]KeyValue)
|
||||||
|
copy((*ptr)[:], kvs)
|
||||||
|
return *ptr
|
||||||
|
case 8:
|
||||||
|
ptr := new([8]KeyValue)
|
||||||
|
copy((*ptr)[:], kvs)
|
||||||
|
return *ptr
|
||||||
|
case 9:
|
||||||
|
ptr := new([9]KeyValue)
|
||||||
|
copy((*ptr)[:], kvs)
|
||||||
|
return *ptr
|
||||||
|
case 10:
|
||||||
|
ptr := new([10]KeyValue)
|
||||||
|
copy((*ptr)[:], kvs)
|
||||||
|
return *ptr
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// computeDistinctReflect computes a `Distinct` using reflection,
|
||||||
|
// works for any size input.
|
||||||
|
func computeDistinctReflect(kvs []KeyValue) interface{} {
|
||||||
|
at := reflect.New(reflect.ArrayOf(len(kvs), keyValueType)).Elem()
|
||||||
|
for i, keyValue := range kvs {
|
||||||
|
*(at.Index(i).Addr().Interface().(*KeyValue)) = keyValue
|
||||||
|
}
|
||||||
|
return at.Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON returns the JSON encoding of the `*Set`.
|
||||||
|
func (l *Set) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(l.equivalent.iface)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len implements `sort.Interface`.
|
||||||
|
func (l *Sortable) Len() int {
|
||||||
|
return len(*l)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap implements `sort.Interface`.
|
||||||
|
func (l *Sortable) Swap(i, j int) {
|
||||||
|
(*l)[i], (*l)[j] = (*l)[j], (*l)[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less implements `sort.Interface`.
|
||||||
|
func (l *Sortable) Less(i, j int) bool {
|
||||||
|
return (*l)[i].Key < (*l)[j].Key
|
||||||
|
}
|
||||||
31
vendor/go.opentelemetry.io/otel/attribute/type_string.go
generated
vendored
Normal file
31
vendor/go.opentelemetry.io/otel/attribute/type_string.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Code generated by "stringer -type=Type"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package attribute
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[INVALID-0]
|
||||||
|
_ = x[BOOL-1]
|
||||||
|
_ = x[INT64-2]
|
||||||
|
_ = x[FLOAT64-3]
|
||||||
|
_ = x[STRING-4]
|
||||||
|
_ = x[BOOLSLICE-5]
|
||||||
|
_ = x[INT64SLICE-6]
|
||||||
|
_ = x[FLOAT64SLICE-7]
|
||||||
|
_ = x[STRINGSLICE-8]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _Type_name = "INVALIDBOOLINT64FLOAT64STRINGBOOLSLICEINT64SLICEFLOAT64SLICESTRINGSLICE"
|
||||||
|
|
||||||
|
var _Type_index = [...]uint8{0, 7, 11, 16, 23, 29, 38, 48, 60, 71}
|
||||||
|
|
||||||
|
func (i Type) String() string {
|
||||||
|
if i < 0 || i >= Type(len(_Type_index)-1) {
|
||||||
|
return "Type(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _Type_name[_Type_index[i]:_Type_index[i+1]]
|
||||||
|
}
|
||||||
271
vendor/go.opentelemetry.io/otel/attribute/value.go
generated
vendored
Normal file
271
vendor/go.opentelemetry.io/otel/attribute/value.go
generated
vendored
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
// Copyright The 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 attribute // import "go.opentelemetry.io/otel/attribute"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate stringer -type=Type
|
||||||
|
|
||||||
|
// Type describes the type of the data Value holds.
|
||||||
|
type Type int
|
||||||
|
|
||||||
|
// Value represents the value part in key-value pairs.
|
||||||
|
type Value struct {
|
||||||
|
vtype Type
|
||||||
|
numeric uint64
|
||||||
|
stringly string
|
||||||
|
slice interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// INVALID is used for a Value with no value set.
|
||||||
|
INVALID Type = iota
|
||||||
|
// BOOL is a boolean Type Value.
|
||||||
|
BOOL
|
||||||
|
// INT64 is a 64-bit signed integral Type Value.
|
||||||
|
INT64
|
||||||
|
// FLOAT64 is a 64-bit floating point Type Value.
|
||||||
|
FLOAT64
|
||||||
|
// STRING is a string Type Value.
|
||||||
|
STRING
|
||||||
|
// BOOLSLICE is a slice of booleans Type Value.
|
||||||
|
BOOLSLICE
|
||||||
|
// INT64SLICE is a slice of 64-bit signed integral numbers Type Value.
|
||||||
|
INT64SLICE
|
||||||
|
// FLOAT64SLICE is a slice of 64-bit floating point numbers Type Value.
|
||||||
|
FLOAT64SLICE
|
||||||
|
// STRINGSLICE is a slice of strings Type Value.
|
||||||
|
STRINGSLICE
|
||||||
|
)
|
||||||
|
|
||||||
|
// BoolValue creates a BOOL Value.
|
||||||
|
func BoolValue(v bool) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: BOOL,
|
||||||
|
numeric: internal.BoolToRaw(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceValue creates a BOOLSLICE Value.
|
||||||
|
func BoolSliceValue(v []bool) Value {
|
||||||
|
cp := make([]bool, len(v))
|
||||||
|
copy(cp, v)
|
||||||
|
return Value{
|
||||||
|
vtype: BOOLSLICE,
|
||||||
|
slice: &cp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntValue creates an INT64 Value.
|
||||||
|
func IntValue(v int) Value {
|
||||||
|
return Int64Value(int64(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntSliceValue creates an INTSLICE Value.
|
||||||
|
func IntSliceValue(v []int) Value {
|
||||||
|
cp := make([]int64, 0, len(v))
|
||||||
|
for _, i := range v {
|
||||||
|
cp = append(cp, int64(i))
|
||||||
|
}
|
||||||
|
return Value{
|
||||||
|
vtype: INT64SLICE,
|
||||||
|
slice: &cp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Value creates an INT64 Value.
|
||||||
|
func Int64Value(v int64) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: INT64,
|
||||||
|
numeric: internal.Int64ToRaw(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64SliceValue creates an INT64SLICE Value.
|
||||||
|
func Int64SliceValue(v []int64) Value {
|
||||||
|
cp := make([]int64, len(v))
|
||||||
|
copy(cp, v)
|
||||||
|
return Value{
|
||||||
|
vtype: INT64SLICE,
|
||||||
|
slice: &cp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Value creates a FLOAT64 Value.
|
||||||
|
func Float64Value(v float64) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: FLOAT64,
|
||||||
|
numeric: internal.Float64ToRaw(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64SliceValue creates a FLOAT64SLICE Value.
|
||||||
|
func Float64SliceValue(v []float64) Value {
|
||||||
|
cp := make([]float64, len(v))
|
||||||
|
copy(cp, v)
|
||||||
|
return Value{
|
||||||
|
vtype: FLOAT64SLICE,
|
||||||
|
slice: &cp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringValue creates a STRING Value.
|
||||||
|
func StringValue(v string) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: STRING,
|
||||||
|
stringly: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSliceValue creates a STRINGSLICE Value.
|
||||||
|
func StringSliceValue(v []string) Value {
|
||||||
|
cp := make([]string, len(v))
|
||||||
|
copy(cp, v)
|
||||||
|
return Value{
|
||||||
|
vtype: STRINGSLICE,
|
||||||
|
slice: &cp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns a type of the Value.
|
||||||
|
func (v Value) Type() Type {
|
||||||
|
return v.vtype
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsBool returns the bool value. Make sure that the Value's type is
|
||||||
|
// BOOL.
|
||||||
|
func (v Value) AsBool() bool {
|
||||||
|
return internal.RawToBool(v.numeric)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsBoolSlice returns the []bool value. Make sure that the Value's type is
|
||||||
|
// BOOLSLICE.
|
||||||
|
func (v Value) AsBoolSlice() []bool {
|
||||||
|
if s, ok := v.slice.(*[]bool); ok {
|
||||||
|
return *s
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsInt64 returns the int64 value. Make sure that the Value's type is
|
||||||
|
// INT64.
|
||||||
|
func (v Value) AsInt64() int64 {
|
||||||
|
return internal.RawToInt64(v.numeric)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsInt64Slice returns the []int64 value. Make sure that the Value's type is
|
||||||
|
// INT64SLICE.
|
||||||
|
func (v Value) AsInt64Slice() []int64 {
|
||||||
|
if s, ok := v.slice.(*[]int64); ok {
|
||||||
|
return *s
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsFloat64 returns the float64 value. Make sure that the Value's
|
||||||
|
// type is FLOAT64.
|
||||||
|
func (v Value) AsFloat64() float64 {
|
||||||
|
return internal.RawToFloat64(v.numeric)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsFloat64Slice returns the []float64 value. Make sure that the Value's type is
|
||||||
|
// INT64SLICE.
|
||||||
|
func (v Value) AsFloat64Slice() []float64 {
|
||||||
|
if s, ok := v.slice.(*[]float64); ok {
|
||||||
|
return *s
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsString returns the string value. Make sure that the Value's type
|
||||||
|
// is STRING.
|
||||||
|
func (v Value) AsString() string {
|
||||||
|
return v.stringly
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsStringSlice returns the []string value. Make sure that the Value's type is
|
||||||
|
// INT64SLICE.
|
||||||
|
func (v Value) AsStringSlice() []string {
|
||||||
|
if s, ok := v.slice.(*[]string); ok {
|
||||||
|
return *s
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type unknownValueType struct{}
|
||||||
|
|
||||||
|
// AsInterface returns Value's data as interface{}.
|
||||||
|
func (v Value) AsInterface() interface{} {
|
||||||
|
switch v.Type() {
|
||||||
|
case BOOL:
|
||||||
|
return v.AsBool()
|
||||||
|
case BOOLSLICE:
|
||||||
|
return v.AsBoolSlice()
|
||||||
|
case INT64:
|
||||||
|
return v.AsInt64()
|
||||||
|
case INT64SLICE:
|
||||||
|
return v.AsInt64Slice()
|
||||||
|
case FLOAT64:
|
||||||
|
return v.AsFloat64()
|
||||||
|
case FLOAT64SLICE:
|
||||||
|
return v.AsFloat64Slice()
|
||||||
|
case STRING:
|
||||||
|
return v.stringly
|
||||||
|
case STRINGSLICE:
|
||||||
|
return v.AsStringSlice()
|
||||||
|
}
|
||||||
|
return unknownValueType{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit returns a string representation of Value's data.
|
||||||
|
func (v Value) Emit() string {
|
||||||
|
switch v.Type() {
|
||||||
|
case BOOLSLICE:
|
||||||
|
return fmt.Sprint(*(v.slice.(*[]bool)))
|
||||||
|
case BOOL:
|
||||||
|
return strconv.FormatBool(v.AsBool())
|
||||||
|
case INT64SLICE:
|
||||||
|
return fmt.Sprint(*(v.slice.(*[]int64)))
|
||||||
|
case INT64:
|
||||||
|
return strconv.FormatInt(v.AsInt64(), 10)
|
||||||
|
case FLOAT64SLICE:
|
||||||
|
return fmt.Sprint(*(v.slice.(*[]float64)))
|
||||||
|
case FLOAT64:
|
||||||
|
return fmt.Sprint(v.AsFloat64())
|
||||||
|
case STRINGSLICE:
|
||||||
|
return fmt.Sprint(*(v.slice.(*[]string)))
|
||||||
|
case STRING:
|
||||||
|
return v.stringly
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON returns the JSON encoding of the Value.
|
||||||
|
func (v Value) MarshalJSON() ([]byte, error) {
|
||||||
|
var jsonVal struct {
|
||||||
|
Type string
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
jsonVal.Type = v.Type().String()
|
||||||
|
jsonVal.Value = v.AsInterface()
|
||||||
|
return json.Marshal(jsonVal)
|
||||||
|
}
|
||||||
509
vendor/go.opentelemetry.io/otel/baggage/baggage.go
generated
vendored
Normal file
509
vendor/go.opentelemetry.io/otel/baggage/baggage.go
generated
vendored
Normal file
@@ -0,0 +1,509 @@
|
|||||||
|
// Copyright The 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 baggage // import "go.opentelemetry.io/otel/baggage"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/internal/baggage"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxMembers = 180
|
||||||
|
maxBytesPerMembers = 4096
|
||||||
|
maxBytesPerBaggageString = 8192
|
||||||
|
|
||||||
|
listDelimiter = ","
|
||||||
|
keyValueDelimiter = "="
|
||||||
|
propertyDelimiter = ";"
|
||||||
|
|
||||||
|
keyDef = `([\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5a\x5e-\x7a\x7c\x7e]+)`
|
||||||
|
valueDef = `([\x21\x23-\x2b\x2d-\x3a\x3c-\x5B\x5D-\x7e]*)`
|
||||||
|
keyValueDef = `\s*` + keyDef + `\s*` + keyValueDelimiter + `\s*` + valueDef + `\s*`
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
keyRe = regexp.MustCompile(`^` + keyDef + `$`)
|
||||||
|
valueRe = regexp.MustCompile(`^` + valueDef + `$`)
|
||||||
|
propertyRe = regexp.MustCompile(`^(?:\s*` + keyDef + `\s*|` + keyValueDef + `)$`)
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errInvalidKey = errors.New("invalid key")
|
||||||
|
errInvalidValue = errors.New("invalid value")
|
||||||
|
errInvalidProperty = errors.New("invalid baggage list-member property")
|
||||||
|
errInvalidMember = errors.New("invalid baggage list-member")
|
||||||
|
errMemberNumber = errors.New("too many list-members in baggage-string")
|
||||||
|
errMemberBytes = errors.New("list-member too large")
|
||||||
|
errBaggageBytes = errors.New("baggage-string too large")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Property is an additional metadata entry for a baggage list-member.
|
||||||
|
type Property struct {
|
||||||
|
key, value string
|
||||||
|
|
||||||
|
// hasValue indicates if a zero-value value means the property does not
|
||||||
|
// have a value or if it was the zero-value.
|
||||||
|
hasValue bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKeyProperty(key string) (Property, error) {
|
||||||
|
p := Property{}
|
||||||
|
if !keyRe.MatchString(key) {
|
||||||
|
return p, fmt.Errorf("%w: %q", errInvalidKey, key)
|
||||||
|
}
|
||||||
|
p.key = key
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKeyValueProperty(key, value string) (Property, error) {
|
||||||
|
p := Property{}
|
||||||
|
if !keyRe.MatchString(key) {
|
||||||
|
return p, fmt.Errorf("%w: %q", errInvalidKey, key)
|
||||||
|
}
|
||||||
|
if !valueRe.MatchString(value) {
|
||||||
|
return p, fmt.Errorf("%w: %q", errInvalidValue, value)
|
||||||
|
}
|
||||||
|
p.key = key
|
||||||
|
p.value = value
|
||||||
|
p.hasValue = true
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseProperty attempts to decode a Property from the passed string. It
|
||||||
|
// returns an error if the input is invalid according to the W3C Baggage
|
||||||
|
// specification.
|
||||||
|
func parseProperty(property string) (Property, error) {
|
||||||
|
p := Property{}
|
||||||
|
if property == "" {
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
match := propertyRe.FindStringSubmatch(property)
|
||||||
|
if len(match) != 4 {
|
||||||
|
return p, fmt.Errorf("%w: %q", errInvalidProperty, property)
|
||||||
|
}
|
||||||
|
|
||||||
|
if match[1] != "" {
|
||||||
|
p.key = match[1]
|
||||||
|
} else {
|
||||||
|
p.key = match[2]
|
||||||
|
p.value = match[3]
|
||||||
|
p.hasValue = true
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate ensures p conforms to the W3C Baggage specification, returning an
|
||||||
|
// error otherwise.
|
||||||
|
func (p Property) validate() error {
|
||||||
|
errFunc := func(err error) error {
|
||||||
|
return fmt.Errorf("invalid property: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !keyRe.MatchString(p.key) {
|
||||||
|
return errFunc(fmt.Errorf("%w: %q", errInvalidKey, p.key))
|
||||||
|
}
|
||||||
|
if p.hasValue && !valueRe.MatchString(p.value) {
|
||||||
|
return errFunc(fmt.Errorf("%w: %q", errInvalidValue, p.value))
|
||||||
|
}
|
||||||
|
if !p.hasValue && p.value != "" {
|
||||||
|
return errFunc(errors.New("inconsistent value"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the Property key.
|
||||||
|
func (p Property) Key() string {
|
||||||
|
return p.key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the Property value. Additionally a boolean value is returned
|
||||||
|
// indicating if the returned value is the empty if the Property has a value
|
||||||
|
// that is empty or if the value is not set.
|
||||||
|
func (p Property) Value() (string, bool) {
|
||||||
|
return p.value, p.hasValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// String encodes Property into a string compliant with the W3C Baggage
|
||||||
|
// specification.
|
||||||
|
func (p Property) String() string {
|
||||||
|
if p.hasValue {
|
||||||
|
return fmt.Sprintf("%s%s%v", p.key, keyValueDelimiter, p.value)
|
||||||
|
}
|
||||||
|
return p.key
|
||||||
|
}
|
||||||
|
|
||||||
|
type properties []Property
|
||||||
|
|
||||||
|
func fromInternalProperties(iProps []baggage.Property) properties {
|
||||||
|
if len(iProps) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
props := make(properties, len(iProps))
|
||||||
|
for i, p := range iProps {
|
||||||
|
props[i] = Property{
|
||||||
|
key: p.Key,
|
||||||
|
value: p.Value,
|
||||||
|
hasValue: p.HasValue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return props
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p properties) asInternal() []baggage.Property {
|
||||||
|
if len(p) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
iProps := make([]baggage.Property, len(p))
|
||||||
|
for i, prop := range p {
|
||||||
|
iProps[i] = baggage.Property{
|
||||||
|
Key: prop.key,
|
||||||
|
Value: prop.value,
|
||||||
|
HasValue: prop.hasValue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return iProps
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p properties) Copy() properties {
|
||||||
|
if len(p) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
props := make(properties, len(p))
|
||||||
|
copy(props, p)
|
||||||
|
return props
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate ensures each Property in p conforms to the W3C Baggage
|
||||||
|
// specification, returning an error otherwise.
|
||||||
|
func (p properties) validate() error {
|
||||||
|
for _, prop := range p {
|
||||||
|
if err := prop.validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String encodes properties into a string compliant with the W3C Baggage
|
||||||
|
// specification.
|
||||||
|
func (p properties) String() string {
|
||||||
|
props := make([]string, len(p))
|
||||||
|
for i, prop := range p {
|
||||||
|
props[i] = prop.String()
|
||||||
|
}
|
||||||
|
return strings.Join(props, propertyDelimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Member is a list-member of a baggage-string as defined by the W3C Baggage
|
||||||
|
// specification.
|
||||||
|
type Member struct {
|
||||||
|
key, value string
|
||||||
|
properties properties
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMember returns a new Member from the passed arguments. An error is
|
||||||
|
// returned if the created Member would be invalid according to the W3C
|
||||||
|
// Baggage specification.
|
||||||
|
func NewMember(key, value string, props ...Property) (Member, error) {
|
||||||
|
m := Member{key: key, value: value, properties: properties(props).Copy()}
|
||||||
|
if err := m.validate(); err != nil {
|
||||||
|
return Member{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseMember attempts to decode a Member from the passed string. It returns
|
||||||
|
// an error if the input is invalid according to the W3C Baggage
|
||||||
|
// specification.
|
||||||
|
func parseMember(member string) (Member, error) {
|
||||||
|
if n := len(member); n > maxBytesPerMembers {
|
||||||
|
return Member{}, fmt.Errorf("%w: %d", errMemberBytes, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
key, value string
|
||||||
|
props properties
|
||||||
|
)
|
||||||
|
|
||||||
|
parts := strings.SplitN(member, propertyDelimiter, 2)
|
||||||
|
switch len(parts) {
|
||||||
|
case 2:
|
||||||
|
// Parse the member properties.
|
||||||
|
for _, pStr := range strings.Split(parts[1], propertyDelimiter) {
|
||||||
|
p, err := parseProperty(pStr)
|
||||||
|
if err != nil {
|
||||||
|
return Member{}, err
|
||||||
|
}
|
||||||
|
props = append(props, p)
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case 1:
|
||||||
|
// Parse the member key/value pair.
|
||||||
|
|
||||||
|
// Take into account a value can contain equal signs (=).
|
||||||
|
kv := strings.SplitN(parts[0], keyValueDelimiter, 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return Member{}, fmt.Errorf("%w: %q", errInvalidMember, member)
|
||||||
|
}
|
||||||
|
// "Leading and trailing whitespaces are allowed but MUST be trimmed
|
||||||
|
// when converting the header into a data structure."
|
||||||
|
key, value = strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1])
|
||||||
|
if !keyRe.MatchString(key) {
|
||||||
|
return Member{}, fmt.Errorf("%w: %q", errInvalidKey, key)
|
||||||
|
}
|
||||||
|
if !valueRe.MatchString(value) {
|
||||||
|
return Member{}, fmt.Errorf("%w: %q", errInvalidValue, value)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// This should never happen unless a developer has changed the string
|
||||||
|
// splitting somehow. Panic instead of failing silently and allowing
|
||||||
|
// the bug to slip past the CI checks.
|
||||||
|
panic("failed to parse baggage member")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Member{key: key, value: value, properties: props}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate ensures m conforms to the W3C Baggage specification, returning an
|
||||||
|
// error otherwise.
|
||||||
|
func (m Member) validate() error {
|
||||||
|
if !keyRe.MatchString(m.key) {
|
||||||
|
return fmt.Errorf("%w: %q", errInvalidKey, m.key)
|
||||||
|
}
|
||||||
|
if !valueRe.MatchString(m.value) {
|
||||||
|
return fmt.Errorf("%w: %q", errInvalidValue, m.value)
|
||||||
|
}
|
||||||
|
return m.properties.validate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the Member key.
|
||||||
|
func (m Member) Key() string { return m.key }
|
||||||
|
|
||||||
|
// Value returns the Member value.
|
||||||
|
func (m Member) Value() string { return m.value }
|
||||||
|
|
||||||
|
// Properties returns a copy of the Member properties.
|
||||||
|
func (m Member) Properties() []Property { return m.properties.Copy() }
|
||||||
|
|
||||||
|
// String encodes Member into a string compliant with the W3C Baggage
|
||||||
|
// specification.
|
||||||
|
func (m Member) String() string {
|
||||||
|
// A key is just an ASCII string, but a value is URL encoded UTF-8.
|
||||||
|
s := fmt.Sprintf("%s%s%s", m.key, keyValueDelimiter, url.QueryEscape(m.value))
|
||||||
|
if len(m.properties) > 0 {
|
||||||
|
s = fmt.Sprintf("%s%s%s", s, propertyDelimiter, m.properties.String())
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Baggage is a list of baggage members representing the baggage-string as
|
||||||
|
// defined by the W3C Baggage specification.
|
||||||
|
type Baggage struct { //nolint:golint
|
||||||
|
list baggage.List
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new valid Baggage. It returns an error if the passed members
|
||||||
|
// are invalid according to the W3C Baggage specification or if it results in
|
||||||
|
// a Baggage exceeding limits set in that specification.
|
||||||
|
func New(members ...Member) (Baggage, error) {
|
||||||
|
if len(members) == 0 {
|
||||||
|
return Baggage{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
b := make(baggage.List)
|
||||||
|
for _, m := range members {
|
||||||
|
if err := m.validate(); err != nil {
|
||||||
|
return Baggage{}, err
|
||||||
|
}
|
||||||
|
// OpenTelemetry resolves duplicates by last-one-wins.
|
||||||
|
b[m.key] = baggage.Item{
|
||||||
|
Value: m.value,
|
||||||
|
Properties: m.properties.asInternal(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check member numbers after deduplicating.
|
||||||
|
if len(b) > maxMembers {
|
||||||
|
return Baggage{}, errMemberNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
bag := Baggage{b}
|
||||||
|
if n := len(bag.String()); n > maxBytesPerBaggageString {
|
||||||
|
return Baggage{}, fmt.Errorf("%w: %d", errBaggageBytes, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bag, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse attempts to decode a baggage-string from the passed string. It
|
||||||
|
// returns an error if the input is invalid according to the W3C Baggage
|
||||||
|
// specification.
|
||||||
|
//
|
||||||
|
// If there are duplicate list-members contained in baggage, the last one
|
||||||
|
// defined (reading left-to-right) will be the only one kept. This diverges
|
||||||
|
// from the W3C Baggage specification which allows duplicate list-members, but
|
||||||
|
// conforms to the OpenTelemetry Baggage specification.
|
||||||
|
func Parse(bStr string) (Baggage, error) {
|
||||||
|
if bStr == "" {
|
||||||
|
return Baggage{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if n := len(bStr); n > maxBytesPerBaggageString {
|
||||||
|
return Baggage{}, fmt.Errorf("%w: %d", errBaggageBytes, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
b := make(baggage.List)
|
||||||
|
for _, memberStr := range strings.Split(bStr, listDelimiter) {
|
||||||
|
m, err := parseMember(memberStr)
|
||||||
|
if err != nil {
|
||||||
|
return Baggage{}, err
|
||||||
|
}
|
||||||
|
// OpenTelemetry resolves duplicates by last-one-wins.
|
||||||
|
b[m.key] = baggage.Item{
|
||||||
|
Value: m.value,
|
||||||
|
Properties: m.properties.asInternal(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenTelemetry does not allow for duplicate list-members, but the W3C
|
||||||
|
// specification does. Now that we have deduplicated, ensure the baggage
|
||||||
|
// does not exceed list-member limits.
|
||||||
|
if len(b) > maxMembers {
|
||||||
|
return Baggage{}, errMemberNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
return Baggage{b}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Member returns the baggage list-member identified by key.
|
||||||
|
//
|
||||||
|
// If there is no list-member matching the passed key the returned Member will
|
||||||
|
// be a zero-value Member.
|
||||||
|
func (b Baggage) Member(key string) Member {
|
||||||
|
v, ok := b.list[key]
|
||||||
|
if !ok {
|
||||||
|
// We do not need to worry about distiguising between the situation
|
||||||
|
// where a zero-valued Member is included in the Baggage because a
|
||||||
|
// zero-valued Member is invalid according to the W3C Baggage
|
||||||
|
// specification (it has an empty key).
|
||||||
|
return Member{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Member{
|
||||||
|
key: key,
|
||||||
|
value: v.Value,
|
||||||
|
properties: fromInternalProperties(v.Properties),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Members returns all the baggage list-members.
|
||||||
|
// The order of the returned list-members does not have significance.
|
||||||
|
func (b Baggage) Members() []Member {
|
||||||
|
if len(b.list) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
members := make([]Member, 0, len(b.list))
|
||||||
|
for k, v := range b.list {
|
||||||
|
members = append(members, Member{
|
||||||
|
key: k,
|
||||||
|
value: v.Value,
|
||||||
|
properties: fromInternalProperties(v.Properties),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return members
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMember returns a copy the Baggage with the member included. If the
|
||||||
|
// baggage contains a Member with the same key the existing Member is
|
||||||
|
// replaced.
|
||||||
|
//
|
||||||
|
// If member is invalid according to the W3C Baggage specification, an error
|
||||||
|
// is returned with the original Baggage.
|
||||||
|
func (b Baggage) SetMember(member Member) (Baggage, error) {
|
||||||
|
if err := member.validate(); err != nil {
|
||||||
|
return b, fmt.Errorf("%w: %s", errInvalidMember, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
n := len(b.list)
|
||||||
|
if _, ok := b.list[member.key]; !ok {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
list := make(baggage.List, n)
|
||||||
|
|
||||||
|
for k, v := range b.list {
|
||||||
|
// Do not copy if we are just going to overwrite.
|
||||||
|
if k == member.key {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
list[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
list[member.key] = baggage.Item{
|
||||||
|
Value: member.value,
|
||||||
|
Properties: member.properties.asInternal(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return Baggage{list: list}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMember returns a copy of the Baggage with the list-member identified
|
||||||
|
// by key removed.
|
||||||
|
func (b Baggage) DeleteMember(key string) Baggage {
|
||||||
|
n := len(b.list)
|
||||||
|
if _, ok := b.list[key]; ok {
|
||||||
|
n--
|
||||||
|
}
|
||||||
|
list := make(baggage.List, n)
|
||||||
|
|
||||||
|
for k, v := range b.list {
|
||||||
|
if k == key {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
list[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return Baggage{list: list}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of list-members in the Baggage.
|
||||||
|
func (b Baggage) Len() int {
|
||||||
|
return len(b.list)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String encodes Baggage into a string compliant with the W3C Baggage
|
||||||
|
// specification. The returned string will be invalid if the Baggage contains
|
||||||
|
// any invalid list-members.
|
||||||
|
func (b Baggage) String() string {
|
||||||
|
members := make([]string, 0, len(b.list))
|
||||||
|
for k, v := range b.list {
|
||||||
|
members = append(members, Member{
|
||||||
|
key: k,
|
||||||
|
value: v.Value,
|
||||||
|
properties: fromInternalProperties(v.Properties),
|
||||||
|
}.String())
|
||||||
|
}
|
||||||
|
return strings.Join(members, listDelimiter)
|
||||||
|
}
|
||||||
39
vendor/go.opentelemetry.io/otel/baggage/context.go
generated
vendored
Normal file
39
vendor/go.opentelemetry.io/otel/baggage/context.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright The 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 baggage // import "go.opentelemetry.io/otel/baggage"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/internal/baggage"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContextWithBaggage returns a copy of parent with baggage.
|
||||||
|
func ContextWithBaggage(parent context.Context, b Baggage) context.Context {
|
||||||
|
// Delegate so any hooks for the OpenTracing bridge are handled.
|
||||||
|
return baggage.ContextWithList(parent, b.list)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextWithoutBaggage returns a copy of parent with no baggage.
|
||||||
|
func ContextWithoutBaggage(parent context.Context) context.Context {
|
||||||
|
// Delegate so any hooks for the OpenTracing bridge are handled.
|
||||||
|
return baggage.ContextWithList(parent, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContext returns the baggage contained in ctx.
|
||||||
|
func FromContext(ctx context.Context) Baggage {
|
||||||
|
// Delegate so any hooks for the OpenTracing bridge are handled.
|
||||||
|
return Baggage{list: baggage.ListFromContext(ctx)}
|
||||||
|
}
|
||||||
20
vendor/go.opentelemetry.io/otel/baggage/doc.go
generated
vendored
Normal file
20
vendor/go.opentelemetry.io/otel/baggage/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright The 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 baggage provides functionality for storing and retrieving
|
||||||
|
baggage items in Go context. For propagating the baggage, see the
|
||||||
|
go.opentelemetry.io/otel/propagation package.
|
||||||
|
*/
|
||||||
|
package baggage // import "go.opentelemetry.io/otel/baggage"
|
||||||
106
vendor/go.opentelemetry.io/otel/codes/codes.go
generated
vendored
Normal file
106
vendor/go.opentelemetry.io/otel/codes/codes.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
// Copyright The 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 codes // import "go.opentelemetry.io/otel/codes"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Unset is the default status code.
|
||||||
|
Unset Code = 0
|
||||||
|
// Error indicates the operation contains an error.
|
||||||
|
Error Code = 1
|
||||||
|
// Ok indicates operation has been validated by an Application developers
|
||||||
|
// or Operator to have completed successfully, or contain no error.
|
||||||
|
Ok Code = 2
|
||||||
|
|
||||||
|
maxCode = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// Code is an 32-bit representation of a status state.
|
||||||
|
type Code uint32
|
||||||
|
|
||||||
|
var codeToStr = map[Code]string{
|
||||||
|
Unset: "Unset",
|
||||||
|
Error: "Error",
|
||||||
|
Ok: "Ok",
|
||||||
|
}
|
||||||
|
|
||||||
|
var strToCode = map[string]Code{
|
||||||
|
`"Unset"`: Unset,
|
||||||
|
`"Error"`: Error,
|
||||||
|
`"Ok"`: Ok,
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the Code as a string.
|
||||||
|
func (c Code) String() string {
|
||||||
|
return codeToStr[c]
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals b into the Code.
|
||||||
|
//
|
||||||
|
// This is based on the functionality in the gRPC codes package:
|
||||||
|
// https://github.com/grpc/grpc-go/blob/bb64fee312b46ebee26be43364a7a966033521b1/codes/codes.go#L218-L244
|
||||||
|
func (c *Code) UnmarshalJSON(b []byte) error {
|
||||||
|
// From json.Unmarshaler: By convention, to approximate the behavior of
|
||||||
|
// Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
|
||||||
|
// a no-op.
|
||||||
|
if string(b) == "null" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if c == nil {
|
||||||
|
return fmt.Errorf("nil receiver passed to UnmarshalJSON")
|
||||||
|
}
|
||||||
|
|
||||||
|
var x interface{}
|
||||||
|
if err := json.Unmarshal(b, &x); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch x.(type) {
|
||||||
|
case string:
|
||||||
|
if jc, ok := strToCode[string(b)]; ok {
|
||||||
|
*c = jc
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("invalid code: %q", string(b))
|
||||||
|
case float64:
|
||||||
|
if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
|
||||||
|
if ci >= maxCode {
|
||||||
|
return fmt.Errorf("invalid code: %q", ci)
|
||||||
|
}
|
||||||
|
|
||||||
|
*c = Code(ci)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("invalid code: %q", string(b))
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid code: %q", string(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON returns c as the JSON encoding of c.
|
||||||
|
func (c *Code) MarshalJSON() ([]byte, error) {
|
||||||
|
if c == nil {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
str, ok := codeToStr[*c]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid code: %d", *c)
|
||||||
|
}
|
||||||
|
return []byte(fmt.Sprintf("%q", str)), nil
|
||||||
|
}
|
||||||
21
vendor/go.opentelemetry.io/otel/codes/doc.go
generated
vendored
Normal file
21
vendor/go.opentelemetry.io/otel/codes/doc.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright The 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 codes defines the canonical error codes used by OpenTelemetry.
|
||||||
|
|
||||||
|
It conforms to [the OpenTelemetry
|
||||||
|
specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#statuscanonicalcode).
|
||||||
|
*/
|
||||||
|
package codes // import "go.opentelemetry.io/otel/codes"
|
||||||
34
vendor/go.opentelemetry.io/otel/doc.go
generated
vendored
Normal file
34
vendor/go.opentelemetry.io/otel/doc.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// Copyright The 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 otel provides global access to the OpenTelemetry API. The subpackages of
|
||||||
|
the otel package provide an implementation of the OpenTelemetry API.
|
||||||
|
|
||||||
|
The provided API is used to instrument code and measure data about that code's
|
||||||
|
performance and operation. The measured data, by default, is not processed or
|
||||||
|
transmitted anywhere. An implementation of the OpenTelemetry SDK, like the
|
||||||
|
default SDK implementation (go.opentelemetry.io/otel/sdk), and associated
|
||||||
|
exporters are used to process and transport this data.
|
||||||
|
|
||||||
|
To read the getting started guide, see https://opentelemetry.io/docs/go/getting-started/.
|
||||||
|
|
||||||
|
To read more about tracing, see go.opentelemetry.io/otel/trace.
|
||||||
|
|
||||||
|
To read more about metrics, see go.opentelemetry.io/otel/metric.
|
||||||
|
|
||||||
|
To read more about propagation, see go.opentelemetry.io/otel/propagation and
|
||||||
|
go.opentelemetry.io/otel/baggage.
|
||||||
|
*/
|
||||||
|
package otel // import "go.opentelemetry.io/otel"
|
||||||
38
vendor/go.opentelemetry.io/otel/error_handler.go
generated
vendored
Normal file
38
vendor/go.opentelemetry.io/otel/error_handler.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// Copyright The 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 otel // import "go.opentelemetry.io/otel"
|
||||||
|
|
||||||
|
// ErrorHandler handles irremediable events.
|
||||||
|
type ErrorHandler interface {
|
||||||
|
// DO NOT CHANGE: any modification will not be backwards compatible and
|
||||||
|
// must never be done outside of a new major release.
|
||||||
|
|
||||||
|
// Handle handles any error deemed irremediable by an OpenTelemetry
|
||||||
|
// component.
|
||||||
|
Handle(error)
|
||||||
|
// DO NOT CHANGE: any modification will not be backwards compatible and
|
||||||
|
// must never be done outside of a new major release.
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorHandlerFunc is a convenience adapter to allow the use of a function
|
||||||
|
// as an ErrorHandler.
|
||||||
|
type ErrorHandlerFunc func(error)
|
||||||
|
|
||||||
|
var _ ErrorHandler = ErrorHandlerFunc(nil)
|
||||||
|
|
||||||
|
// Handle handles the irremediable error by calling the ErrorHandlerFunc itself.
|
||||||
|
func (f ErrorHandlerFunc) Handle(err error) {
|
||||||
|
f(err)
|
||||||
|
}
|
||||||
201
vendor/go.opentelemetry.io/otel/exporters/stdout/stdoutmetric/LICENSE
generated
vendored
Normal file
201
vendor/go.opentelemetry.io/otel/exporters/stdout/stdoutmetric/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
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.
|
||||||
114
vendor/go.opentelemetry.io/otel/exporters/stdout/stdoutmetric/config.go
generated
vendored
Normal file
114
vendor/go.opentelemetry.io/otel/exporters/stdout/stdoutmetric/config.go
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
// Copyright The 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 stdoutmetric // import "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultWriter = os.Stdout
|
||||||
|
defaultPrettyPrint = false
|
||||||
|
defaultTimestamps = true
|
||||||
|
defaultLabelEncoder = attribute.DefaultEncoder()
|
||||||
|
)
|
||||||
|
|
||||||
|
// config contains options for the STDOUT exporter.
|
||||||
|
type config struct {
|
||||||
|
// Writer is the destination. If not set, os.Stdout is used.
|
||||||
|
Writer io.Writer
|
||||||
|
|
||||||
|
// PrettyPrint will encode the output into readable JSON. Default is
|
||||||
|
// false.
|
||||||
|
PrettyPrint bool
|
||||||
|
|
||||||
|
// Timestamps specifies if timestamps should be printed. Default is
|
||||||
|
// true.
|
||||||
|
Timestamps bool
|
||||||
|
|
||||||
|
// LabelEncoder encodes the labels.
|
||||||
|
LabelEncoder attribute.Encoder
|
||||||
|
}
|
||||||
|
|
||||||
|
// newConfig creates a validated Config configured with options.
|
||||||
|
func newConfig(options ...Option) (config, error) {
|
||||||
|
cfg := config{
|
||||||
|
Writer: defaultWriter,
|
||||||
|
PrettyPrint: defaultPrettyPrint,
|
||||||
|
Timestamps: defaultTimestamps,
|
||||||
|
LabelEncoder: defaultLabelEncoder,
|
||||||
|
}
|
||||||
|
for _, opt := range options {
|
||||||
|
opt.apply(&cfg)
|
||||||
|
|
||||||
|
}
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option sets the value of an option for a Config.
|
||||||
|
type Option interface {
|
||||||
|
apply(*config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithWriter sets the export stream destination.
|
||||||
|
func WithWriter(w io.Writer) Option {
|
||||||
|
return writerOption{w}
|
||||||
|
}
|
||||||
|
|
||||||
|
type writerOption struct {
|
||||||
|
W io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o writerOption) apply(cfg *config) {
|
||||||
|
cfg.Writer = o.W
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPrettyPrint sets the export stream format to use JSON.
|
||||||
|
func WithPrettyPrint() Option {
|
||||||
|
return prettyPrintOption(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
type prettyPrintOption bool
|
||||||
|
|
||||||
|
func (o prettyPrintOption) apply(cfg *config) {
|
||||||
|
cfg.PrettyPrint = bool(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithoutTimestamps sets the export stream to not include timestamps.
|
||||||
|
func WithoutTimestamps() Option {
|
||||||
|
return timestampsOption(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
type timestampsOption bool
|
||||||
|
|
||||||
|
func (o timestampsOption) apply(cfg *config) {
|
||||||
|
cfg.Timestamps = bool(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithLabelEncoder sets the label encoder used in export.
|
||||||
|
func WithLabelEncoder(enc attribute.Encoder) Option {
|
||||||
|
return labelEncoderOption{enc}
|
||||||
|
}
|
||||||
|
|
||||||
|
type labelEncoderOption struct {
|
||||||
|
LabelEncoder attribute.Encoder
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o labelEncoderOption) apply(cfg *config) {
|
||||||
|
cfg.LabelEncoder = o.LabelEncoder
|
||||||
|
}
|
||||||
21
vendor/go.opentelemetry.io/otel/exporters/stdout/stdoutmetric/doc.go
generated
vendored
Normal file
21
vendor/go.opentelemetry.io/otel/exporters/stdout/stdoutmetric/doc.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright The 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 stdout contains an OpenTelemetry exporter for metric telemetry
|
||||||
|
// to be written to an output destination as JSON.
|
||||||
|
//
|
||||||
|
// This package is currently in a pre-GA phase. Backwards incompatible changes
|
||||||
|
// may be introduced in subsequent minor version releases as we work to track
|
||||||
|
// the evolving OpenTelemetry specification and user feedback.
|
||||||
|
package stdoutmetric // import "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
|
||||||
38
vendor/go.opentelemetry.io/otel/exporters/stdout/stdoutmetric/exporter.go
generated
vendored
Normal file
38
vendor/go.opentelemetry.io/otel/exporters/stdout/stdoutmetric/exporter.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// Copyright The 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 stdoutmetric // import "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Exporter struct {
|
||||||
|
metricExporter
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ metric.Exporter = &Exporter{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// New creates an Exporter with the passed options.
|
||||||
|
func New(options ...Option) (*Exporter, error) {
|
||||||
|
cfg, err := newConfig(options...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Exporter{
|
||||||
|
metricExporter: metricExporter{cfg},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
167
vendor/go.opentelemetry.io/otel/exporters/stdout/stdoutmetric/metric.go
generated
vendored
Normal file
167
vendor/go.opentelemetry.io/otel/exporters/stdout/stdoutmetric/metric.go
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
// Copyright The 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 stdoutmetric // import "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
exportmetric "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||||
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
type metricExporter struct {
|
||||||
|
config config
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ exportmetric.Exporter = &metricExporter{}
|
||||||
|
|
||||||
|
type line struct {
|
||||||
|
Name string `json:"Name"`
|
||||||
|
Min interface{} `json:"Min,omitempty"`
|
||||||
|
Max interface{} `json:"Max,omitempty"`
|
||||||
|
Sum interface{} `json:"Sum,omitempty"`
|
||||||
|
Count interface{} `json:"Count,omitempty"`
|
||||||
|
LastValue interface{} `json:"Last,omitempty"`
|
||||||
|
|
||||||
|
// Note: this is a pointer because omitempty doesn't work when time.IsZero()
|
||||||
|
Timestamp *time.Time `json:"Timestamp,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *metricExporter) TemporalityFor(desc *sdkapi.Descriptor, kind aggregation.Kind) aggregation.Temporality {
|
||||||
|
return aggregation.StatelessTemporalitySelector().TemporalityFor(desc, kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *metricExporter) Export(_ context.Context, res *resource.Resource, reader exportmetric.InstrumentationLibraryReader) error {
|
||||||
|
var aggError error
|
||||||
|
var batch []line
|
||||||
|
aggError = reader.ForEach(func(lib instrumentation.Library, mr exportmetric.Reader) error {
|
||||||
|
|
||||||
|
var instLabels []attribute.KeyValue
|
||||||
|
if name := lib.Name; name != "" {
|
||||||
|
instLabels = append(instLabels, attribute.String("instrumentation.name", name))
|
||||||
|
if version := lib.Version; version != "" {
|
||||||
|
instLabels = append(instLabels, attribute.String("instrumentation.version", version))
|
||||||
|
}
|
||||||
|
if schema := lib.SchemaURL; schema != "" {
|
||||||
|
instLabels = append(instLabels, attribute.String("instrumentation.schema_url", schema))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
instSet := attribute.NewSet(instLabels...)
|
||||||
|
encodedInstLabels := instSet.Encoded(e.config.LabelEncoder)
|
||||||
|
|
||||||
|
return mr.ForEach(e, func(record exportmetric.Record) error {
|
||||||
|
desc := record.Descriptor()
|
||||||
|
agg := record.Aggregation()
|
||||||
|
kind := desc.NumberKind()
|
||||||
|
encodedResource := res.Encoded(e.config.LabelEncoder)
|
||||||
|
|
||||||
|
var expose line
|
||||||
|
|
||||||
|
if sum, ok := agg.(aggregation.Sum); ok {
|
||||||
|
value, err := sum.Sum()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
expose.Sum = value.AsInterface(kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mmsc, ok := agg.(aggregation.MinMaxSumCount); ok {
|
||||||
|
count, err := mmsc.Count()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
expose.Count = count
|
||||||
|
|
||||||
|
max, err := mmsc.Max()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
expose.Max = max.AsInterface(kind)
|
||||||
|
|
||||||
|
min, err := mmsc.Min()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
expose.Min = min.AsInterface(kind)
|
||||||
|
} else if lv, ok := agg.(aggregation.LastValue); ok {
|
||||||
|
value, timestamp, err := lv.LastValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
expose.LastValue = value.AsInterface(kind)
|
||||||
|
|
||||||
|
if e.config.Timestamps {
|
||||||
|
expose.Timestamp = ×tamp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var encodedLabels string
|
||||||
|
iter := record.Labels().Iter()
|
||||||
|
if iter.Len() > 0 {
|
||||||
|
encodedLabels = record.Labels().Encoded(e.config.LabelEncoder)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb strings.Builder
|
||||||
|
|
||||||
|
sb.WriteString(desc.Name())
|
||||||
|
|
||||||
|
if len(encodedLabels) > 0 || len(encodedResource) > 0 || len(encodedInstLabels) > 0 {
|
||||||
|
sb.WriteRune('{')
|
||||||
|
sb.WriteString(encodedResource)
|
||||||
|
if len(encodedInstLabels) > 0 && len(encodedResource) > 0 {
|
||||||
|
sb.WriteRune(',')
|
||||||
|
}
|
||||||
|
sb.WriteString(encodedInstLabels)
|
||||||
|
if len(encodedLabels) > 0 && (len(encodedInstLabels) > 0 || len(encodedResource) > 0) {
|
||||||
|
sb.WriteRune(',')
|
||||||
|
}
|
||||||
|
sb.WriteString(encodedLabels)
|
||||||
|
sb.WriteRune('}')
|
||||||
|
}
|
||||||
|
|
||||||
|
expose.Name = sb.String()
|
||||||
|
|
||||||
|
batch = append(batch, expose)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if len(batch) == 0 {
|
||||||
|
return aggError
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := e.marshal(batch)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintln(e.config.Writer, string(data))
|
||||||
|
|
||||||
|
return aggError
|
||||||
|
}
|
||||||
|
|
||||||
|
// marshal v with appropriate indentation.
|
||||||
|
func (e *metricExporter) marshal(v interface{}) ([]byte, error) {
|
||||||
|
if e.config.PrettyPrint {
|
||||||
|
return json.MarshalIndent(v, "", "\t")
|
||||||
|
}
|
||||||
|
return json.Marshal(v)
|
||||||
|
}
|
||||||
41
vendor/go.opentelemetry.io/otel/get_main_pkgs.sh
generated
vendored
Normal file
41
vendor/go.opentelemetry.io/otel/get_main_pkgs.sh
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright The 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.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
top_dir='.'
|
||||||
|
if [[ $# -gt 0 ]]; then
|
||||||
|
top_dir="${1}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
p=$(pwd)
|
||||||
|
mod_dirs=()
|
||||||
|
|
||||||
|
# Note `mapfile` does not exist in older bash versions:
|
||||||
|
# https://stackoverflow.com/questions/41475261/need-alternative-to-readarray-mapfile-for-script-on-older-version-of-bash
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
mod_dirs+=("$line")
|
||||||
|
done < <(find "${top_dir}" -type f -name 'go.mod' -exec dirname {} \; | sort)
|
||||||
|
|
||||||
|
for mod_dir in "${mod_dirs[@]}"; do
|
||||||
|
cd "${mod_dir}"
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
echo ".${line#${p}}"
|
||||||
|
done < <(go list --find -f '{{.Name}}|{{.Dir}}' ./... | grep '^main|' | cut -f 2- -d '|')
|
||||||
|
cd "${p}"
|
||||||
|
done
|
||||||
107
vendor/go.opentelemetry.io/otel/handler.go
generated
vendored
Normal file
107
vendor/go.opentelemetry.io/otel/handler.go
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
// Copyright The 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 otel // import "go.opentelemetry.io/otel"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// globalErrorHandler provides an ErrorHandler that can be used
|
||||||
|
// throughout an OpenTelemetry instrumented project. When a user
|
||||||
|
// specified ErrorHandler is registered (`SetErrorHandler`) all calls to
|
||||||
|
// `Handle` and will be delegated to the registered ErrorHandler.
|
||||||
|
globalErrorHandler = defaultErrorHandler()
|
||||||
|
|
||||||
|
// delegateErrorHandlerOnce ensures that a user provided ErrorHandler is
|
||||||
|
// only ever registered once.
|
||||||
|
delegateErrorHandlerOnce sync.Once
|
||||||
|
|
||||||
|
// Compile-time check that delegator implements ErrorHandler.
|
||||||
|
_ ErrorHandler = (*delegator)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
type holder struct {
|
||||||
|
eh ErrorHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultErrorHandler() *atomic.Value {
|
||||||
|
v := &atomic.Value{}
|
||||||
|
v.Store(holder{eh: &delegator{l: log.New(os.Stderr, "", log.LstdFlags)}})
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// delegator logs errors if no delegate is set, otherwise they are delegated.
|
||||||
|
type delegator struct {
|
||||||
|
delegate atomic.Value
|
||||||
|
|
||||||
|
l *log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// setDelegate sets the ErrorHandler delegate.
|
||||||
|
func (h *delegator) setDelegate(d ErrorHandler) {
|
||||||
|
// It is critical this is guarded with delegateErrorHandlerOnce, if it is
|
||||||
|
// called again with a different concrete type it will panic.
|
||||||
|
h.delegate.Store(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle logs err if no delegate is set, otherwise it is delegated.
|
||||||
|
func (h *delegator) Handle(err error) {
|
||||||
|
if d := h.delegate.Load(); d != nil {
|
||||||
|
d.(ErrorHandler).Handle(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.l.Print(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetErrorHandler returns the global ErrorHandler instance.
|
||||||
|
//
|
||||||
|
// The default ErrorHandler instance returned will log all errors to STDERR
|
||||||
|
// until an override ErrorHandler is set with SetErrorHandler. All
|
||||||
|
// ErrorHandler returned prior to this will automatically forward errors to
|
||||||
|
// the set instance instead of logging.
|
||||||
|
//
|
||||||
|
// Subsequent calls to SetErrorHandler after the first will not forward errors
|
||||||
|
// to the new ErrorHandler for prior returned instances.
|
||||||
|
func GetErrorHandler() ErrorHandler {
|
||||||
|
return globalErrorHandler.Load().(holder).eh
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetErrorHandler sets the global ErrorHandler to h.
|
||||||
|
//
|
||||||
|
// The first time this is called all ErrorHandler previously returned from
|
||||||
|
// GetErrorHandler will send errors to h instead of the default logging
|
||||||
|
// ErrorHandler. Subsequent calls will set the global ErrorHandler, but not
|
||||||
|
// delegate errors to h.
|
||||||
|
func SetErrorHandler(h ErrorHandler) {
|
||||||
|
delegateErrorHandlerOnce.Do(func() {
|
||||||
|
current := GetErrorHandler()
|
||||||
|
if current == h {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if internalHandler, ok := current.(*delegator); ok {
|
||||||
|
internalHandler.setDelegate(h)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
globalErrorHandler.Store(holder{eh: h})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is a convenience function for ErrorHandler().Handle(err)
|
||||||
|
func Handle(err error) {
|
||||||
|
GetErrorHandler().Handle(err)
|
||||||
|
}
|
||||||
43
vendor/go.opentelemetry.io/otel/internal/baggage/baggage.go
generated
vendored
Normal file
43
vendor/go.opentelemetry.io/otel/internal/baggage/baggage.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// Copyright The 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 baggage provides base types and functionality to store and retrieve
|
||||||
|
baggage in Go context. This package exists because the OpenTracing bridge to
|
||||||
|
OpenTelemetry needs to synchronize state whenever baggage for a context is
|
||||||
|
modified and that context contains an OpenTracing span. If it were not for
|
||||||
|
this need this package would not need to exist and the
|
||||||
|
`go.opentelemetry.io/otel/baggage` package would be the singular place where
|
||||||
|
W3C baggage is handled.
|
||||||
|
*/
|
||||||
|
package baggage // import "go.opentelemetry.io/otel/internal/baggage"
|
||||||
|
|
||||||
|
// List is the collection of baggage members. The W3C allows for duplicates,
|
||||||
|
// but OpenTelemetry does not, therefore, this is represented as a map.
|
||||||
|
type List map[string]Item
|
||||||
|
|
||||||
|
// Item is the value and metadata properties part of a list-member.
|
||||||
|
type Item struct {
|
||||||
|
Value string
|
||||||
|
Properties []Property
|
||||||
|
}
|
||||||
|
|
||||||
|
// Property is a metadata entry for a list-member.
|
||||||
|
type Property struct {
|
||||||
|
Key, Value string
|
||||||
|
|
||||||
|
// HasValue indicates if a zero-value value means the property does not
|
||||||
|
// have a value or if it was the zero-value.
|
||||||
|
HasValue bool
|
||||||
|
}
|
||||||
95
vendor/go.opentelemetry.io/otel/internal/baggage/context.go
generated
vendored
Normal file
95
vendor/go.opentelemetry.io/otel/internal/baggage/context.go
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
// Copyright The 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 baggage // import "go.opentelemetry.io/otel/internal/baggage"
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
type baggageContextKeyType int
|
||||||
|
|
||||||
|
const baggageKey baggageContextKeyType = iota
|
||||||
|
|
||||||
|
// SetHookFunc is a callback called when storing baggage in the context.
|
||||||
|
type SetHookFunc func(context.Context, List) context.Context
|
||||||
|
|
||||||
|
// GetHookFunc is a callback called when getting baggage from the context.
|
||||||
|
type GetHookFunc func(context.Context, List) List
|
||||||
|
|
||||||
|
type baggageState struct {
|
||||||
|
list List
|
||||||
|
|
||||||
|
setHook SetHookFunc
|
||||||
|
getHook GetHookFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextWithSetHook returns a copy of parent with hook configured to be
|
||||||
|
// invoked every time ContextWithBaggage is called.
|
||||||
|
//
|
||||||
|
// Passing nil SetHookFunc creates a context with no set hook to call.
|
||||||
|
func ContextWithSetHook(parent context.Context, hook SetHookFunc) context.Context {
|
||||||
|
var s baggageState
|
||||||
|
switch v := parent.Value(baggageKey).(type) {
|
||||||
|
case baggageState:
|
||||||
|
s = v
|
||||||
|
}
|
||||||
|
|
||||||
|
s.setHook = hook
|
||||||
|
return context.WithValue(parent, baggageKey, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextWithGetHook returns a copy of parent with hook configured to be
|
||||||
|
// invoked every time FromContext is called.
|
||||||
|
//
|
||||||
|
// Passing nil GetHookFunc creates a context with no get hook to call.
|
||||||
|
func ContextWithGetHook(parent context.Context, hook GetHookFunc) context.Context {
|
||||||
|
var s baggageState
|
||||||
|
switch v := parent.Value(baggageKey).(type) {
|
||||||
|
case baggageState:
|
||||||
|
s = v
|
||||||
|
}
|
||||||
|
|
||||||
|
s.getHook = hook
|
||||||
|
return context.WithValue(parent, baggageKey, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextWithList returns a copy of parent with baggage. Passing nil list
|
||||||
|
// returns a context without any baggage.
|
||||||
|
func ContextWithList(parent context.Context, list List) context.Context {
|
||||||
|
var s baggageState
|
||||||
|
switch v := parent.Value(baggageKey).(type) {
|
||||||
|
case baggageState:
|
||||||
|
s = v
|
||||||
|
}
|
||||||
|
|
||||||
|
s.list = list
|
||||||
|
ctx := context.WithValue(parent, baggageKey, s)
|
||||||
|
if s.setHook != nil {
|
||||||
|
ctx = s.setHook(ctx, list)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFromContext returns the baggage contained in ctx.
|
||||||
|
func ListFromContext(ctx context.Context) List {
|
||||||
|
switch v := ctx.Value(baggageKey).(type) {
|
||||||
|
case baggageState:
|
||||||
|
if v.getHook != nil {
|
||||||
|
return v.getHook(ctx, v.list)
|
||||||
|
}
|
||||||
|
return v.list
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
82
vendor/go.opentelemetry.io/otel/internal/global/propagator.go
generated
vendored
Normal file
82
vendor/go.opentelemetry.io/otel/internal/global/propagator.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright The 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 global // import "go.opentelemetry.io/otel/internal/global"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/propagation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// textMapPropagator is a default TextMapPropagator that delegates calls to a
|
||||||
|
// registered delegate if one is set, otherwise it defaults to delegating the
|
||||||
|
// calls to a the default no-op propagation.TextMapPropagator.
|
||||||
|
type textMapPropagator struct {
|
||||||
|
mtx sync.Mutex
|
||||||
|
once sync.Once
|
||||||
|
delegate propagation.TextMapPropagator
|
||||||
|
noop propagation.TextMapPropagator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile-time guarantee that textMapPropagator implements the
|
||||||
|
// propagation.TextMapPropagator interface.
|
||||||
|
var _ propagation.TextMapPropagator = (*textMapPropagator)(nil)
|
||||||
|
|
||||||
|
func newTextMapPropagator() *textMapPropagator {
|
||||||
|
return &textMapPropagator{
|
||||||
|
noop: propagation.NewCompositeTextMapPropagator(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDelegate sets a delegate propagation.TextMapPropagator that all calls are
|
||||||
|
// forwarded to. Delegation can only be performed once, all subsequent calls
|
||||||
|
// perform no delegation.
|
||||||
|
func (p *textMapPropagator) SetDelegate(delegate propagation.TextMapPropagator) {
|
||||||
|
if delegate == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.mtx.Lock()
|
||||||
|
p.once.Do(func() { p.delegate = delegate })
|
||||||
|
p.mtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// effectiveDelegate returns the current delegate of p if one is set,
|
||||||
|
// otherwise the default noop TextMapPropagator is returned. This method
|
||||||
|
// can be called concurrently.
|
||||||
|
func (p *textMapPropagator) effectiveDelegate() propagation.TextMapPropagator {
|
||||||
|
p.mtx.Lock()
|
||||||
|
defer p.mtx.Unlock()
|
||||||
|
if p.delegate != nil {
|
||||||
|
return p.delegate
|
||||||
|
}
|
||||||
|
return p.noop
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inject set cross-cutting concerns from the Context into the carrier.
|
||||||
|
func (p *textMapPropagator) Inject(ctx context.Context, carrier propagation.TextMapCarrier) {
|
||||||
|
p.effectiveDelegate().Inject(ctx, carrier)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract reads cross-cutting concerns from the carrier into a Context.
|
||||||
|
func (p *textMapPropagator) Extract(ctx context.Context, carrier propagation.TextMapCarrier) context.Context {
|
||||||
|
return p.effectiveDelegate().Extract(ctx, carrier)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fields returns the keys whose values are set with Inject.
|
||||||
|
func (p *textMapPropagator) Fields() []string {
|
||||||
|
return p.effectiveDelegate().Fields()
|
||||||
|
}
|
||||||
106
vendor/go.opentelemetry.io/otel/internal/global/state.go
generated
vendored
Normal file
106
vendor/go.opentelemetry.io/otel/internal/global/state.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
// Copyright The 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 global // import "go.opentelemetry.io/otel/internal/global"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/propagation"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
tracerProviderHolder struct {
|
||||||
|
tp trace.TracerProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
propagatorsHolder struct {
|
||||||
|
tm propagation.TextMapPropagator
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
globalTracer = defaultTracerValue()
|
||||||
|
globalPropagators = defaultPropagatorsValue()
|
||||||
|
|
||||||
|
delegateTraceOnce sync.Once
|
||||||
|
delegateTextMapPropagatorOnce sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// TracerProvider is the internal implementation for global.TracerProvider.
|
||||||
|
func TracerProvider() trace.TracerProvider {
|
||||||
|
return globalTracer.Load().(tracerProviderHolder).tp
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTracerProvider is the internal implementation for global.SetTracerProvider.
|
||||||
|
func SetTracerProvider(tp trace.TracerProvider) {
|
||||||
|
delegateTraceOnce.Do(func() {
|
||||||
|
current := TracerProvider()
|
||||||
|
if current == tp {
|
||||||
|
// Setting the provider to the prior default is nonsense, panic.
|
||||||
|
// Panic is acceptable because we are likely still early in the
|
||||||
|
// process lifetime.
|
||||||
|
panic("invalid TracerProvider, the global instance cannot be reinstalled")
|
||||||
|
} else if def, ok := current.(*tracerProvider); ok {
|
||||||
|
def.setDelegate(tp)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
globalTracer.Store(tracerProviderHolder{tp: tp})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextMapPropagator is the internal implementation for global.TextMapPropagator.
|
||||||
|
func TextMapPropagator() propagation.TextMapPropagator {
|
||||||
|
return globalPropagators.Load().(propagatorsHolder).tm
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTextMapPropagator is the internal implementation for global.SetTextMapPropagator.
|
||||||
|
func SetTextMapPropagator(p propagation.TextMapPropagator) {
|
||||||
|
// For the textMapPropagator already returned by TextMapPropagator
|
||||||
|
// delegate to p.
|
||||||
|
delegateTextMapPropagatorOnce.Do(func() {
|
||||||
|
if current := TextMapPropagator(); current == p {
|
||||||
|
// Setting the provider to the prior default is nonsense, panic.
|
||||||
|
// Panic is acceptable because we are likely still early in the
|
||||||
|
// process lifetime.
|
||||||
|
panic("invalid TextMapPropagator, the global instance cannot be reinstalled")
|
||||||
|
} else if def, ok := current.(*textMapPropagator); ok {
|
||||||
|
def.SetDelegate(p)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Return p when subsequent calls to TextMapPropagator are made.
|
||||||
|
globalPropagators.Store(propagatorsHolder{tm: p})
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultTracerValue() *atomic.Value {
|
||||||
|
v := &atomic.Value{}
|
||||||
|
v.Store(tracerProviderHolder{tp: &tracerProvider{}})
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultPropagatorsValue() *atomic.Value {
|
||||||
|
v := &atomic.Value{}
|
||||||
|
v.Store(propagatorsHolder{tm: newTextMapPropagator()})
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetForTest restores the initial global state, for testing purposes.
|
||||||
|
func ResetForTest() {
|
||||||
|
globalTracer = defaultTracerValue()
|
||||||
|
globalPropagators = defaultPropagatorsValue()
|
||||||
|
delegateTraceOnce = sync.Once{}
|
||||||
|
delegateTextMapPropagatorOnce = sync.Once{}
|
||||||
|
}
|
||||||
192
vendor/go.opentelemetry.io/otel/internal/global/trace.go
generated
vendored
Normal file
192
vendor/go.opentelemetry.io/otel/internal/global/trace.go
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
// Copyright The 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 global // import "go.opentelemetry.io/otel/internal/global"
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file contains the forwarding implementation of the TracerProvider used as
|
||||||
|
the default global instance. Prior to initialization of an SDK, Tracers
|
||||||
|
returned by the global TracerProvider will provide no-op functionality. This
|
||||||
|
means that all Span created prior to initialization are no-op Spans.
|
||||||
|
|
||||||
|
Once an SDK has been initialized, all provided no-op Tracers are swapped for
|
||||||
|
Tracers provided by the SDK defined TracerProvider. However, any Span started
|
||||||
|
prior to this initialization does not change its behavior. Meaning, the Span
|
||||||
|
remains a no-op Span.
|
||||||
|
|
||||||
|
The implementation to track and swap Tracers locks all new Tracer creation
|
||||||
|
until the swap is complete. This assumes that this operation is not
|
||||||
|
performance-critical. If that assumption is incorrect, be sure to configure an
|
||||||
|
SDK prior to any Tracer creation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/codes"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
// tracerProvider is a placeholder for a configured SDK TracerProvider.
|
||||||
|
//
|
||||||
|
// All TracerProvider functionality is forwarded to a delegate once
|
||||||
|
// configured.
|
||||||
|
type tracerProvider struct {
|
||||||
|
mtx sync.Mutex
|
||||||
|
tracers map[il]*tracer
|
||||||
|
delegate trace.TracerProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile-time guarantee that tracerProvider implements the TracerProvider
|
||||||
|
// interface.
|
||||||
|
var _ trace.TracerProvider = &tracerProvider{}
|
||||||
|
|
||||||
|
// setDelegate configures p to delegate all TracerProvider functionality to
|
||||||
|
// provider.
|
||||||
|
//
|
||||||
|
// All Tracers provided prior to this function call are switched out to be
|
||||||
|
// Tracers provided by provider.
|
||||||
|
//
|
||||||
|
// It is guaranteed by the caller that this happens only once.
|
||||||
|
func (p *tracerProvider) setDelegate(provider trace.TracerProvider) {
|
||||||
|
p.mtx.Lock()
|
||||||
|
defer p.mtx.Unlock()
|
||||||
|
|
||||||
|
p.delegate = provider
|
||||||
|
|
||||||
|
if len(p.tracers) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, t := range p.tracers {
|
||||||
|
t.setDelegate(provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.tracers = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tracer implements TracerProvider.
|
||||||
|
func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
|
||||||
|
p.mtx.Lock()
|
||||||
|
defer p.mtx.Unlock()
|
||||||
|
|
||||||
|
if p.delegate != nil {
|
||||||
|
return p.delegate.Tracer(name, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this moment it is guaranteed that no sdk is installed, save the tracer in the tracers map.
|
||||||
|
|
||||||
|
c := trace.NewTracerConfig(opts...)
|
||||||
|
key := il{
|
||||||
|
name: name,
|
||||||
|
version: c.InstrumentationVersion(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.tracers == nil {
|
||||||
|
p.tracers = make(map[il]*tracer)
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := p.tracers[key]; ok {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
t := &tracer{name: name, opts: opts, provider: p}
|
||||||
|
p.tracers[key] = t
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
type il struct {
|
||||||
|
name string
|
||||||
|
version string
|
||||||
|
}
|
||||||
|
|
||||||
|
// tracer is a placeholder for a trace.Tracer.
|
||||||
|
//
|
||||||
|
// All Tracer functionality is forwarded to a delegate once configured.
|
||||||
|
// Otherwise, all functionality is forwarded to a NoopTracer.
|
||||||
|
type tracer struct {
|
||||||
|
name string
|
||||||
|
opts []trace.TracerOption
|
||||||
|
provider *tracerProvider
|
||||||
|
|
||||||
|
delegate atomic.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile-time guarantee that tracer implements the trace.Tracer interface.
|
||||||
|
var _ trace.Tracer = &tracer{}
|
||||||
|
|
||||||
|
// setDelegate configures t to delegate all Tracer functionality to Tracers
|
||||||
|
// created by provider.
|
||||||
|
//
|
||||||
|
// All subsequent calls to the Tracer methods will be passed to the delegate.
|
||||||
|
//
|
||||||
|
// It is guaranteed by the caller that this happens only once.
|
||||||
|
func (t *tracer) setDelegate(provider trace.TracerProvider) {
|
||||||
|
t.delegate.Store(provider.Tracer(t.name, t.opts...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start implements trace.Tracer by forwarding the call to t.delegate if
|
||||||
|
// set, otherwise it forwards the call to a NoopTracer.
|
||||||
|
func (t *tracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
||||||
|
delegate := t.delegate.Load()
|
||||||
|
if delegate != nil {
|
||||||
|
return delegate.(trace.Tracer).Start(ctx, name, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := nonRecordingSpan{sc: trace.SpanContextFromContext(ctx), tracer: t}
|
||||||
|
ctx = trace.ContextWithSpan(ctx, s)
|
||||||
|
return ctx, s
|
||||||
|
}
|
||||||
|
|
||||||
|
// nonRecordingSpan is a minimal implementation of a Span that wraps a
|
||||||
|
// SpanContext. It performs no operations other than to return the wrapped
|
||||||
|
// SpanContext.
|
||||||
|
type nonRecordingSpan struct {
|
||||||
|
sc trace.SpanContext
|
||||||
|
tracer *tracer
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ trace.Span = nonRecordingSpan{}
|
||||||
|
|
||||||
|
// SpanContext returns the wrapped SpanContext.
|
||||||
|
func (s nonRecordingSpan) SpanContext() trace.SpanContext { return s.sc }
|
||||||
|
|
||||||
|
// IsRecording always returns false.
|
||||||
|
func (nonRecordingSpan) IsRecording() bool { return false }
|
||||||
|
|
||||||
|
// SetStatus does nothing.
|
||||||
|
func (nonRecordingSpan) SetStatus(codes.Code, string) {}
|
||||||
|
|
||||||
|
// SetError does nothing.
|
||||||
|
func (nonRecordingSpan) SetError(bool) {}
|
||||||
|
|
||||||
|
// SetAttributes does nothing.
|
||||||
|
func (nonRecordingSpan) SetAttributes(...attribute.KeyValue) {}
|
||||||
|
|
||||||
|
// End does nothing.
|
||||||
|
func (nonRecordingSpan) End(...trace.SpanEndOption) {}
|
||||||
|
|
||||||
|
// RecordError does nothing.
|
||||||
|
func (nonRecordingSpan) RecordError(error, ...trace.EventOption) {}
|
||||||
|
|
||||||
|
// AddEvent does nothing.
|
||||||
|
func (nonRecordingSpan) AddEvent(string, ...trace.EventOption) {}
|
||||||
|
|
||||||
|
// SetName does nothing.
|
||||||
|
func (nonRecordingSpan) SetName(string) {}
|
||||||
|
|
||||||
|
func (s nonRecordingSpan) TracerProvider() trace.TracerProvider { return s.tracer.provider }
|
||||||
201
vendor/go.opentelemetry.io/otel/internal/metric/LICENSE
generated
vendored
Normal file
201
vendor/go.opentelemetry.io/otel/internal/metric/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
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.
|
||||||
149
vendor/go.opentelemetry.io/otel/internal/metric/async.go
generated
vendored
Normal file
149
vendor/go.opentelemetry.io/otel/internal/metric/async.go
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
// Copyright The 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 "go.opentelemetry.io/otel/internal/metric"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
//nolint:revive // ignoring missing comments for exported error in an internal package
|
||||||
|
var ErrInvalidAsyncRunner = errors.New("unknown async runner type")
|
||||||
|
|
||||||
|
// AsyncCollector is an interface used between the MeterImpl and the
|
||||||
|
// AsyncInstrumentState helper below. This interface is implemented by
|
||||||
|
// the SDK to provide support for running observer callbacks.
|
||||||
|
type AsyncCollector interface {
|
||||||
|
// CollectAsync passes a batch of observations to the MeterImpl.
|
||||||
|
CollectAsync(labels []attribute.KeyValue, observation ...sdkapi.Observation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncInstrumentState manages an ordered set of asynchronous
|
||||||
|
// instruments and the distinct runners, taking into account batch
|
||||||
|
// observer callbacks.
|
||||||
|
type AsyncInstrumentState struct {
|
||||||
|
lock sync.Mutex
|
||||||
|
|
||||||
|
// errorOnce will use the otel.Handler to report an error
|
||||||
|
// once in case of an invalid runner attempting to run.
|
||||||
|
errorOnce sync.Once
|
||||||
|
|
||||||
|
// runnerMap keeps the set of runners that will run each
|
||||||
|
// collection interval. Singletons are entered with a real
|
||||||
|
// instrument each, batch observers are entered with a nil
|
||||||
|
// instrument, ensuring that when a singleton callback is used
|
||||||
|
// repeatedly, it is executed repeatedly in the interval, while
|
||||||
|
// when a batch callback is used repeatedly, it only executes
|
||||||
|
// once per interval.
|
||||||
|
runnerMap map[asyncRunnerPair]struct{}
|
||||||
|
|
||||||
|
// runners maintains the set of runners in the order they were
|
||||||
|
// registered.
|
||||||
|
runners []asyncRunnerPair
|
||||||
|
|
||||||
|
// instruments maintains the set of instruments in the order
|
||||||
|
// they were registered.
|
||||||
|
instruments []sdkapi.AsyncImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// asyncRunnerPair is a map entry for Observer callback runners.
|
||||||
|
type asyncRunnerPair struct {
|
||||||
|
// runner is used as a map key here. The API ensures
|
||||||
|
// that all callbacks are pointers for this reason.
|
||||||
|
runner sdkapi.AsyncRunner
|
||||||
|
|
||||||
|
// inst refers to a non-nil instrument when `runner` is a
|
||||||
|
// AsyncSingleRunner.
|
||||||
|
inst sdkapi.AsyncImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAsyncInstrumentState returns a new *AsyncInstrumentState, for
|
||||||
|
// use by MeterImpl to manage running the set of observer callbacks in
|
||||||
|
// the correct order.
|
||||||
|
func NewAsyncInstrumentState() *AsyncInstrumentState {
|
||||||
|
return &AsyncInstrumentState{
|
||||||
|
runnerMap: map[asyncRunnerPair]struct{}{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instruments returns the asynchronous instruments managed by this
|
||||||
|
// object, the set that should be checkpointed after observers are
|
||||||
|
// run.
|
||||||
|
func (a *AsyncInstrumentState) Instruments() []sdkapi.AsyncImpl {
|
||||||
|
a.lock.Lock()
|
||||||
|
defer a.lock.Unlock()
|
||||||
|
return a.instruments
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register adds a new asynchronous instrument to by managed by this
|
||||||
|
// object. This should be called during NewAsyncInstrument() and
|
||||||
|
// assumes that errors (e.g., duplicate registration) have already
|
||||||
|
// been checked.
|
||||||
|
func (a *AsyncInstrumentState) Register(inst sdkapi.AsyncImpl, runner sdkapi.AsyncRunner) {
|
||||||
|
a.lock.Lock()
|
||||||
|
defer a.lock.Unlock()
|
||||||
|
|
||||||
|
a.instruments = append(a.instruments, inst)
|
||||||
|
|
||||||
|
// asyncRunnerPair reflects this callback in the asyncRunners
|
||||||
|
// list. If this is a batch runner, the instrument is nil.
|
||||||
|
// If this is a single-Observer runner, the instrument is
|
||||||
|
// included. This ensures that batch callbacks are called
|
||||||
|
// once and single callbacks are called once per instrument.
|
||||||
|
rp := asyncRunnerPair{
|
||||||
|
runner: runner,
|
||||||
|
}
|
||||||
|
if _, ok := runner.(sdkapi.AsyncSingleRunner); ok {
|
||||||
|
rp.inst = inst
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := a.runnerMap[rp]; !ok {
|
||||||
|
a.runnerMap[rp] = struct{}{}
|
||||||
|
a.runners = append(a.runners, rp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run executes the complete set of observer callbacks.
|
||||||
|
func (a *AsyncInstrumentState) Run(ctx context.Context, collector AsyncCollector) {
|
||||||
|
a.lock.Lock()
|
||||||
|
runners := a.runners
|
||||||
|
a.lock.Unlock()
|
||||||
|
|
||||||
|
for _, rp := range runners {
|
||||||
|
// The runner must be a single or batch runner, no
|
||||||
|
// other implementations are possible because the
|
||||||
|
// interface has un-exported methods.
|
||||||
|
|
||||||
|
if singleRunner, ok := rp.runner.(sdkapi.AsyncSingleRunner); ok {
|
||||||
|
singleRunner.Run(ctx, rp.inst, collector.CollectAsync)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if multiRunner, ok := rp.runner.(sdkapi.AsyncBatchRunner); ok {
|
||||||
|
multiRunner.Run(ctx, collector.CollectAsync)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
a.errorOnce.Do(func() {
|
||||||
|
otel.Handle(fmt.Errorf("%w: type %T (reported once)", ErrInvalidAsyncRunner, rp))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
361
vendor/go.opentelemetry.io/otel/internal/metric/global/meter.go
generated
vendored
Normal file
361
vendor/go.opentelemetry.io/otel/internal/metric/global/meter.go
generated
vendored
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
// Copyright The 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 global // import "go.opentelemetry.io/otel/internal/metric/global"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/internal/metric/registry"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file contains the forwarding implementation of MeterProvider used as
|
||||||
|
// the default global instance. Metric events using instruments provided by
|
||||||
|
// this implementation are no-ops until the first Meter implementation is set
|
||||||
|
// as the global provider.
|
||||||
|
//
|
||||||
|
// The implementation here uses Mutexes to maintain a list of active Meters in
|
||||||
|
// the MeterProvider and Instruments in each Meter, under the assumption that
|
||||||
|
// these interfaces are not performance-critical.
|
||||||
|
//
|
||||||
|
// We have the invariant that setDelegate() will be called before a new
|
||||||
|
// MeterProvider implementation is registered as the global provider. Mutexes
|
||||||
|
// in the MeterProvider and Meters ensure that each instrument has a delegate
|
||||||
|
// before the global provider is set.
|
||||||
|
//
|
||||||
|
// Bound instrument operations are implemented by delegating to the
|
||||||
|
// instrument after it is registered, with a sync.Once initializer to
|
||||||
|
// protect against races with Release().
|
||||||
|
//
|
||||||
|
// Metric uniqueness checking is implemented by calling the exported
|
||||||
|
// methods of the api/metric/registry package.
|
||||||
|
|
||||||
|
type meterKey struct {
|
||||||
|
InstrumentationName string
|
||||||
|
InstrumentationVersion string
|
||||||
|
SchemaURL string
|
||||||
|
}
|
||||||
|
|
||||||
|
type meterProvider struct {
|
||||||
|
delegate metric.MeterProvider
|
||||||
|
|
||||||
|
// lock protects `delegate` and `meters`.
|
||||||
|
lock sync.Mutex
|
||||||
|
|
||||||
|
// meters maintains a unique entry for every named Meter
|
||||||
|
// that has been registered through the global instance.
|
||||||
|
meters map[meterKey]*meterEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
type meterImpl struct {
|
||||||
|
delegate unsafe.Pointer // (*metric.MeterImpl)
|
||||||
|
|
||||||
|
lock sync.Mutex
|
||||||
|
syncInsts []*syncImpl
|
||||||
|
asyncInsts []*asyncImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
type meterEntry struct {
|
||||||
|
unique sdkapi.MeterImpl
|
||||||
|
impl meterImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
type instrument struct {
|
||||||
|
descriptor sdkapi.Descriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
type syncImpl struct {
|
||||||
|
delegate unsafe.Pointer // (*sdkapi.SyncImpl)
|
||||||
|
|
||||||
|
instrument
|
||||||
|
}
|
||||||
|
|
||||||
|
type asyncImpl struct {
|
||||||
|
delegate unsafe.Pointer // (*sdkapi.AsyncImpl)
|
||||||
|
|
||||||
|
instrument
|
||||||
|
|
||||||
|
runner sdkapi.AsyncRunner
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncImpler is implemented by all of the sync metric
|
||||||
|
// instruments.
|
||||||
|
type SyncImpler interface {
|
||||||
|
SyncImpl() sdkapi.SyncImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncImpler is implemented by all of the async
|
||||||
|
// metric instruments.
|
||||||
|
type AsyncImpler interface {
|
||||||
|
AsyncImpl() sdkapi.AsyncImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
type syncHandle struct {
|
||||||
|
delegate unsafe.Pointer // (*sdkapi.BoundInstrumentImpl)
|
||||||
|
|
||||||
|
inst *syncImpl
|
||||||
|
labels []attribute.KeyValue
|
||||||
|
|
||||||
|
initialize sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ metric.MeterProvider = &meterProvider{}
|
||||||
|
var _ sdkapi.MeterImpl = &meterImpl{}
|
||||||
|
var _ sdkapi.InstrumentImpl = &syncImpl{}
|
||||||
|
var _ sdkapi.BoundSyncImpl = &syncHandle{}
|
||||||
|
var _ sdkapi.AsyncImpl = &asyncImpl{}
|
||||||
|
|
||||||
|
func (inst *instrument) Descriptor() sdkapi.Descriptor {
|
||||||
|
return inst.descriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
// MeterProvider interface and delegation
|
||||||
|
|
||||||
|
func newMeterProvider() *meterProvider {
|
||||||
|
return &meterProvider{
|
||||||
|
meters: map[meterKey]*meterEntry{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *meterProvider) setDelegate(provider metric.MeterProvider) {
|
||||||
|
p.lock.Lock()
|
||||||
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
|
p.delegate = provider
|
||||||
|
for key, entry := range p.meters {
|
||||||
|
entry.impl.setDelegate(key, provider)
|
||||||
|
}
|
||||||
|
p.meters = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *meterProvider) Meter(instrumentationName string, opts ...metric.MeterOption) metric.Meter {
|
||||||
|
p.lock.Lock()
|
||||||
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
|
if p.delegate != nil {
|
||||||
|
return p.delegate.Meter(instrumentationName, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := metric.NewMeterConfig(opts...)
|
||||||
|
key := meterKey{
|
||||||
|
InstrumentationName: instrumentationName,
|
||||||
|
InstrumentationVersion: cfg.InstrumentationVersion(),
|
||||||
|
SchemaURL: cfg.SchemaURL(),
|
||||||
|
}
|
||||||
|
entry, ok := p.meters[key]
|
||||||
|
if !ok {
|
||||||
|
entry = &meterEntry{}
|
||||||
|
// Note: This code implements its own MeterProvider
|
||||||
|
// name-uniqueness logic because there is
|
||||||
|
// synchronization required at the moment of
|
||||||
|
// delegation. We use the same instrument-uniqueness
|
||||||
|
// checking the real SDK uses here:
|
||||||
|
entry.unique = registry.NewUniqueInstrumentMeterImpl(&entry.impl)
|
||||||
|
p.meters[key] = entry
|
||||||
|
}
|
||||||
|
return metric.WrapMeterImpl(entry.unique)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Meter interface and delegation
|
||||||
|
|
||||||
|
func (m *meterImpl) setDelegate(key meterKey, provider metric.MeterProvider) {
|
||||||
|
m.lock.Lock()
|
||||||
|
defer m.lock.Unlock()
|
||||||
|
|
||||||
|
d := new(sdkapi.MeterImpl)
|
||||||
|
*d = provider.Meter(
|
||||||
|
key.InstrumentationName,
|
||||||
|
metric.WithInstrumentationVersion(key.InstrumentationVersion),
|
||||||
|
metric.WithSchemaURL(key.SchemaURL),
|
||||||
|
).MeterImpl()
|
||||||
|
m.delegate = unsafe.Pointer(d)
|
||||||
|
|
||||||
|
for _, inst := range m.syncInsts {
|
||||||
|
inst.setDelegate(*d)
|
||||||
|
}
|
||||||
|
m.syncInsts = nil
|
||||||
|
for _, obs := range m.asyncInsts {
|
||||||
|
obs.setDelegate(*d)
|
||||||
|
}
|
||||||
|
m.asyncInsts = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *meterImpl) NewSyncInstrument(desc sdkapi.Descriptor) (sdkapi.SyncImpl, error) {
|
||||||
|
m.lock.Lock()
|
||||||
|
defer m.lock.Unlock()
|
||||||
|
|
||||||
|
if meterPtr := (*sdkapi.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||||
|
return (*meterPtr).NewSyncInstrument(desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
inst := &syncImpl{
|
||||||
|
instrument: instrument{
|
||||||
|
descriptor: desc,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
m.syncInsts = append(m.syncInsts, inst)
|
||||||
|
return inst, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Synchronous delegation
|
||||||
|
|
||||||
|
func (inst *syncImpl) setDelegate(d sdkapi.MeterImpl) {
|
||||||
|
implPtr := new(sdkapi.SyncImpl)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
*implPtr, err = d.NewSyncInstrument(inst.descriptor)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// TODO: There is no standard way to deliver this error to the user.
|
||||||
|
// See https://github.com/open-telemetry/opentelemetry-go/issues/514
|
||||||
|
// Note that the default SDK will not generate any errors yet, this is
|
||||||
|
// only for added safety.
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic.StorePointer(&inst.delegate, unsafe.Pointer(implPtr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (inst *syncImpl) Implementation() interface{} {
|
||||||
|
if implPtr := (*sdkapi.SyncImpl)(atomic.LoadPointer(&inst.delegate)); implPtr != nil {
|
||||||
|
return (*implPtr).Implementation()
|
||||||
|
}
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
|
||||||
|
func (inst *syncImpl) Bind(labels []attribute.KeyValue) sdkapi.BoundSyncImpl {
|
||||||
|
if implPtr := (*sdkapi.SyncImpl)(atomic.LoadPointer(&inst.delegate)); implPtr != nil {
|
||||||
|
return (*implPtr).Bind(labels)
|
||||||
|
}
|
||||||
|
return &syncHandle{
|
||||||
|
inst: inst,
|
||||||
|
labels: labels,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bound *syncHandle) Unbind() {
|
||||||
|
bound.initialize.Do(func() {})
|
||||||
|
|
||||||
|
implPtr := (*sdkapi.BoundSyncImpl)(atomic.LoadPointer(&bound.delegate))
|
||||||
|
|
||||||
|
if implPtr == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
(*implPtr).Unbind()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Async delegation
|
||||||
|
|
||||||
|
func (m *meterImpl) NewAsyncInstrument(
|
||||||
|
desc sdkapi.Descriptor,
|
||||||
|
runner sdkapi.AsyncRunner,
|
||||||
|
) (sdkapi.AsyncImpl, error) {
|
||||||
|
|
||||||
|
m.lock.Lock()
|
||||||
|
defer m.lock.Unlock()
|
||||||
|
|
||||||
|
if meterPtr := (*sdkapi.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||||
|
return (*meterPtr).NewAsyncInstrument(desc, runner)
|
||||||
|
}
|
||||||
|
|
||||||
|
inst := &asyncImpl{
|
||||||
|
instrument: instrument{
|
||||||
|
descriptor: desc,
|
||||||
|
},
|
||||||
|
runner: runner,
|
||||||
|
}
|
||||||
|
m.asyncInsts = append(m.asyncInsts, inst)
|
||||||
|
return inst, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (obs *asyncImpl) Implementation() interface{} {
|
||||||
|
if implPtr := (*sdkapi.AsyncImpl)(atomic.LoadPointer(&obs.delegate)); implPtr != nil {
|
||||||
|
return (*implPtr).Implementation()
|
||||||
|
}
|
||||||
|
return obs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (obs *asyncImpl) setDelegate(d sdkapi.MeterImpl) {
|
||||||
|
implPtr := new(sdkapi.AsyncImpl)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
*implPtr, err = d.NewAsyncInstrument(obs.descriptor, obs.runner)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// TODO: There is no standard way to deliver this error to the user.
|
||||||
|
// See https://github.com/open-telemetry/opentelemetry-go/issues/514
|
||||||
|
// Note that the default SDK will not generate any errors yet, this is
|
||||||
|
// only for added safety.
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic.StorePointer(&obs.delegate, unsafe.Pointer(implPtr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metric updates
|
||||||
|
|
||||||
|
func (m *meterImpl) RecordBatch(ctx context.Context, labels []attribute.KeyValue, measurements ...sdkapi.Measurement) {
|
||||||
|
if delegatePtr := (*sdkapi.MeterImpl)(atomic.LoadPointer(&m.delegate)); delegatePtr != nil {
|
||||||
|
(*delegatePtr).RecordBatch(ctx, labels, measurements...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (inst *syncImpl) RecordOne(ctx context.Context, number number.Number, labels []attribute.KeyValue) {
|
||||||
|
if instPtr := (*sdkapi.SyncImpl)(atomic.LoadPointer(&inst.delegate)); instPtr != nil {
|
||||||
|
(*instPtr).RecordOne(ctx, number, labels)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bound instrument initialization
|
||||||
|
|
||||||
|
func (bound *syncHandle) RecordOne(ctx context.Context, number number.Number) {
|
||||||
|
instPtr := (*sdkapi.SyncImpl)(atomic.LoadPointer(&bound.inst.delegate))
|
||||||
|
if instPtr == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var implPtr *sdkapi.BoundSyncImpl
|
||||||
|
bound.initialize.Do(func() {
|
||||||
|
implPtr = new(sdkapi.BoundSyncImpl)
|
||||||
|
*implPtr = (*instPtr).Bind(bound.labels)
|
||||||
|
atomic.StorePointer(&bound.delegate, unsafe.Pointer(implPtr))
|
||||||
|
})
|
||||||
|
if implPtr == nil {
|
||||||
|
implPtr = (*sdkapi.BoundSyncImpl)(atomic.LoadPointer(&bound.delegate))
|
||||||
|
}
|
||||||
|
// This may still be nil if instrument was created and bound
|
||||||
|
// without a delegate, then the instrument was set to have a
|
||||||
|
// delegate and unbound.
|
||||||
|
if implPtr == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
(*implPtr).RecordOne(ctx, number)
|
||||||
|
}
|
||||||
|
|
||||||
|
func AtomicFieldOffsets() map[string]uintptr {
|
||||||
|
return map[string]uintptr{
|
||||||
|
"meterProvider.delegate": unsafe.Offsetof(meterProvider{}.delegate),
|
||||||
|
"meterImpl.delegate": unsafe.Offsetof(meterImpl{}.delegate),
|
||||||
|
"syncImpl.delegate": unsafe.Offsetof(syncImpl{}.delegate),
|
||||||
|
"asyncImpl.delegate": unsafe.Offsetof(asyncImpl{}.delegate),
|
||||||
|
"syncHandle.delegate": unsafe.Offsetof(syncHandle{}.delegate),
|
||||||
|
}
|
||||||
|
}
|
||||||
66
vendor/go.opentelemetry.io/otel/internal/metric/global/metric.go
generated
vendored
Normal file
66
vendor/go.opentelemetry.io/otel/internal/metric/global/metric.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// Copyright The 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 global // import "go.opentelemetry.io/otel/internal/metric/global"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
)
|
||||||
|
|
||||||
|
type meterProviderHolder struct {
|
||||||
|
mp metric.MeterProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
globalMeter = defaultMeterValue()
|
||||||
|
|
||||||
|
delegateMeterOnce sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// MeterProvider is the internal implementation for global.MeterProvider.
|
||||||
|
func MeterProvider() metric.MeterProvider {
|
||||||
|
return globalMeter.Load().(meterProviderHolder).mp
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMeterProvider is the internal implementation for global.SetMeterProvider.
|
||||||
|
func SetMeterProvider(mp metric.MeterProvider) {
|
||||||
|
delegateMeterOnce.Do(func() {
|
||||||
|
current := MeterProvider()
|
||||||
|
|
||||||
|
if current == mp {
|
||||||
|
// Setting the provider to the prior default is nonsense, panic.
|
||||||
|
// Panic is acceptable because we are likely still early in the
|
||||||
|
// process lifetime.
|
||||||
|
panic("invalid MeterProvider, the global instance cannot be reinstalled")
|
||||||
|
} else if def, ok := current.(*meterProvider); ok {
|
||||||
|
def.setDelegate(mp)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
globalMeter.Store(meterProviderHolder{mp: mp})
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultMeterValue() *atomic.Value {
|
||||||
|
v := &atomic.Value{}
|
||||||
|
v.Store(meterProviderHolder{mp: newMeterProvider()})
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetForTest restores the initial global state, for testing purposes.
|
||||||
|
func ResetForTest() {
|
||||||
|
globalMeter = defaultMeterValue()
|
||||||
|
delegateMeterOnce = sync.Once{}
|
||||||
|
}
|
||||||
24
vendor/go.opentelemetry.io/otel/internal/metric/registry/doc.go
generated
vendored
Normal file
24
vendor/go.opentelemetry.io/otel/internal/metric/registry/doc.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright The 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 registry provides a non-standalone implementation of
|
||||||
|
MeterProvider that adds uniqueness checking for instrument descriptors
|
||||||
|
on top of other MeterProvider it wraps.
|
||||||
|
|
||||||
|
This package is currently in a pre-GA phase. Backwards incompatible changes
|
||||||
|
may be introduced in subsequent minor version releases as we work to track the
|
||||||
|
evolving OpenTelemetry specification and user feedback.
|
||||||
|
*/
|
||||||
|
package registry // import "go.opentelemetry.io/otel/internal/metric/registry"
|
||||||
139
vendor/go.opentelemetry.io/otel/internal/metric/registry/registry.go
generated
vendored
Normal file
139
vendor/go.opentelemetry.io/otel/internal/metric/registry/registry.go
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
// Copyright The 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 registry // import "go.opentelemetry.io/otel/internal/metric/registry"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UniqueInstrumentMeterImpl implements the metric.MeterImpl interface, adding
|
||||||
|
// uniqueness checking for instrument descriptors.
|
||||||
|
type UniqueInstrumentMeterImpl struct {
|
||||||
|
lock sync.Mutex
|
||||||
|
impl sdkapi.MeterImpl
|
||||||
|
state map[string]sdkapi.InstrumentImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ sdkapi.MeterImpl = (*UniqueInstrumentMeterImpl)(nil)
|
||||||
|
|
||||||
|
// ErrMetricKindMismatch is the standard error for mismatched metric
|
||||||
|
// instrument definitions.
|
||||||
|
var ErrMetricKindMismatch = fmt.Errorf(
|
||||||
|
"a metric was already registered by this name with another kind or number type")
|
||||||
|
|
||||||
|
// NewUniqueInstrumentMeterImpl returns a wrapped metric.MeterImpl
|
||||||
|
// with the addition of instrument name uniqueness checking.
|
||||||
|
func NewUniqueInstrumentMeterImpl(impl sdkapi.MeterImpl) *UniqueInstrumentMeterImpl {
|
||||||
|
return &UniqueInstrumentMeterImpl{
|
||||||
|
impl: impl,
|
||||||
|
state: map[string]sdkapi.InstrumentImpl{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MeterImpl gives the caller access to the underlying MeterImpl
|
||||||
|
// used by this UniqueInstrumentMeterImpl.
|
||||||
|
func (u *UniqueInstrumentMeterImpl) MeterImpl() sdkapi.MeterImpl {
|
||||||
|
return u.impl
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordBatch implements sdkapi.MeterImpl.
|
||||||
|
func (u *UniqueInstrumentMeterImpl) RecordBatch(ctx context.Context, labels []attribute.KeyValue, ms ...sdkapi.Measurement) {
|
||||||
|
u.impl.RecordBatch(ctx, labels, ms...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMetricKindMismatchError formats an error that describes a
|
||||||
|
// mismatched metric instrument definition.
|
||||||
|
func NewMetricKindMismatchError(desc sdkapi.Descriptor) error {
|
||||||
|
return fmt.Errorf("metric %s registered as %s %s: %w",
|
||||||
|
desc.Name(),
|
||||||
|
desc.NumberKind(),
|
||||||
|
desc.InstrumentKind(),
|
||||||
|
ErrMetricKindMismatch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compatible determines whether two sdkapi.Descriptors are considered
|
||||||
|
// the same for the purpose of uniqueness checking.
|
||||||
|
func Compatible(candidate, existing sdkapi.Descriptor) bool {
|
||||||
|
return candidate.InstrumentKind() == existing.InstrumentKind() &&
|
||||||
|
candidate.NumberKind() == existing.NumberKind()
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkUniqueness returns an ErrMetricKindMismatch error if there is
|
||||||
|
// a conflict between a descriptor that was already registered and the
|
||||||
|
// `descriptor` argument. If there is an existing compatible
|
||||||
|
// registration, this returns the already-registered instrument. If
|
||||||
|
// there is no conflict and no prior registration, returns (nil, nil).
|
||||||
|
func (u *UniqueInstrumentMeterImpl) checkUniqueness(descriptor sdkapi.Descriptor) (sdkapi.InstrumentImpl, error) {
|
||||||
|
impl, ok := u.state[descriptor.Name()]
|
||||||
|
if !ok {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !Compatible(descriptor, impl.Descriptor()) {
|
||||||
|
return nil, NewMetricKindMismatchError(impl.Descriptor())
|
||||||
|
}
|
||||||
|
|
||||||
|
return impl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSyncInstrument implements sdkapi.MeterImpl.
|
||||||
|
func (u *UniqueInstrumentMeterImpl) NewSyncInstrument(descriptor sdkapi.Descriptor) (sdkapi.SyncImpl, error) {
|
||||||
|
u.lock.Lock()
|
||||||
|
defer u.lock.Unlock()
|
||||||
|
|
||||||
|
impl, err := u.checkUniqueness(descriptor)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if impl != nil {
|
||||||
|
return impl.(sdkapi.SyncImpl), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
syncInst, err := u.impl.NewSyncInstrument(descriptor)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
u.state[descriptor.Name()] = syncInst
|
||||||
|
return syncInst, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAsyncInstrument implements sdkapi.MeterImpl.
|
||||||
|
func (u *UniqueInstrumentMeterImpl) NewAsyncInstrument(
|
||||||
|
descriptor sdkapi.Descriptor,
|
||||||
|
runner sdkapi.AsyncRunner,
|
||||||
|
) (sdkapi.AsyncImpl, error) {
|
||||||
|
u.lock.Lock()
|
||||||
|
defer u.lock.Unlock()
|
||||||
|
|
||||||
|
impl, err := u.checkUniqueness(descriptor)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if impl != nil {
|
||||||
|
return impl.(sdkapi.AsyncImpl), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncInst, err := u.impl.NewAsyncInstrument(descriptor, runner)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
u.state[descriptor.Name()] = asyncInst
|
||||||
|
return asyncInst, nil
|
||||||
|
}
|
||||||
55
vendor/go.opentelemetry.io/otel/internal/rawhelpers.go
generated
vendored
Normal file
55
vendor/go.opentelemetry.io/otel/internal/rawhelpers.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// Copyright The 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 internal // import "go.opentelemetry.io/otel/internal"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BoolToRaw(b bool) uint64 {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func RawToBool(r uint64) bool {
|
||||||
|
return r != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int64ToRaw(i int64) uint64 {
|
||||||
|
return uint64(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RawToInt64(r uint64) int64 {
|
||||||
|
return int64(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Float64ToRaw(f float64) uint64 {
|
||||||
|
return math.Float64bits(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RawToFloat64(r uint64) float64 {
|
||||||
|
return math.Float64frombits(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RawPtrToFloat64Ptr(r *uint64) *float64 {
|
||||||
|
return (*float64)(unsafe.Pointer(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
func RawPtrToInt64Ptr(r *uint64) *int64 {
|
||||||
|
return (*int64)(unsafe.Pointer(r))
|
||||||
|
}
|
||||||
201
vendor/go.opentelemetry.io/otel/metric/LICENSE
generated
vendored
Normal file
201
vendor/go.opentelemetry.io/otel/metric/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
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.
|
||||||
124
vendor/go.opentelemetry.io/otel/metric/config.go
generated
vendored
Normal file
124
vendor/go.opentelemetry.io/otel/metric/config.go
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
// Copyright The 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 "go.opentelemetry.io/otel/metric"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.opentelemetry.io/otel/metric/unit"
|
||||||
|
)
|
||||||
|
|
||||||
|
// InstrumentConfig contains options for metric instrument descriptors.
|
||||||
|
type InstrumentConfig struct {
|
||||||
|
description string
|
||||||
|
unit unit.Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
// Description describes the instrument in human-readable terms.
|
||||||
|
func (cfg InstrumentConfig) Description() string {
|
||||||
|
return cfg.description
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unit describes the measurement unit for a instrument.
|
||||||
|
func (cfg InstrumentConfig) Unit() unit.Unit {
|
||||||
|
return cfg.unit
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstrumentOption is an interface for applying metric instrument options.
|
||||||
|
type InstrumentOption interface {
|
||||||
|
// ApplyMeter is used to set a InstrumentOption value of a
|
||||||
|
// InstrumentConfig.
|
||||||
|
applyInstrument(*InstrumentConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInstrumentConfig creates a new InstrumentConfig
|
||||||
|
// and applies all the given options.
|
||||||
|
func NewInstrumentConfig(opts ...InstrumentOption) InstrumentConfig {
|
||||||
|
var config InstrumentConfig
|
||||||
|
for _, o := range opts {
|
||||||
|
o.applyInstrument(&config)
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
type instrumentOptionFunc func(*InstrumentConfig)
|
||||||
|
|
||||||
|
func (fn instrumentOptionFunc) applyInstrument(cfg *InstrumentConfig) {
|
||||||
|
fn(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDescription applies provided description.
|
||||||
|
func WithDescription(desc string) InstrumentOption {
|
||||||
|
return instrumentOptionFunc(func(cfg *InstrumentConfig) {
|
||||||
|
cfg.description = desc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithUnit applies provided unit.
|
||||||
|
func WithUnit(unit unit.Unit) InstrumentOption {
|
||||||
|
return instrumentOptionFunc(func(cfg *InstrumentConfig) {
|
||||||
|
cfg.unit = unit
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MeterConfig contains options for Meters.
|
||||||
|
type MeterConfig struct {
|
||||||
|
instrumentationVersion string
|
||||||
|
schemaURL string
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstrumentationVersion is the version of the library providing instrumentation.
|
||||||
|
func (cfg MeterConfig) InstrumentationVersion() string {
|
||||||
|
return cfg.instrumentationVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchemaURL is the schema_url of the library providing instrumentation.
|
||||||
|
func (cfg MeterConfig) SchemaURL() string {
|
||||||
|
return cfg.schemaURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// MeterOption is an interface for applying Meter options.
|
||||||
|
type MeterOption interface {
|
||||||
|
// ApplyMeter is used to set a MeterOption value of a MeterConfig.
|
||||||
|
applyMeter(*MeterConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMeterConfig creates a new MeterConfig and applies
|
||||||
|
// all the given options.
|
||||||
|
func NewMeterConfig(opts ...MeterOption) MeterConfig {
|
||||||
|
var config MeterConfig
|
||||||
|
for _, o := range opts {
|
||||||
|
o.applyMeter(&config)
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
type meterOptionFunc func(*MeterConfig)
|
||||||
|
|
||||||
|
func (fn meterOptionFunc) applyMeter(cfg *MeterConfig) {
|
||||||
|
fn(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithInstrumentationVersion sets the instrumentation version.
|
||||||
|
func WithInstrumentationVersion(version string) MeterOption {
|
||||||
|
return meterOptionFunc(func(config *MeterConfig) {
|
||||||
|
config.instrumentationVersion = version
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSchemaURL sets the schema URL.
|
||||||
|
func WithSchemaURL(schemaURL string) MeterOption {
|
||||||
|
return meterOptionFunc(func(config *MeterConfig) {
|
||||||
|
config.schemaURL = schemaURL
|
||||||
|
})
|
||||||
|
}
|
||||||
67
vendor/go.opentelemetry.io/otel/metric/doc.go
generated
vendored
Normal file
67
vendor/go.opentelemetry.io/otel/metric/doc.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// Copyright The 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 provides an implementation of the metrics part of the
|
||||||
|
OpenTelemetry API.
|
||||||
|
|
||||||
|
This package is currently in a pre-GA phase. Backwards incompatible changes
|
||||||
|
may be introduced in subsequent minor version releases as we work to track the
|
||||||
|
evolving OpenTelemetry specification and user feedback.
|
||||||
|
|
||||||
|
Measurements can be made about an operation being performed or the state of a
|
||||||
|
system in general. These measurements can be crucial to the reliable operation
|
||||||
|
of code and provide valuable insights about the inner workings of a system.
|
||||||
|
|
||||||
|
Measurements are made using instruments provided by this package. The type of
|
||||||
|
instrument used will depend on the type of measurement being made and of what
|
||||||
|
part of a system is being measured.
|
||||||
|
|
||||||
|
Instruments are categorized as Synchronous or Asynchronous and independently
|
||||||
|
as Adding or Grouping. Synchronous instruments are called by the user with a
|
||||||
|
Context. Asynchronous instruments are called by the SDK during collection.
|
||||||
|
Adding instruments are semantically intended for capturing a sum. Grouping
|
||||||
|
instruments are intended for capturing a distribution.
|
||||||
|
|
||||||
|
Adding instruments may be monotonic, in which case they are non-decreasing
|
||||||
|
and naturally define a rate.
|
||||||
|
|
||||||
|
The synchronous instrument names are:
|
||||||
|
|
||||||
|
Counter: adding, monotonic
|
||||||
|
UpDownCounter: adding
|
||||||
|
Histogram: grouping
|
||||||
|
|
||||||
|
and the asynchronous instruments are:
|
||||||
|
|
||||||
|
CounterObserver: adding, monotonic
|
||||||
|
UpDownCounterObserver: adding
|
||||||
|
GaugeObserver: grouping
|
||||||
|
|
||||||
|
All instruments are provided with support for either float64 or int64 input
|
||||||
|
values.
|
||||||
|
|
||||||
|
An instrument is created using a Meter. Additionally, a Meter is used to
|
||||||
|
record batches of synchronous measurements or asynchronous observations. A
|
||||||
|
Meter is obtained using a MeterProvider. A Meter, like a Tracer, is unique to
|
||||||
|
the instrumentation it instruments and must be named and versioned when
|
||||||
|
created with a MeterProvider with the name and version of the instrumentation
|
||||||
|
library.
|
||||||
|
|
||||||
|
Instrumentation should be designed to accept a MeterProvider from which it can
|
||||||
|
create its own unique Meter. Alternatively, the registered global
|
||||||
|
MeterProvider from the go.opentelemetry.io/otel package can be used as a
|
||||||
|
default.
|
||||||
|
*/
|
||||||
|
package metric // import "go.opentelemetry.io/otel/metric"
|
||||||
49
vendor/go.opentelemetry.io/otel/metric/global/metric.go
generated
vendored
Normal file
49
vendor/go.opentelemetry.io/otel/metric/global/metric.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright The 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 global // import "go.opentelemetry.io/otel/metric/global"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.opentelemetry.io/otel/internal/metric/global"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Meter creates an implementation of the Meter interface from the global
|
||||||
|
// MeterProvider. The instrumentationName must be the name of the library
|
||||||
|
// providing instrumentation. This name may be the same as the instrumented
|
||||||
|
// code only if that code provides built-in instrumentation. If the
|
||||||
|
// instrumentationName is empty, then a implementation defined default name
|
||||||
|
// will be used instead.
|
||||||
|
//
|
||||||
|
// This is short for MeterProvider().Meter(name)
|
||||||
|
func Meter(instrumentationName string, opts ...metric.MeterOption) metric.Meter {
|
||||||
|
return GetMeterProvider().Meter(instrumentationName, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMeterProvider returns the registered global meter provider. If
|
||||||
|
// none is registered then a default meter provider is returned that
|
||||||
|
// forwards the Meter interface to the first registered Meter.
|
||||||
|
//
|
||||||
|
// Use the meter provider to create a named meter. E.g.
|
||||||
|
// meter := global.MeterProvider().Meter("example.com/foo")
|
||||||
|
// or
|
||||||
|
// meter := global.Meter("example.com/foo")
|
||||||
|
func GetMeterProvider() metric.MeterProvider {
|
||||||
|
return global.MeterProvider()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMeterProvider registers `mp` as the global meter provider.
|
||||||
|
func SetMeterProvider(mp metric.MeterProvider) {
|
||||||
|
global.SetMeterProvider(mp)
|
||||||
|
}
|
||||||
538
vendor/go.opentelemetry.io/otel/metric/metric.go
generated
vendored
Normal file
538
vendor/go.opentelemetry.io/otel/metric/metric.go
generated
vendored
Normal file
@@ -0,0 +1,538 @@
|
|||||||
|
// Copyright The 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 "go.opentelemetry.io/otel/metric"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MeterProvider supports named Meter instances.
|
||||||
|
type MeterProvider interface {
|
||||||
|
// Meter creates an implementation of the Meter interface.
|
||||||
|
// The instrumentationName must be the name of the library providing
|
||||||
|
// instrumentation. This name may be the same as the instrumented code
|
||||||
|
// only if that code provides built-in instrumentation. If the
|
||||||
|
// instrumentationName is empty, then a implementation defined default
|
||||||
|
// name will be used instead.
|
||||||
|
Meter(instrumentationName string, opts ...MeterOption) Meter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Meter is the creator of metric instruments.
|
||||||
|
//
|
||||||
|
// An uninitialized Meter is a no-op implementation.
|
||||||
|
type Meter struct {
|
||||||
|
impl sdkapi.MeterImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapMeterImpl constructs a `Meter` implementation from a
|
||||||
|
// `MeterImpl` implementation.
|
||||||
|
func WrapMeterImpl(impl sdkapi.MeterImpl) Meter {
|
||||||
|
return Meter{
|
||||||
|
impl: impl,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measurement is used for reporting a synchronous batch of metric
|
||||||
|
// values. Instances of this type should be created by synchronous
|
||||||
|
// instruments (e.g., Int64Counter.Measurement()).
|
||||||
|
//
|
||||||
|
// Note: This is an alias because it is a first-class member of the
|
||||||
|
// API but is also part of the lower-level sdkapi interface.
|
||||||
|
type Measurement = sdkapi.Measurement
|
||||||
|
|
||||||
|
// Observation is used for reporting an asynchronous batch of metric
|
||||||
|
// values. Instances of this type should be created by asynchronous
|
||||||
|
// instruments (e.g., Int64GaugeObserver.Observation()).
|
||||||
|
//
|
||||||
|
// Note: This is an alias because it is a first-class member of the
|
||||||
|
// API but is also part of the lower-level sdkapi interface.
|
||||||
|
type Observation = sdkapi.Observation
|
||||||
|
|
||||||
|
// RecordBatch atomically records a batch of measurements.
|
||||||
|
func (m Meter) RecordBatch(ctx context.Context, ls []attribute.KeyValue, ms ...Measurement) {
|
||||||
|
if m.impl == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.impl.RecordBatch(ctx, ls, ms...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBatchObserver creates a new BatchObserver that supports
|
||||||
|
// making batches of observations for multiple instruments.
|
||||||
|
func (m Meter) NewBatchObserver(callback BatchObserverFunc) BatchObserver {
|
||||||
|
return BatchObserver{
|
||||||
|
meter: m,
|
||||||
|
runner: newBatchAsyncRunner(callback),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64Counter creates a new integer Counter instrument with the
|
||||||
|
// given name, customized with options. May return an error if the
|
||||||
|
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||||
|
// duplicate registration).
|
||||||
|
func (m Meter) NewInt64Counter(name string, options ...InstrumentOption) (Int64Counter, error) {
|
||||||
|
return wrapInt64CounterInstrument(
|
||||||
|
m.newSync(name, sdkapi.CounterInstrumentKind, number.Int64Kind, options))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64Counter creates a new floating point Counter with the
|
||||||
|
// given name, customized with options. May return an error if the
|
||||||
|
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||||
|
// duplicate registration).
|
||||||
|
func (m Meter) NewFloat64Counter(name string, options ...InstrumentOption) (Float64Counter, error) {
|
||||||
|
return wrapFloat64CounterInstrument(
|
||||||
|
m.newSync(name, sdkapi.CounterInstrumentKind, number.Float64Kind, options))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64UpDownCounter creates a new integer UpDownCounter instrument with the
|
||||||
|
// given name, customized with options. May return an error if the
|
||||||
|
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||||
|
// duplicate registration).
|
||||||
|
func (m Meter) NewInt64UpDownCounter(name string, options ...InstrumentOption) (Int64UpDownCounter, error) {
|
||||||
|
return wrapInt64UpDownCounterInstrument(
|
||||||
|
m.newSync(name, sdkapi.UpDownCounterInstrumentKind, number.Int64Kind, options))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64UpDownCounter creates a new floating point UpDownCounter with the
|
||||||
|
// given name, customized with options. May return an error if the
|
||||||
|
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||||
|
// duplicate registration).
|
||||||
|
func (m Meter) NewFloat64UpDownCounter(name string, options ...InstrumentOption) (Float64UpDownCounter, error) {
|
||||||
|
return wrapFloat64UpDownCounterInstrument(
|
||||||
|
m.newSync(name, sdkapi.UpDownCounterInstrumentKind, number.Float64Kind, options))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64Histogram creates a new integer Histogram instrument with the
|
||||||
|
// given name, customized with options. May return an error if the
|
||||||
|
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||||
|
// duplicate registration).
|
||||||
|
func (m Meter) NewInt64Histogram(name string, opts ...InstrumentOption) (Int64Histogram, error) {
|
||||||
|
return wrapInt64HistogramInstrument(
|
||||||
|
m.newSync(name, sdkapi.HistogramInstrumentKind, number.Int64Kind, opts))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64Histogram creates a new floating point Histogram with the
|
||||||
|
// given name, customized with options. May return an error if the
|
||||||
|
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||||
|
// duplicate registration).
|
||||||
|
func (m Meter) NewFloat64Histogram(name string, opts ...InstrumentOption) (Float64Histogram, error) {
|
||||||
|
return wrapFloat64HistogramInstrument(
|
||||||
|
m.newSync(name, sdkapi.HistogramInstrumentKind, number.Float64Kind, opts))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64GaugeObserver creates a new integer GaugeObserver instrument
|
||||||
|
// with the given name, running a given callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (m Meter) NewInt64GaugeObserver(name string, callback Int64ObserverFunc, opts ...InstrumentOption) (Int64GaugeObserver, error) {
|
||||||
|
if callback == nil {
|
||||||
|
return wrapInt64GaugeObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapInt64GaugeObserverInstrument(
|
||||||
|
m.newAsync(name, sdkapi.GaugeObserverInstrumentKind, number.Int64Kind, opts,
|
||||||
|
newInt64AsyncRunner(callback)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64GaugeObserver creates a new floating point GaugeObserver with
|
||||||
|
// the given name, running a given callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (m Meter) NewFloat64GaugeObserver(name string, callback Float64ObserverFunc, opts ...InstrumentOption) (Float64GaugeObserver, error) {
|
||||||
|
if callback == nil {
|
||||||
|
return wrapFloat64GaugeObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapFloat64GaugeObserverInstrument(
|
||||||
|
m.newAsync(name, sdkapi.GaugeObserverInstrumentKind, number.Float64Kind, opts,
|
||||||
|
newFloat64AsyncRunner(callback)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64CounterObserver creates a new integer CounterObserver instrument
|
||||||
|
// with the given name, running a given callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (m Meter) NewInt64CounterObserver(name string, callback Int64ObserverFunc, opts ...InstrumentOption) (Int64CounterObserver, error) {
|
||||||
|
if callback == nil {
|
||||||
|
return wrapInt64CounterObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapInt64CounterObserverInstrument(
|
||||||
|
m.newAsync(name, sdkapi.CounterObserverInstrumentKind, number.Int64Kind, opts,
|
||||||
|
newInt64AsyncRunner(callback)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64CounterObserver creates a new floating point CounterObserver with
|
||||||
|
// the given name, running a given callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (m Meter) NewFloat64CounterObserver(name string, callback Float64ObserverFunc, opts ...InstrumentOption) (Float64CounterObserver, error) {
|
||||||
|
if callback == nil {
|
||||||
|
return wrapFloat64CounterObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapFloat64CounterObserverInstrument(
|
||||||
|
m.newAsync(name, sdkapi.CounterObserverInstrumentKind, number.Float64Kind, opts,
|
||||||
|
newFloat64AsyncRunner(callback)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64UpDownCounterObserver creates a new integer UpDownCounterObserver instrument
|
||||||
|
// with the given name, running a given callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (m Meter) NewInt64UpDownCounterObserver(name string, callback Int64ObserverFunc, opts ...InstrumentOption) (Int64UpDownCounterObserver, error) {
|
||||||
|
if callback == nil {
|
||||||
|
return wrapInt64UpDownCounterObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapInt64UpDownCounterObserverInstrument(
|
||||||
|
m.newAsync(name, sdkapi.UpDownCounterObserverInstrumentKind, number.Int64Kind, opts,
|
||||||
|
newInt64AsyncRunner(callback)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64UpDownCounterObserver creates a new floating point UpDownCounterObserver with
|
||||||
|
// the given name, running a given callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (m Meter) NewFloat64UpDownCounterObserver(name string, callback Float64ObserverFunc, opts ...InstrumentOption) (Float64UpDownCounterObserver, error) {
|
||||||
|
if callback == nil {
|
||||||
|
return wrapFloat64UpDownCounterObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapFloat64UpDownCounterObserverInstrument(
|
||||||
|
m.newAsync(name, sdkapi.UpDownCounterObserverInstrumentKind, number.Float64Kind, opts,
|
||||||
|
newFloat64AsyncRunner(callback)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64GaugeObserver creates a new integer GaugeObserver instrument
|
||||||
|
// with the given name, running in a batch callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (b BatchObserver) NewInt64GaugeObserver(name string, opts ...InstrumentOption) (Int64GaugeObserver, error) {
|
||||||
|
if b.runner == nil {
|
||||||
|
return wrapInt64GaugeObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapInt64GaugeObserverInstrument(
|
||||||
|
b.meter.newAsync(name, sdkapi.GaugeObserverInstrumentKind, number.Int64Kind, opts, b.runner))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64GaugeObserver creates a new floating point GaugeObserver with
|
||||||
|
// the given name, running in a batch callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (b BatchObserver) NewFloat64GaugeObserver(name string, opts ...InstrumentOption) (Float64GaugeObserver, error) {
|
||||||
|
if b.runner == nil {
|
||||||
|
return wrapFloat64GaugeObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapFloat64GaugeObserverInstrument(
|
||||||
|
b.meter.newAsync(name, sdkapi.GaugeObserverInstrumentKind, number.Float64Kind, opts,
|
||||||
|
b.runner))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64CounterObserver creates a new integer CounterObserver instrument
|
||||||
|
// with the given name, running in a batch callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (b BatchObserver) NewInt64CounterObserver(name string, opts ...InstrumentOption) (Int64CounterObserver, error) {
|
||||||
|
if b.runner == nil {
|
||||||
|
return wrapInt64CounterObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapInt64CounterObserverInstrument(
|
||||||
|
b.meter.newAsync(name, sdkapi.CounterObserverInstrumentKind, number.Int64Kind, opts, b.runner))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64CounterObserver creates a new floating point CounterObserver with
|
||||||
|
// the given name, running in a batch callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (b BatchObserver) NewFloat64CounterObserver(name string, opts ...InstrumentOption) (Float64CounterObserver, error) {
|
||||||
|
if b.runner == nil {
|
||||||
|
return wrapFloat64CounterObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapFloat64CounterObserverInstrument(
|
||||||
|
b.meter.newAsync(name, sdkapi.CounterObserverInstrumentKind, number.Float64Kind, opts,
|
||||||
|
b.runner))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64UpDownCounterObserver creates a new integer UpDownCounterObserver instrument
|
||||||
|
// with the given name, running in a batch callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (b BatchObserver) NewInt64UpDownCounterObserver(name string, opts ...InstrumentOption) (Int64UpDownCounterObserver, error) {
|
||||||
|
if b.runner == nil {
|
||||||
|
return wrapInt64UpDownCounterObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapInt64UpDownCounterObserverInstrument(
|
||||||
|
b.meter.newAsync(name, sdkapi.UpDownCounterObserverInstrumentKind, number.Int64Kind, opts, b.runner))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64UpDownCounterObserver creates a new floating point UpDownCounterObserver with
|
||||||
|
// the given name, running in a batch callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (b BatchObserver) NewFloat64UpDownCounterObserver(name string, opts ...InstrumentOption) (Float64UpDownCounterObserver, error) {
|
||||||
|
if b.runner == nil {
|
||||||
|
return wrapFloat64UpDownCounterObserverInstrument(sdkapi.NewNoopAsyncInstrument(), nil)
|
||||||
|
}
|
||||||
|
return wrapFloat64UpDownCounterObserverInstrument(
|
||||||
|
b.meter.newAsync(name, sdkapi.UpDownCounterObserverInstrumentKind, number.Float64Kind, opts,
|
||||||
|
b.runner))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MeterImpl returns the underlying MeterImpl of this Meter.
|
||||||
|
func (m Meter) MeterImpl() sdkapi.MeterImpl {
|
||||||
|
return m.impl
|
||||||
|
}
|
||||||
|
|
||||||
|
// newAsync constructs one new asynchronous instrument.
|
||||||
|
func (m Meter) newAsync(
|
||||||
|
name string,
|
||||||
|
mkind sdkapi.InstrumentKind,
|
||||||
|
nkind number.Kind,
|
||||||
|
opts []InstrumentOption,
|
||||||
|
runner sdkapi.AsyncRunner,
|
||||||
|
) (
|
||||||
|
sdkapi.AsyncImpl,
|
||||||
|
error,
|
||||||
|
) {
|
||||||
|
if m.impl == nil {
|
||||||
|
return sdkapi.NewNoopAsyncInstrument(), nil
|
||||||
|
}
|
||||||
|
cfg := NewInstrumentConfig(opts...)
|
||||||
|
desc := sdkapi.NewDescriptor(name, mkind, nkind, cfg.description, cfg.unit)
|
||||||
|
return m.impl.NewAsyncInstrument(desc, runner)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newSync constructs one new synchronous instrument.
|
||||||
|
func (m Meter) newSync(
|
||||||
|
name string,
|
||||||
|
metricKind sdkapi.InstrumentKind,
|
||||||
|
numberKind number.Kind,
|
||||||
|
opts []InstrumentOption,
|
||||||
|
) (
|
||||||
|
sdkapi.SyncImpl,
|
||||||
|
error,
|
||||||
|
) {
|
||||||
|
if m.impl == nil {
|
||||||
|
return sdkapi.NewNoopSyncInstrument(), nil
|
||||||
|
}
|
||||||
|
cfg := NewInstrumentConfig(opts...)
|
||||||
|
desc := sdkapi.NewDescriptor(name, metricKind, numberKind, cfg.description, cfg.unit)
|
||||||
|
return m.impl.NewSyncInstrument(desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MeterMust is a wrapper for Meter interfaces that panics when any
|
||||||
|
// instrument constructor encounters an error.
|
||||||
|
type MeterMust struct {
|
||||||
|
meter Meter
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchObserverMust is a wrapper for BatchObserver that panics when
|
||||||
|
// any instrument constructor encounters an error.
|
||||||
|
type BatchObserverMust struct {
|
||||||
|
batch BatchObserver
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must constructs a MeterMust implementation from a Meter, allowing
|
||||||
|
// the application to panic when any instrument constructor yields an
|
||||||
|
// error.
|
||||||
|
func Must(meter Meter) MeterMust {
|
||||||
|
return MeterMust{meter: meter}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64Counter calls `Meter.NewInt64Counter` and returns the
|
||||||
|
// instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewInt64Counter(name string, cos ...InstrumentOption) Int64Counter {
|
||||||
|
if inst, err := mm.meter.NewInt64Counter(name, cos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64Counter calls `Meter.NewFloat64Counter` and returns the
|
||||||
|
// instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewFloat64Counter(name string, cos ...InstrumentOption) Float64Counter {
|
||||||
|
if inst, err := mm.meter.NewFloat64Counter(name, cos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64UpDownCounter calls `Meter.NewInt64UpDownCounter` and returns the
|
||||||
|
// instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewInt64UpDownCounter(name string, cos ...InstrumentOption) Int64UpDownCounter {
|
||||||
|
if inst, err := mm.meter.NewInt64UpDownCounter(name, cos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64UpDownCounter calls `Meter.NewFloat64UpDownCounter` and returns the
|
||||||
|
// instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewFloat64UpDownCounter(name string, cos ...InstrumentOption) Float64UpDownCounter {
|
||||||
|
if inst, err := mm.meter.NewFloat64UpDownCounter(name, cos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64Histogram calls `Meter.NewInt64Histogram` and returns the
|
||||||
|
// instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewInt64Histogram(name string, mos ...InstrumentOption) Int64Histogram {
|
||||||
|
if inst, err := mm.meter.NewInt64Histogram(name, mos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64Histogram calls `Meter.NewFloat64Histogram` and returns the
|
||||||
|
// instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewFloat64Histogram(name string, mos ...InstrumentOption) Float64Histogram {
|
||||||
|
if inst, err := mm.meter.NewFloat64Histogram(name, mos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64GaugeObserver calls `Meter.NewInt64GaugeObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewInt64GaugeObserver(name string, callback Int64ObserverFunc, oos ...InstrumentOption) Int64GaugeObserver {
|
||||||
|
if inst, err := mm.meter.NewInt64GaugeObserver(name, callback, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64GaugeObserver calls `Meter.NewFloat64GaugeObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewFloat64GaugeObserver(name string, callback Float64ObserverFunc, oos ...InstrumentOption) Float64GaugeObserver {
|
||||||
|
if inst, err := mm.meter.NewFloat64GaugeObserver(name, callback, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64CounterObserver calls `Meter.NewInt64CounterObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewInt64CounterObserver(name string, callback Int64ObserverFunc, oos ...InstrumentOption) Int64CounterObserver {
|
||||||
|
if inst, err := mm.meter.NewInt64CounterObserver(name, callback, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64CounterObserver calls `Meter.NewFloat64CounterObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewFloat64CounterObserver(name string, callback Float64ObserverFunc, oos ...InstrumentOption) Float64CounterObserver {
|
||||||
|
if inst, err := mm.meter.NewFloat64CounterObserver(name, callback, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64UpDownCounterObserver calls `Meter.NewInt64UpDownCounterObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewInt64UpDownCounterObserver(name string, callback Int64ObserverFunc, oos ...InstrumentOption) Int64UpDownCounterObserver {
|
||||||
|
if inst, err := mm.meter.NewInt64UpDownCounterObserver(name, callback, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64UpDownCounterObserver calls `Meter.NewFloat64UpDownCounterObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (mm MeterMust) NewFloat64UpDownCounterObserver(name string, callback Float64ObserverFunc, oos ...InstrumentOption) Float64UpDownCounterObserver {
|
||||||
|
if inst, err := mm.meter.NewFloat64UpDownCounterObserver(name, callback, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBatchObserver returns a wrapper around BatchObserver that panics
|
||||||
|
// when any instrument constructor returns an error.
|
||||||
|
func (mm MeterMust) NewBatchObserver(callback BatchObserverFunc) BatchObserverMust {
|
||||||
|
return BatchObserverMust{
|
||||||
|
batch: mm.meter.NewBatchObserver(callback),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64GaugeObserver calls `BatchObserver.NewInt64GaugeObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (bm BatchObserverMust) NewInt64GaugeObserver(name string, oos ...InstrumentOption) Int64GaugeObserver {
|
||||||
|
if inst, err := bm.batch.NewInt64GaugeObserver(name, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64GaugeObserver calls `BatchObserver.NewFloat64GaugeObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (bm BatchObserverMust) NewFloat64GaugeObserver(name string, oos ...InstrumentOption) Float64GaugeObserver {
|
||||||
|
if inst, err := bm.batch.NewFloat64GaugeObserver(name, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64CounterObserver calls `BatchObserver.NewInt64CounterObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (bm BatchObserverMust) NewInt64CounterObserver(name string, oos ...InstrumentOption) Int64CounterObserver {
|
||||||
|
if inst, err := bm.batch.NewInt64CounterObserver(name, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64CounterObserver calls `BatchObserver.NewFloat64CounterObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (bm BatchObserverMust) NewFloat64CounterObserver(name string, oos ...InstrumentOption) Float64CounterObserver {
|
||||||
|
if inst, err := bm.batch.NewFloat64CounterObserver(name, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64UpDownCounterObserver calls `BatchObserver.NewInt64UpDownCounterObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (bm BatchObserverMust) NewInt64UpDownCounterObserver(name string, oos ...InstrumentOption) Int64UpDownCounterObserver {
|
||||||
|
if inst, err := bm.batch.NewInt64UpDownCounterObserver(name, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64UpDownCounterObserver calls `BatchObserver.NewFloat64UpDownCounterObserver` and
|
||||||
|
// returns the instrument, panicking if it encounters an error.
|
||||||
|
func (bm BatchObserverMust) NewFloat64UpDownCounterObserver(name string, oos ...InstrumentOption) Float64UpDownCounterObserver {
|
||||||
|
if inst, err := bm.batch.NewFloat64UpDownCounterObserver(name, oos...); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
608
vendor/go.opentelemetry.io/otel/metric/metric_instrument.go
generated
vendored
Normal file
608
vendor/go.opentelemetry.io/otel/metric/metric_instrument.go
generated
vendored
Normal file
@@ -0,0 +1,608 @@
|
|||||||
|
// Copyright The 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 "go.opentelemetry.io/otel/metric"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrSDKReturnedNilImpl is returned when a new `MeterImpl` returns nil.
|
||||||
|
var ErrSDKReturnedNilImpl = errors.New("SDK returned a nil implementation")
|
||||||
|
|
||||||
|
// Int64ObserverFunc is a type of callback that integral
|
||||||
|
// observers run.
|
||||||
|
type Int64ObserverFunc func(context.Context, Int64ObserverResult)
|
||||||
|
|
||||||
|
// Float64ObserverFunc is a type of callback that floating point
|
||||||
|
// observers run.
|
||||||
|
type Float64ObserverFunc func(context.Context, Float64ObserverResult)
|
||||||
|
|
||||||
|
// BatchObserverFunc is a callback argument for use with any
|
||||||
|
// Observer instrument that will be reported as a batch of
|
||||||
|
// observations.
|
||||||
|
type BatchObserverFunc func(context.Context, BatchObserverResult)
|
||||||
|
|
||||||
|
// Int64ObserverResult is passed to an observer callback to capture
|
||||||
|
// observations for one asynchronous integer metric instrument.
|
||||||
|
type Int64ObserverResult struct {
|
||||||
|
instrument sdkapi.AsyncImpl
|
||||||
|
function func([]attribute.KeyValue, ...Observation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64ObserverResult is passed to an observer callback to capture
|
||||||
|
// observations for one asynchronous floating point metric instrument.
|
||||||
|
type Float64ObserverResult struct {
|
||||||
|
instrument sdkapi.AsyncImpl
|
||||||
|
function func([]attribute.KeyValue, ...Observation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchObserverResult is passed to a batch observer callback to
|
||||||
|
// capture observations for multiple asynchronous instruments.
|
||||||
|
type BatchObserverResult struct {
|
||||||
|
function func([]attribute.KeyValue, ...Observation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observe captures a single integer value from the associated
|
||||||
|
// instrument callback, with the given labels.
|
||||||
|
func (ir Int64ObserverResult) Observe(value int64, labels ...attribute.KeyValue) {
|
||||||
|
ir.function(labels, sdkapi.NewObservation(ir.instrument, number.NewInt64Number(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observe captures a single floating point value from the associated
|
||||||
|
// instrument callback, with the given labels.
|
||||||
|
func (fr Float64ObserverResult) Observe(value float64, labels ...attribute.KeyValue) {
|
||||||
|
fr.function(labels, sdkapi.NewObservation(fr.instrument, number.NewFloat64Number(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observe captures a multiple observations from the associated batch
|
||||||
|
// instrument callback, with the given labels.
|
||||||
|
func (br BatchObserverResult) Observe(labels []attribute.KeyValue, obs ...Observation) {
|
||||||
|
br.function(labels, obs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ sdkapi.AsyncSingleRunner = (*Int64ObserverFunc)(nil)
|
||||||
|
var _ sdkapi.AsyncSingleRunner = (*Float64ObserverFunc)(nil)
|
||||||
|
var _ sdkapi.AsyncBatchRunner = (*BatchObserverFunc)(nil)
|
||||||
|
|
||||||
|
// newInt64AsyncRunner returns a single-observer callback for integer Observer instruments.
|
||||||
|
func newInt64AsyncRunner(c Int64ObserverFunc) sdkapi.AsyncSingleRunner {
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
// newFloat64AsyncRunner returns a single-observer callback for floating point Observer instruments.
|
||||||
|
func newFloat64AsyncRunner(c Float64ObserverFunc) sdkapi.AsyncSingleRunner {
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
// newBatchAsyncRunner returns a batch-observer callback use with multiple Observer instruments.
|
||||||
|
func newBatchAsyncRunner(c BatchObserverFunc) sdkapi.AsyncBatchRunner {
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyRunner implements AsyncRunner.
|
||||||
|
func (*Int64ObserverFunc) AnyRunner() {}
|
||||||
|
|
||||||
|
// AnyRunner implements AsyncRunner.
|
||||||
|
func (*Float64ObserverFunc) AnyRunner() {}
|
||||||
|
|
||||||
|
// AnyRunner implements AsyncRunner.
|
||||||
|
func (*BatchObserverFunc) AnyRunner() {}
|
||||||
|
|
||||||
|
// Run implements AsyncSingleRunner.
|
||||||
|
func (i *Int64ObserverFunc) Run(ctx context.Context, impl sdkapi.AsyncImpl, function func([]attribute.KeyValue, ...Observation)) {
|
||||||
|
(*i)(ctx, Int64ObserverResult{
|
||||||
|
instrument: impl,
|
||||||
|
function: function,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run implements AsyncSingleRunner.
|
||||||
|
func (f *Float64ObserverFunc) Run(ctx context.Context, impl sdkapi.AsyncImpl, function func([]attribute.KeyValue, ...Observation)) {
|
||||||
|
(*f)(ctx, Float64ObserverResult{
|
||||||
|
instrument: impl,
|
||||||
|
function: function,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run implements AsyncBatchRunner.
|
||||||
|
func (b *BatchObserverFunc) Run(ctx context.Context, function func([]attribute.KeyValue, ...Observation)) {
|
||||||
|
(*b)(ctx, BatchObserverResult{
|
||||||
|
function: function,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapInt64GaugeObserverInstrument converts an AsyncImpl into Int64GaugeObserver.
|
||||||
|
func wrapInt64GaugeObserverInstrument(asyncInst sdkapi.AsyncImpl, err error) (Int64GaugeObserver, error) {
|
||||||
|
common, err := checkNewAsync(asyncInst, err)
|
||||||
|
return Int64GaugeObserver{asyncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapFloat64GaugeObserverInstrument converts an AsyncImpl into Float64GaugeObserver.
|
||||||
|
func wrapFloat64GaugeObserverInstrument(asyncInst sdkapi.AsyncImpl, err error) (Float64GaugeObserver, error) {
|
||||||
|
common, err := checkNewAsync(asyncInst, err)
|
||||||
|
return Float64GaugeObserver{asyncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapInt64CounterObserverInstrument converts an AsyncImpl into Int64CounterObserver.
|
||||||
|
func wrapInt64CounterObserverInstrument(asyncInst sdkapi.AsyncImpl, err error) (Int64CounterObserver, error) {
|
||||||
|
common, err := checkNewAsync(asyncInst, err)
|
||||||
|
return Int64CounterObserver{asyncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapFloat64CounterObserverInstrument converts an AsyncImpl into Float64CounterObserver.
|
||||||
|
func wrapFloat64CounterObserverInstrument(asyncInst sdkapi.AsyncImpl, err error) (Float64CounterObserver, error) {
|
||||||
|
common, err := checkNewAsync(asyncInst, err)
|
||||||
|
return Float64CounterObserver{asyncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapInt64UpDownCounterObserverInstrument converts an AsyncImpl into Int64UpDownCounterObserver.
|
||||||
|
func wrapInt64UpDownCounterObserverInstrument(asyncInst sdkapi.AsyncImpl, err error) (Int64UpDownCounterObserver, error) {
|
||||||
|
common, err := checkNewAsync(asyncInst, err)
|
||||||
|
return Int64UpDownCounterObserver{asyncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapFloat64UpDownCounterObserverInstrument converts an AsyncImpl into Float64UpDownCounterObserver.
|
||||||
|
func wrapFloat64UpDownCounterObserverInstrument(asyncInst sdkapi.AsyncImpl, err error) (Float64UpDownCounterObserver, error) {
|
||||||
|
common, err := checkNewAsync(asyncInst, err)
|
||||||
|
return Float64UpDownCounterObserver{asyncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchObserver represents an Observer callback that can report
|
||||||
|
// observations for multiple instruments.
|
||||||
|
type BatchObserver struct {
|
||||||
|
meter Meter
|
||||||
|
runner sdkapi.AsyncBatchRunner
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64GaugeObserver is a metric that captures a set of int64 values at a
|
||||||
|
// point in time.
|
||||||
|
type Int64GaugeObserver struct {
|
||||||
|
asyncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64GaugeObserver is a metric that captures a set of float64 values
|
||||||
|
// at a point in time.
|
||||||
|
type Float64GaugeObserver struct {
|
||||||
|
asyncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64CounterObserver is a metric that captures a precomputed sum of
|
||||||
|
// int64 values at a point in time.
|
||||||
|
type Int64CounterObserver struct {
|
||||||
|
asyncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64CounterObserver is a metric that captures a precomputed sum of
|
||||||
|
// float64 values at a point in time.
|
||||||
|
type Float64CounterObserver struct {
|
||||||
|
asyncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64UpDownCounterObserver is a metric that captures a precomputed sum of
|
||||||
|
// int64 values at a point in time.
|
||||||
|
type Int64UpDownCounterObserver struct {
|
||||||
|
asyncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64UpDownCounterObserver is a metric that captures a precomputed sum of
|
||||||
|
// float64 values at a point in time.
|
||||||
|
type Float64UpDownCounterObserver struct {
|
||||||
|
asyncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observation returns an Observation, a BatchObserverFunc
|
||||||
|
// argument, for an asynchronous integer instrument.
|
||||||
|
// This returns an implementation-level object for use by the SDK,
|
||||||
|
// users should not refer to this.
|
||||||
|
func (i Int64GaugeObserver) Observation(v int64) Observation {
|
||||||
|
return sdkapi.NewObservation(i.instrument, number.NewInt64Number(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observation returns an Observation, a BatchObserverFunc
|
||||||
|
// argument, for an asynchronous integer instrument.
|
||||||
|
// This returns an implementation-level object for use by the SDK,
|
||||||
|
// users should not refer to this.
|
||||||
|
func (f Float64GaugeObserver) Observation(v float64) Observation {
|
||||||
|
return sdkapi.NewObservation(f.instrument, number.NewFloat64Number(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observation returns an Observation, a BatchObserverFunc
|
||||||
|
// argument, for an asynchronous integer instrument.
|
||||||
|
// This returns an implementation-level object for use by the SDK,
|
||||||
|
// users should not refer to this.
|
||||||
|
func (i Int64CounterObserver) Observation(v int64) Observation {
|
||||||
|
return sdkapi.NewObservation(i.instrument, number.NewInt64Number(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observation returns an Observation, a BatchObserverFunc
|
||||||
|
// argument, for an asynchronous integer instrument.
|
||||||
|
// This returns an implementation-level object for use by the SDK,
|
||||||
|
// users should not refer to this.
|
||||||
|
func (f Float64CounterObserver) Observation(v float64) Observation {
|
||||||
|
return sdkapi.NewObservation(f.instrument, number.NewFloat64Number(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observation returns an Observation, a BatchObserverFunc
|
||||||
|
// argument, for an asynchronous integer instrument.
|
||||||
|
// This returns an implementation-level object for use by the SDK,
|
||||||
|
// users should not refer to this.
|
||||||
|
func (i Int64UpDownCounterObserver) Observation(v int64) Observation {
|
||||||
|
return sdkapi.NewObservation(i.instrument, number.NewInt64Number(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observation returns an Observation, a BatchObserverFunc
|
||||||
|
// argument, for an asynchronous integer instrument.
|
||||||
|
// This returns an implementation-level object for use by the SDK,
|
||||||
|
// users should not refer to this.
|
||||||
|
func (f Float64UpDownCounterObserver) Observation(v float64) Observation {
|
||||||
|
return sdkapi.NewObservation(f.instrument, number.NewFloat64Number(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// syncInstrument contains a SyncImpl.
|
||||||
|
type syncInstrument struct {
|
||||||
|
instrument sdkapi.SyncImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// syncBoundInstrument contains a BoundSyncImpl.
|
||||||
|
type syncBoundInstrument struct {
|
||||||
|
boundInstrument sdkapi.BoundSyncImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// asyncInstrument contains a AsyncImpl.
|
||||||
|
type asyncInstrument struct {
|
||||||
|
instrument sdkapi.AsyncImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncImpl implements AsyncImpl.
|
||||||
|
func (a asyncInstrument) AsyncImpl() sdkapi.AsyncImpl {
|
||||||
|
return a.instrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncImpl returns the implementation object for synchronous instruments.
|
||||||
|
func (s syncInstrument) SyncImpl() sdkapi.SyncImpl {
|
||||||
|
return s.instrument
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s syncInstrument) bind(labels []attribute.KeyValue) syncBoundInstrument {
|
||||||
|
return newSyncBoundInstrument(s.instrument.Bind(labels))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s syncInstrument) float64Measurement(value float64) Measurement {
|
||||||
|
return sdkapi.NewMeasurement(s.instrument, number.NewFloat64Number(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s syncInstrument) int64Measurement(value int64) Measurement {
|
||||||
|
return sdkapi.NewMeasurement(s.instrument, number.NewInt64Number(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s syncInstrument) directRecord(ctx context.Context, number number.Number, labels []attribute.KeyValue) {
|
||||||
|
s.instrument.RecordOne(ctx, number, labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h syncBoundInstrument) directRecord(ctx context.Context, number number.Number) {
|
||||||
|
h.boundInstrument.RecordOne(ctx, number)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unbind calls SyncImpl.Unbind.
|
||||||
|
func (h syncBoundInstrument) Unbind() {
|
||||||
|
h.boundInstrument.Unbind()
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkNewAsync receives an AsyncImpl and potential
|
||||||
|
// error, and returns the same types, checking for and ensuring that
|
||||||
|
// the returned interface is not nil.
|
||||||
|
func checkNewAsync(instrument sdkapi.AsyncImpl, err error) (asyncInstrument, error) {
|
||||||
|
if instrument == nil {
|
||||||
|
if err == nil {
|
||||||
|
err = ErrSDKReturnedNilImpl
|
||||||
|
}
|
||||||
|
instrument = sdkapi.NewNoopAsyncInstrument()
|
||||||
|
}
|
||||||
|
return asyncInstrument{
|
||||||
|
instrument: instrument,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkNewSync receives an SyncImpl and potential
|
||||||
|
// error, and returns the same types, checking for and ensuring that
|
||||||
|
// the returned interface is not nil.
|
||||||
|
func checkNewSync(instrument sdkapi.SyncImpl, err error) (syncInstrument, error) {
|
||||||
|
if instrument == nil {
|
||||||
|
if err == nil {
|
||||||
|
err = ErrSDKReturnedNilImpl
|
||||||
|
}
|
||||||
|
// Note: an alternate behavior would be to synthesize a new name
|
||||||
|
// or group all duplicately-named instruments of a certain type
|
||||||
|
// together and use a tag for the original name, e.g.,
|
||||||
|
// name = 'invalid.counter.int64'
|
||||||
|
// label = 'original-name=duplicate-counter-name'
|
||||||
|
instrument = sdkapi.NewNoopSyncInstrument()
|
||||||
|
}
|
||||||
|
return syncInstrument{
|
||||||
|
instrument: instrument,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSyncBoundInstrument(boundInstrument sdkapi.BoundSyncImpl) syncBoundInstrument {
|
||||||
|
return syncBoundInstrument{
|
||||||
|
boundInstrument: boundInstrument,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapInt64CounterInstrument converts a SyncImpl into Int64Counter.
|
||||||
|
func wrapInt64CounterInstrument(syncInst sdkapi.SyncImpl, err error) (Int64Counter, error) {
|
||||||
|
common, err := checkNewSync(syncInst, err)
|
||||||
|
return Int64Counter{syncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapFloat64CounterInstrument converts a SyncImpl into Float64Counter.
|
||||||
|
func wrapFloat64CounterInstrument(syncInst sdkapi.SyncImpl, err error) (Float64Counter, error) {
|
||||||
|
common, err := checkNewSync(syncInst, err)
|
||||||
|
return Float64Counter{syncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapInt64UpDownCounterInstrument converts a SyncImpl into Int64UpDownCounter.
|
||||||
|
func wrapInt64UpDownCounterInstrument(syncInst sdkapi.SyncImpl, err error) (Int64UpDownCounter, error) {
|
||||||
|
common, err := checkNewSync(syncInst, err)
|
||||||
|
return Int64UpDownCounter{syncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapFloat64UpDownCounterInstrument converts a SyncImpl into Float64UpDownCounter.
|
||||||
|
func wrapFloat64UpDownCounterInstrument(syncInst sdkapi.SyncImpl, err error) (Float64UpDownCounter, error) {
|
||||||
|
common, err := checkNewSync(syncInst, err)
|
||||||
|
return Float64UpDownCounter{syncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapInt64HistogramInstrument converts a SyncImpl into Int64Histogram.
|
||||||
|
func wrapInt64HistogramInstrument(syncInst sdkapi.SyncImpl, err error) (Int64Histogram, error) {
|
||||||
|
common, err := checkNewSync(syncInst, err)
|
||||||
|
return Int64Histogram{syncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapFloat64HistogramInstrument converts a SyncImpl into Float64Histogram.
|
||||||
|
func wrapFloat64HistogramInstrument(syncInst sdkapi.SyncImpl, err error) (Float64Histogram, error) {
|
||||||
|
common, err := checkNewSync(syncInst, err)
|
||||||
|
return Float64Histogram{syncInstrument: common}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Counter is a metric that accumulates float64 values.
|
||||||
|
type Float64Counter struct {
|
||||||
|
syncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Counter is a metric that accumulates int64 values.
|
||||||
|
type Int64Counter struct {
|
||||||
|
syncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoundFloat64Counter is a bound instrument for Float64Counter.
|
||||||
|
//
|
||||||
|
// It inherits the Unbind function from syncBoundInstrument.
|
||||||
|
type BoundFloat64Counter struct {
|
||||||
|
syncBoundInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoundInt64Counter is a boundInstrument for Int64Counter.
|
||||||
|
//
|
||||||
|
// It inherits the Unbind function from syncBoundInstrument.
|
||||||
|
type BoundInt64Counter struct {
|
||||||
|
syncBoundInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind creates a bound instrument for this counter. The labels are
|
||||||
|
// associated with values recorded via subsequent calls to Record.
|
||||||
|
func (c Float64Counter) Bind(labels ...attribute.KeyValue) (h BoundFloat64Counter) {
|
||||||
|
h.syncBoundInstrument = c.bind(labels)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind creates a bound instrument for this counter. The labels are
|
||||||
|
// associated with values recorded via subsequent calls to Record.
|
||||||
|
func (c Int64Counter) Bind(labels ...attribute.KeyValue) (h BoundInt64Counter) {
|
||||||
|
h.syncBoundInstrument = c.bind(labels)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measurement creates a Measurement object to use with batch
|
||||||
|
// recording.
|
||||||
|
func (c Float64Counter) Measurement(value float64) Measurement {
|
||||||
|
return c.float64Measurement(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measurement creates a Measurement object to use with batch
|
||||||
|
// recording.
|
||||||
|
func (c Int64Counter) Measurement(value int64) Measurement {
|
||||||
|
return c.int64Measurement(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the value to the counter's sum. The labels should contain
|
||||||
|
// the keys and values to be associated with this value.
|
||||||
|
func (c Float64Counter) Add(ctx context.Context, value float64, labels ...attribute.KeyValue) {
|
||||||
|
c.directRecord(ctx, number.NewFloat64Number(value), labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the value to the counter's sum. The labels should contain
|
||||||
|
// the keys and values to be associated with this value.
|
||||||
|
func (c Int64Counter) Add(ctx context.Context, value int64, labels ...attribute.KeyValue) {
|
||||||
|
c.directRecord(ctx, number.NewInt64Number(value), labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the value to the counter's sum using the labels
|
||||||
|
// previously bound to this counter via Bind()
|
||||||
|
func (b BoundFloat64Counter) Add(ctx context.Context, value float64) {
|
||||||
|
b.directRecord(ctx, number.NewFloat64Number(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the value to the counter's sum using the labels
|
||||||
|
// previously bound to this counter via Bind()
|
||||||
|
func (b BoundInt64Counter) Add(ctx context.Context, value int64) {
|
||||||
|
b.directRecord(ctx, number.NewInt64Number(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64UpDownCounter is a metric instrument that sums floating
|
||||||
|
// point values.
|
||||||
|
type Float64UpDownCounter struct {
|
||||||
|
syncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64UpDownCounter is a metric instrument that sums integer values.
|
||||||
|
type Int64UpDownCounter struct {
|
||||||
|
syncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoundFloat64UpDownCounter is a bound instrument for Float64UpDownCounter.
|
||||||
|
//
|
||||||
|
// It inherits the Unbind function from syncBoundInstrument.
|
||||||
|
type BoundFloat64UpDownCounter struct {
|
||||||
|
syncBoundInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoundInt64UpDownCounter is a boundInstrument for Int64UpDownCounter.
|
||||||
|
//
|
||||||
|
// It inherits the Unbind function from syncBoundInstrument.
|
||||||
|
type BoundInt64UpDownCounter struct {
|
||||||
|
syncBoundInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind creates a bound instrument for this counter. The labels are
|
||||||
|
// associated with values recorded via subsequent calls to Record.
|
||||||
|
func (c Float64UpDownCounter) Bind(labels ...attribute.KeyValue) (h BoundFloat64UpDownCounter) {
|
||||||
|
h.syncBoundInstrument = c.bind(labels)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind creates a bound instrument for this counter. The labels are
|
||||||
|
// associated with values recorded via subsequent calls to Record.
|
||||||
|
func (c Int64UpDownCounter) Bind(labels ...attribute.KeyValue) (h BoundInt64UpDownCounter) {
|
||||||
|
h.syncBoundInstrument = c.bind(labels)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measurement creates a Measurement object to use with batch
|
||||||
|
// recording.
|
||||||
|
func (c Float64UpDownCounter) Measurement(value float64) Measurement {
|
||||||
|
return c.float64Measurement(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measurement creates a Measurement object to use with batch
|
||||||
|
// recording.
|
||||||
|
func (c Int64UpDownCounter) Measurement(value int64) Measurement {
|
||||||
|
return c.int64Measurement(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the value to the counter's sum. The labels should contain
|
||||||
|
// the keys and values to be associated with this value.
|
||||||
|
func (c Float64UpDownCounter) Add(ctx context.Context, value float64, labels ...attribute.KeyValue) {
|
||||||
|
c.directRecord(ctx, number.NewFloat64Number(value), labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the value to the counter's sum. The labels should contain
|
||||||
|
// the keys and values to be associated with this value.
|
||||||
|
func (c Int64UpDownCounter) Add(ctx context.Context, value int64, labels ...attribute.KeyValue) {
|
||||||
|
c.directRecord(ctx, number.NewInt64Number(value), labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the value to the counter's sum using the labels
|
||||||
|
// previously bound to this counter via Bind()
|
||||||
|
func (b BoundFloat64UpDownCounter) Add(ctx context.Context, value float64) {
|
||||||
|
b.directRecord(ctx, number.NewFloat64Number(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the value to the counter's sum using the labels
|
||||||
|
// previously bound to this counter via Bind()
|
||||||
|
func (b BoundInt64UpDownCounter) Add(ctx context.Context, value int64) {
|
||||||
|
b.directRecord(ctx, number.NewInt64Number(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Histogram is a metric that records float64 values.
|
||||||
|
type Float64Histogram struct {
|
||||||
|
syncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Histogram is a metric that records int64 values.
|
||||||
|
type Int64Histogram struct {
|
||||||
|
syncInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoundFloat64Histogram is a bound instrument for Float64Histogram.
|
||||||
|
//
|
||||||
|
// It inherits the Unbind function from syncBoundInstrument.
|
||||||
|
type BoundFloat64Histogram struct {
|
||||||
|
syncBoundInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoundInt64Histogram is a bound instrument for Int64Histogram.
|
||||||
|
//
|
||||||
|
// It inherits the Unbind function from syncBoundInstrument.
|
||||||
|
type BoundInt64Histogram struct {
|
||||||
|
syncBoundInstrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind creates a bound instrument for this Histogram. The labels are
|
||||||
|
// associated with values recorded via subsequent calls to Record.
|
||||||
|
func (c Float64Histogram) Bind(labels ...attribute.KeyValue) (h BoundFloat64Histogram) {
|
||||||
|
h.syncBoundInstrument = c.bind(labels)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind creates a bound instrument for this Histogram. The labels are
|
||||||
|
// associated with values recorded via subsequent calls to Record.
|
||||||
|
func (c Int64Histogram) Bind(labels ...attribute.KeyValue) (h BoundInt64Histogram) {
|
||||||
|
h.syncBoundInstrument = c.bind(labels)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measurement creates a Measurement object to use with batch
|
||||||
|
// recording.
|
||||||
|
func (c Float64Histogram) Measurement(value float64) Measurement {
|
||||||
|
return c.float64Measurement(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measurement creates a Measurement object to use with batch
|
||||||
|
// recording.
|
||||||
|
func (c Int64Histogram) Measurement(value int64) Measurement {
|
||||||
|
return c.int64Measurement(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record adds a new value to the list of Histogram's records. The
|
||||||
|
// labels should contain the keys and values to be associated with
|
||||||
|
// this value.
|
||||||
|
func (c Float64Histogram) Record(ctx context.Context, value float64, labels ...attribute.KeyValue) {
|
||||||
|
c.directRecord(ctx, number.NewFloat64Number(value), labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record adds a new value to the Histogram's distribution. The
|
||||||
|
// labels should contain the keys and values to be associated with
|
||||||
|
// this value.
|
||||||
|
func (c Int64Histogram) Record(ctx context.Context, value int64, labels ...attribute.KeyValue) {
|
||||||
|
c.directRecord(ctx, number.NewInt64Number(value), labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record adds a new value to the Histogram's distribution using the labels
|
||||||
|
// previously bound to the Histogram via Bind().
|
||||||
|
func (b BoundFloat64Histogram) Record(ctx context.Context, value float64) {
|
||||||
|
b.directRecord(ctx, number.NewFloat64Number(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record adds a new value to the Histogram's distribution using the labels
|
||||||
|
// previously bound to the Histogram via Bind().
|
||||||
|
func (b BoundInt64Histogram) Record(ctx context.Context, value int64) {
|
||||||
|
b.directRecord(ctx, number.NewInt64Number(value))
|
||||||
|
}
|
||||||
30
vendor/go.opentelemetry.io/otel/metric/noop.go
generated
vendored
Normal file
30
vendor/go.opentelemetry.io/otel/metric/noop.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright The 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 "go.opentelemetry.io/otel/metric"
|
||||||
|
|
||||||
|
type noopMeterProvider struct{}
|
||||||
|
|
||||||
|
// NewNoopMeterProvider returns an implementation of MeterProvider that
|
||||||
|
// performs no operations. The Meter and Instrument created from the returned
|
||||||
|
// MeterProvider also perform no operations.
|
||||||
|
func NewNoopMeterProvider() MeterProvider {
|
||||||
|
return noopMeterProvider{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ MeterProvider = noopMeterProvider{}
|
||||||
|
|
||||||
|
func (noopMeterProvider) Meter(instrumentationName string, opts ...MeterOption) Meter {
|
||||||
|
return Meter{}
|
||||||
|
}
|
||||||
23
vendor/go.opentelemetry.io/otel/metric/number/doc.go
generated
vendored
Normal file
23
vendor/go.opentelemetry.io/otel/metric/number/doc.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright The 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 number provides a number abstraction for instruments that
|
||||||
|
either support int64 or float64 input values.
|
||||||
|
|
||||||
|
This package is currently in a pre-GA phase. Backwards incompatible changes
|
||||||
|
may be introduced in subsequent minor version releases as we work to track the
|
||||||
|
evolving OpenTelemetry specification and user feedback.
|
||||||
|
*/
|
||||||
|
package number // import "go.opentelemetry.io/otel/metric/number"
|
||||||
24
vendor/go.opentelemetry.io/otel/metric/number/kind_string.go
generated
vendored
Normal file
24
vendor/go.opentelemetry.io/otel/metric/number/kind_string.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Code generated by "stringer -type=Kind"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package number
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[Int64Kind-0]
|
||||||
|
_ = x[Float64Kind-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _Kind_name = "Int64KindFloat64Kind"
|
||||||
|
|
||||||
|
var _Kind_index = [...]uint8{0, 9, 20}
|
||||||
|
|
||||||
|
func (i Kind) String() string {
|
||||||
|
if i < 0 || i >= Kind(len(_Kind_index)-1) {
|
||||||
|
return "Kind(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
|
||||||
|
}
|
||||||
538
vendor/go.opentelemetry.io/otel/metric/number/number.go
generated
vendored
Normal file
538
vendor/go.opentelemetry.io/otel/metric/number/number.go
generated
vendored
Normal file
@@ -0,0 +1,538 @@
|
|||||||
|
// Copyright The 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 number // import "go.opentelemetry.io/otel/metric/number"
|
||||||
|
|
||||||
|
//go:generate stringer -type=Kind
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Kind describes the data type of the Number.
|
||||||
|
type Kind int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Int64Kind means that the Number stores int64.
|
||||||
|
Int64Kind Kind = iota
|
||||||
|
// Float64Kind means that the Number stores float64.
|
||||||
|
Float64Kind
|
||||||
|
)
|
||||||
|
|
||||||
|
// Zero returns a zero value for a given Kind
|
||||||
|
func (k Kind) Zero() Number {
|
||||||
|
switch k {
|
||||||
|
case Int64Kind:
|
||||||
|
return NewInt64Number(0)
|
||||||
|
case Float64Kind:
|
||||||
|
return NewFloat64Number(0.)
|
||||||
|
default:
|
||||||
|
return Number(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minimum returns the minimum representable value
|
||||||
|
// for a given Kind
|
||||||
|
func (k Kind) Minimum() Number {
|
||||||
|
switch k {
|
||||||
|
case Int64Kind:
|
||||||
|
return NewInt64Number(math.MinInt64)
|
||||||
|
case Float64Kind:
|
||||||
|
return NewFloat64Number(-1. * math.MaxFloat64)
|
||||||
|
default:
|
||||||
|
return Number(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maximum returns the maximum representable value
|
||||||
|
// for a given Kind
|
||||||
|
func (k Kind) Maximum() Number {
|
||||||
|
switch k {
|
||||||
|
case Int64Kind:
|
||||||
|
return NewInt64Number(math.MaxInt64)
|
||||||
|
case Float64Kind:
|
||||||
|
return NewFloat64Number(math.MaxFloat64)
|
||||||
|
default:
|
||||||
|
return Number(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number represents either an integral or a floating point value. It
|
||||||
|
// needs to be accompanied with a source of Kind that describes
|
||||||
|
// the actual type of the value stored within Number.
|
||||||
|
type Number uint64
|
||||||
|
|
||||||
|
// - constructors
|
||||||
|
|
||||||
|
// NewNumberFromRaw creates a new Number from a raw value.
|
||||||
|
func NewNumberFromRaw(r uint64) Number {
|
||||||
|
return Number(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt64Number creates an integral Number.
|
||||||
|
func NewInt64Number(i int64) Number {
|
||||||
|
return NewNumberFromRaw(internal.Int64ToRaw(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64Number creates a floating point Number.
|
||||||
|
func NewFloat64Number(f float64) Number {
|
||||||
|
return NewNumberFromRaw(internal.Float64ToRaw(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNumberSignChange returns a number with the same magnitude and
|
||||||
|
// the opposite sign. `kind` must describe the kind of number in `nn`.
|
||||||
|
func NewNumberSignChange(kind Kind, nn Number) Number {
|
||||||
|
switch kind {
|
||||||
|
case Int64Kind:
|
||||||
|
return NewInt64Number(-nn.AsInt64())
|
||||||
|
case Float64Kind:
|
||||||
|
return NewFloat64Number(-nn.AsFloat64())
|
||||||
|
}
|
||||||
|
return nn
|
||||||
|
}
|
||||||
|
|
||||||
|
// - as x
|
||||||
|
|
||||||
|
// AsNumber gets the Number.
|
||||||
|
func (n *Number) AsNumber() Number {
|
||||||
|
return *n
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsRaw gets the uninterpreted raw value. Might be useful for some
|
||||||
|
// atomic operations.
|
||||||
|
func (n *Number) AsRaw() uint64 {
|
||||||
|
return uint64(*n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsInt64 assumes that the value contains an int64 and returns it as
|
||||||
|
// such.
|
||||||
|
func (n *Number) AsInt64() int64 {
|
||||||
|
return internal.RawToInt64(n.AsRaw())
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsFloat64 assumes that the measurement value contains a float64 and
|
||||||
|
// returns it as such.
|
||||||
|
func (n *Number) AsFloat64() float64 {
|
||||||
|
return internal.RawToFloat64(n.AsRaw())
|
||||||
|
}
|
||||||
|
|
||||||
|
// - as x atomic
|
||||||
|
|
||||||
|
// AsNumberAtomic gets the Number atomically.
|
||||||
|
func (n *Number) AsNumberAtomic() Number {
|
||||||
|
return NewNumberFromRaw(n.AsRawAtomic())
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsRawAtomic gets the uninterpreted raw value atomically. Might be
|
||||||
|
// useful for some atomic operations.
|
||||||
|
func (n *Number) AsRawAtomic() uint64 {
|
||||||
|
return atomic.LoadUint64(n.AsRawPtr())
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsInt64Atomic assumes that the number contains an int64 and returns
|
||||||
|
// it as such atomically.
|
||||||
|
func (n *Number) AsInt64Atomic() int64 {
|
||||||
|
return atomic.LoadInt64(n.AsInt64Ptr())
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsFloat64Atomic assumes that the measurement value contains a
|
||||||
|
// float64 and returns it as such atomically.
|
||||||
|
func (n *Number) AsFloat64Atomic() float64 {
|
||||||
|
return internal.RawToFloat64(n.AsRawAtomic())
|
||||||
|
}
|
||||||
|
|
||||||
|
// - as x ptr
|
||||||
|
|
||||||
|
// AsRawPtr gets the pointer to the raw, uninterpreted raw
|
||||||
|
// value. Might be useful for some atomic operations.
|
||||||
|
func (n *Number) AsRawPtr() *uint64 {
|
||||||
|
return (*uint64)(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsInt64Ptr assumes that the number contains an int64 and returns a
|
||||||
|
// pointer to it.
|
||||||
|
func (n *Number) AsInt64Ptr() *int64 {
|
||||||
|
return internal.RawPtrToInt64Ptr(n.AsRawPtr())
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsFloat64Ptr assumes that the number contains a float64 and returns a
|
||||||
|
// pointer to it.
|
||||||
|
func (n *Number) AsFloat64Ptr() *float64 {
|
||||||
|
return internal.RawPtrToFloat64Ptr(n.AsRawPtr())
|
||||||
|
}
|
||||||
|
|
||||||
|
// - coerce
|
||||||
|
|
||||||
|
// CoerceToInt64 casts the number to int64. May result in
|
||||||
|
// data/precision loss.
|
||||||
|
func (n *Number) CoerceToInt64(kind Kind) int64 {
|
||||||
|
switch kind {
|
||||||
|
case Int64Kind:
|
||||||
|
return n.AsInt64()
|
||||||
|
case Float64Kind:
|
||||||
|
return int64(n.AsFloat64())
|
||||||
|
default:
|
||||||
|
// you get what you deserve
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CoerceToFloat64 casts the number to float64. May result in
|
||||||
|
// data/precision loss.
|
||||||
|
func (n *Number) CoerceToFloat64(kind Kind) float64 {
|
||||||
|
switch kind {
|
||||||
|
case Int64Kind:
|
||||||
|
return float64(n.AsInt64())
|
||||||
|
case Float64Kind:
|
||||||
|
return n.AsFloat64()
|
||||||
|
default:
|
||||||
|
// you get what you deserve
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - set
|
||||||
|
|
||||||
|
// SetNumber sets the number to the passed number. Both should be of
|
||||||
|
// the same kind.
|
||||||
|
func (n *Number) SetNumber(nn Number) {
|
||||||
|
*n.AsRawPtr() = nn.AsRaw()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRaw sets the number to the passed raw value. Both number and the
|
||||||
|
// raw number should represent the same kind.
|
||||||
|
func (n *Number) SetRaw(r uint64) {
|
||||||
|
*n.AsRawPtr() = r
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInt64 assumes that the number contains an int64 and sets it to
|
||||||
|
// the passed value.
|
||||||
|
func (n *Number) SetInt64(i int64) {
|
||||||
|
*n.AsInt64Ptr() = i
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFloat64 assumes that the number contains a float64 and sets it
|
||||||
|
// to the passed value.
|
||||||
|
func (n *Number) SetFloat64(f float64) {
|
||||||
|
*n.AsFloat64Ptr() = f
|
||||||
|
}
|
||||||
|
|
||||||
|
// - set atomic
|
||||||
|
|
||||||
|
// SetNumberAtomic sets the number to the passed number
|
||||||
|
// atomically. Both should be of the same kind.
|
||||||
|
func (n *Number) SetNumberAtomic(nn Number) {
|
||||||
|
atomic.StoreUint64(n.AsRawPtr(), nn.AsRaw())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRawAtomic sets the number to the passed raw value
|
||||||
|
// atomically. Both number and the raw number should represent the
|
||||||
|
// same kind.
|
||||||
|
func (n *Number) SetRawAtomic(r uint64) {
|
||||||
|
atomic.StoreUint64(n.AsRawPtr(), r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInt64Atomic assumes that the number contains an int64 and sets
|
||||||
|
// it to the passed value atomically.
|
||||||
|
func (n *Number) SetInt64Atomic(i int64) {
|
||||||
|
atomic.StoreInt64(n.AsInt64Ptr(), i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFloat64Atomic assumes that the number contains a float64 and
|
||||||
|
// sets it to the passed value atomically.
|
||||||
|
func (n *Number) SetFloat64Atomic(f float64) {
|
||||||
|
atomic.StoreUint64(n.AsRawPtr(), internal.Float64ToRaw(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// - swap
|
||||||
|
|
||||||
|
// SwapNumber sets the number to the passed number and returns the old
|
||||||
|
// number. Both this number and the passed number should be of the
|
||||||
|
// same kind.
|
||||||
|
func (n *Number) SwapNumber(nn Number) Number {
|
||||||
|
old := *n
|
||||||
|
n.SetNumber(nn)
|
||||||
|
return old
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwapRaw sets the number to the passed raw value and returns the old
|
||||||
|
// raw value. Both number and the raw number should represent the same
|
||||||
|
// kind.
|
||||||
|
func (n *Number) SwapRaw(r uint64) uint64 {
|
||||||
|
old := n.AsRaw()
|
||||||
|
n.SetRaw(r)
|
||||||
|
return old
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwapInt64 assumes that the number contains an int64, sets it to the
|
||||||
|
// passed value and returns the old int64 value.
|
||||||
|
func (n *Number) SwapInt64(i int64) int64 {
|
||||||
|
old := n.AsInt64()
|
||||||
|
n.SetInt64(i)
|
||||||
|
return old
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwapFloat64 assumes that the number contains an float64, sets it to
|
||||||
|
// the passed value and returns the old float64 value.
|
||||||
|
func (n *Number) SwapFloat64(f float64) float64 {
|
||||||
|
old := n.AsFloat64()
|
||||||
|
n.SetFloat64(f)
|
||||||
|
return old
|
||||||
|
}
|
||||||
|
|
||||||
|
// - swap atomic
|
||||||
|
|
||||||
|
// SwapNumberAtomic sets the number to the passed number and returns
|
||||||
|
// the old number atomically. Both this number and the passed number
|
||||||
|
// should be of the same kind.
|
||||||
|
func (n *Number) SwapNumberAtomic(nn Number) Number {
|
||||||
|
return NewNumberFromRaw(atomic.SwapUint64(n.AsRawPtr(), nn.AsRaw()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwapRawAtomic sets the number to the passed raw value and returns
|
||||||
|
// the old raw value atomically. Both number and the raw number should
|
||||||
|
// represent the same kind.
|
||||||
|
func (n *Number) SwapRawAtomic(r uint64) uint64 {
|
||||||
|
return atomic.SwapUint64(n.AsRawPtr(), r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwapInt64Atomic assumes that the number contains an int64, sets it
|
||||||
|
// to the passed value and returns the old int64 value atomically.
|
||||||
|
func (n *Number) SwapInt64Atomic(i int64) int64 {
|
||||||
|
return atomic.SwapInt64(n.AsInt64Ptr(), i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwapFloat64Atomic assumes that the number contains an float64, sets
|
||||||
|
// it to the passed value and returns the old float64 value
|
||||||
|
// atomically.
|
||||||
|
func (n *Number) SwapFloat64Atomic(f float64) float64 {
|
||||||
|
return internal.RawToFloat64(atomic.SwapUint64(n.AsRawPtr(), internal.Float64ToRaw(f)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// - add
|
||||||
|
|
||||||
|
// AddNumber assumes that this and the passed number are of the passed
|
||||||
|
// kind and adds the passed number to this number.
|
||||||
|
func (n *Number) AddNumber(kind Kind, nn Number) {
|
||||||
|
switch kind {
|
||||||
|
case Int64Kind:
|
||||||
|
n.AddInt64(nn.AsInt64())
|
||||||
|
case Float64Kind:
|
||||||
|
n.AddFloat64(nn.AsFloat64())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRaw assumes that this number and the passed raw value are of the
|
||||||
|
// passed kind and adds the passed raw value to this number.
|
||||||
|
func (n *Number) AddRaw(kind Kind, r uint64) {
|
||||||
|
n.AddNumber(kind, NewNumberFromRaw(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddInt64 assumes that the number contains an int64 and adds the
|
||||||
|
// passed int64 to it.
|
||||||
|
func (n *Number) AddInt64(i int64) {
|
||||||
|
*n.AsInt64Ptr() += i
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFloat64 assumes that the number contains a float64 and adds the
|
||||||
|
// passed float64 to it.
|
||||||
|
func (n *Number) AddFloat64(f float64) {
|
||||||
|
*n.AsFloat64Ptr() += f
|
||||||
|
}
|
||||||
|
|
||||||
|
// - add atomic
|
||||||
|
|
||||||
|
// AddNumberAtomic assumes that this and the passed number are of the
|
||||||
|
// passed kind and adds the passed number to this number atomically.
|
||||||
|
func (n *Number) AddNumberAtomic(kind Kind, nn Number) {
|
||||||
|
switch kind {
|
||||||
|
case Int64Kind:
|
||||||
|
n.AddInt64Atomic(nn.AsInt64())
|
||||||
|
case Float64Kind:
|
||||||
|
n.AddFloat64Atomic(nn.AsFloat64())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRawAtomic assumes that this number and the passed raw value are
|
||||||
|
// of the passed kind and adds the passed raw value to this number
|
||||||
|
// atomically.
|
||||||
|
func (n *Number) AddRawAtomic(kind Kind, r uint64) {
|
||||||
|
n.AddNumberAtomic(kind, NewNumberFromRaw(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddInt64Atomic assumes that the number contains an int64 and adds
|
||||||
|
// the passed int64 to it atomically.
|
||||||
|
func (n *Number) AddInt64Atomic(i int64) {
|
||||||
|
atomic.AddInt64(n.AsInt64Ptr(), i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFloat64Atomic assumes that the number contains a float64 and
|
||||||
|
// adds the passed float64 to it atomically.
|
||||||
|
func (n *Number) AddFloat64Atomic(f float64) {
|
||||||
|
for {
|
||||||
|
o := n.AsFloat64Atomic()
|
||||||
|
if n.CompareAndSwapFloat64(o, o+f) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - compare and swap (atomic only)
|
||||||
|
|
||||||
|
// CompareAndSwapNumber does the atomic CAS operation on this
|
||||||
|
// number. This number and passed old and new numbers should be of the
|
||||||
|
// same kind.
|
||||||
|
func (n *Number) CompareAndSwapNumber(on, nn Number) bool {
|
||||||
|
return atomic.CompareAndSwapUint64(n.AsRawPtr(), on.AsRaw(), nn.AsRaw())
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareAndSwapRaw does the atomic CAS operation on this
|
||||||
|
// number. This number and passed old and new raw values should be of
|
||||||
|
// the same kind.
|
||||||
|
func (n *Number) CompareAndSwapRaw(or, nr uint64) bool {
|
||||||
|
return atomic.CompareAndSwapUint64(n.AsRawPtr(), or, nr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareAndSwapInt64 assumes that this number contains an int64 and
|
||||||
|
// does the atomic CAS operation on it.
|
||||||
|
func (n *Number) CompareAndSwapInt64(oi, ni int64) bool {
|
||||||
|
return atomic.CompareAndSwapInt64(n.AsInt64Ptr(), oi, ni)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareAndSwapFloat64 assumes that this number contains a float64 and
|
||||||
|
// does the atomic CAS operation on it.
|
||||||
|
func (n *Number) CompareAndSwapFloat64(of, nf float64) bool {
|
||||||
|
return atomic.CompareAndSwapUint64(n.AsRawPtr(), internal.Float64ToRaw(of), internal.Float64ToRaw(nf))
|
||||||
|
}
|
||||||
|
|
||||||
|
// - compare
|
||||||
|
|
||||||
|
// CompareNumber compares two Numbers given their kind. Both numbers
|
||||||
|
// should have the same kind. This returns:
|
||||||
|
// 0 if the numbers are equal
|
||||||
|
// -1 if the subject `n` is less than the argument `nn`
|
||||||
|
// +1 if the subject `n` is greater than the argument `nn`
|
||||||
|
func (n *Number) CompareNumber(kind Kind, nn Number) int {
|
||||||
|
switch kind {
|
||||||
|
case Int64Kind:
|
||||||
|
return n.CompareInt64(nn.AsInt64())
|
||||||
|
case Float64Kind:
|
||||||
|
return n.CompareFloat64(nn.AsFloat64())
|
||||||
|
default:
|
||||||
|
// you get what you deserve
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareRaw compares two numbers, where one is input as a raw
|
||||||
|
// uint64, interpreting both values as a `kind` of number.
|
||||||
|
func (n *Number) CompareRaw(kind Kind, r uint64) int {
|
||||||
|
return n.CompareNumber(kind, NewNumberFromRaw(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareInt64 assumes that the Number contains an int64 and performs
|
||||||
|
// a comparison between the value and the other value. It returns the
|
||||||
|
// typical result of the compare function: -1 if the value is less
|
||||||
|
// than the other, 0 if both are equal, 1 if the value is greater than
|
||||||
|
// the other.
|
||||||
|
func (n *Number) CompareInt64(i int64) int {
|
||||||
|
this := n.AsInt64()
|
||||||
|
if this < i {
|
||||||
|
return -1
|
||||||
|
} else if this > i {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareFloat64 assumes that the Number contains a float64 and
|
||||||
|
// performs a comparison between the value and the other value. It
|
||||||
|
// returns the typical result of the compare function: -1 if the value
|
||||||
|
// is less than the other, 0 if both are equal, 1 if the value is
|
||||||
|
// greater than the other.
|
||||||
|
//
|
||||||
|
// Do not compare NaN values.
|
||||||
|
func (n *Number) CompareFloat64(f float64) int {
|
||||||
|
this := n.AsFloat64()
|
||||||
|
if this < f {
|
||||||
|
return -1
|
||||||
|
} else if this > f {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// - relations to zero
|
||||||
|
|
||||||
|
// IsPositive returns true if the actual value is greater than zero.
|
||||||
|
func (n *Number) IsPositive(kind Kind) bool {
|
||||||
|
return n.compareWithZero(kind) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNegative returns true if the actual value is less than zero.
|
||||||
|
func (n *Number) IsNegative(kind Kind) bool {
|
||||||
|
return n.compareWithZero(kind) < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZero returns true if the actual value is equal to zero.
|
||||||
|
func (n *Number) IsZero(kind Kind) bool {
|
||||||
|
return n.compareWithZero(kind) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// - misc
|
||||||
|
|
||||||
|
// Emit returns a string representation of the raw value of the
|
||||||
|
// Number. A %d is used for integral values, %f for floating point
|
||||||
|
// values.
|
||||||
|
func (n *Number) Emit(kind Kind) string {
|
||||||
|
switch kind {
|
||||||
|
case Int64Kind:
|
||||||
|
return fmt.Sprintf("%d", n.AsInt64())
|
||||||
|
case Float64Kind:
|
||||||
|
return fmt.Sprintf("%f", n.AsFloat64())
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsInterface returns the number as an interface{}, typically used
|
||||||
|
// for Kind-correct JSON conversion.
|
||||||
|
func (n *Number) AsInterface(kind Kind) interface{} {
|
||||||
|
switch kind {
|
||||||
|
case Int64Kind:
|
||||||
|
return n.AsInt64()
|
||||||
|
case Float64Kind:
|
||||||
|
return n.AsFloat64()
|
||||||
|
default:
|
||||||
|
return math.NaN()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - private stuff
|
||||||
|
|
||||||
|
func (n *Number) compareWithZero(kind Kind) int {
|
||||||
|
switch kind {
|
||||||
|
case Int64Kind:
|
||||||
|
return n.CompareInt64(0)
|
||||||
|
case Float64Kind:
|
||||||
|
return n.CompareFloat64(0.)
|
||||||
|
default:
|
||||||
|
// you get what you deserve
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
70
vendor/go.opentelemetry.io/otel/metric/sdkapi/descriptor.go
generated
vendored
Normal file
70
vendor/go.opentelemetry.io/otel/metric/sdkapi/descriptor.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
// Copyright The 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 sdkapi // import "go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/unit"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Descriptor contains all the settings that describe an instrument,
|
||||||
|
// including its name, metric kind, number kind, and the configurable
|
||||||
|
// options.
|
||||||
|
type Descriptor struct {
|
||||||
|
name string
|
||||||
|
instrumentKind InstrumentKind
|
||||||
|
numberKind number.Kind
|
||||||
|
description string
|
||||||
|
unit unit.Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDescriptor returns a Descriptor with the given contents.
|
||||||
|
func NewDescriptor(name string, ikind InstrumentKind, nkind number.Kind, description string, unit unit.Unit) Descriptor {
|
||||||
|
return Descriptor{
|
||||||
|
name: name,
|
||||||
|
instrumentKind: ikind,
|
||||||
|
numberKind: nkind,
|
||||||
|
description: description,
|
||||||
|
unit: unit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the metric instrument's name.
|
||||||
|
func (d Descriptor) Name() string {
|
||||||
|
return d.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstrumentKind returns the specific kind of instrument.
|
||||||
|
func (d Descriptor) InstrumentKind() InstrumentKind {
|
||||||
|
return d.instrumentKind
|
||||||
|
}
|
||||||
|
|
||||||
|
// Description provides a human-readable description of the metric
|
||||||
|
// instrument.
|
||||||
|
func (d Descriptor) Description() string {
|
||||||
|
return d.description
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unit describes the units of the metric instrument. Unitless
|
||||||
|
// metrics return the empty string.
|
||||||
|
func (d Descriptor) Unit() unit.Unit {
|
||||||
|
return d.unit
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumberKind returns whether this instrument is declared over int64,
|
||||||
|
// float64, or uint64 values.
|
||||||
|
func (d Descriptor) NumberKind() number.Kind {
|
||||||
|
return d.numberKind
|
||||||
|
}
|
||||||
80
vendor/go.opentelemetry.io/otel/metric/sdkapi/instrumentkind.go
generated
vendored
Normal file
80
vendor/go.opentelemetry.io/otel/metric/sdkapi/instrumentkind.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// Copyright The 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.
|
||||||
|
|
||||||
|
//go:generate stringer -type=InstrumentKind
|
||||||
|
|
||||||
|
package sdkapi // import "go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
|
||||||
|
// InstrumentKind describes the kind of instrument.
|
||||||
|
type InstrumentKind int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
// HistogramInstrumentKind indicates a Histogram instrument.
|
||||||
|
HistogramInstrumentKind InstrumentKind = iota
|
||||||
|
// GaugeObserverInstrumentKind indicates an GaugeObserver instrument.
|
||||||
|
GaugeObserverInstrumentKind
|
||||||
|
|
||||||
|
// CounterInstrumentKind indicates a Counter instrument.
|
||||||
|
CounterInstrumentKind
|
||||||
|
// UpDownCounterInstrumentKind indicates a UpDownCounter instrument.
|
||||||
|
UpDownCounterInstrumentKind
|
||||||
|
|
||||||
|
// CounterObserverInstrumentKind indicates a CounterObserver instrument.
|
||||||
|
CounterObserverInstrumentKind
|
||||||
|
// UpDownCounterObserverInstrumentKind indicates a UpDownCounterObserver
|
||||||
|
// instrument.
|
||||||
|
UpDownCounterObserverInstrumentKind
|
||||||
|
)
|
||||||
|
|
||||||
|
// Synchronous returns whether this is a synchronous kind of instrument.
|
||||||
|
func (k InstrumentKind) Synchronous() bool {
|
||||||
|
switch k {
|
||||||
|
case CounterInstrumentKind, UpDownCounterInstrumentKind, HistogramInstrumentKind:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Asynchronous returns whether this is an asynchronous kind of instrument.
|
||||||
|
func (k InstrumentKind) Asynchronous() bool {
|
||||||
|
return !k.Synchronous()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding returns whether this kind of instrument adds its inputs (as opposed to Grouping).
|
||||||
|
func (k InstrumentKind) Adding() bool {
|
||||||
|
switch k {
|
||||||
|
case CounterInstrumentKind, UpDownCounterInstrumentKind, CounterObserverInstrumentKind, UpDownCounterObserverInstrumentKind:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grouping returns whether this kind of instrument groups its inputs (as opposed to Adding).
|
||||||
|
func (k InstrumentKind) Grouping() bool {
|
||||||
|
return !k.Adding()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monotonic returns whether this kind of instrument exposes a non-decreasing sum.
|
||||||
|
func (k InstrumentKind) Monotonic() bool {
|
||||||
|
switch k {
|
||||||
|
case CounterInstrumentKind, CounterObserverInstrumentKind:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrecomputedSum returns whether this kind of instrument receives precomputed sums.
|
||||||
|
func (k InstrumentKind) PrecomputedSum() bool {
|
||||||
|
return k.Adding() && k.Asynchronous()
|
||||||
|
}
|
||||||
28
vendor/go.opentelemetry.io/otel/metric/sdkapi/instrumentkind_string.go
generated
vendored
Normal file
28
vendor/go.opentelemetry.io/otel/metric/sdkapi/instrumentkind_string.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Code generated by "stringer -type=InstrumentKind"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package sdkapi
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[HistogramInstrumentKind-0]
|
||||||
|
_ = x[GaugeObserverInstrumentKind-1]
|
||||||
|
_ = x[CounterInstrumentKind-2]
|
||||||
|
_ = x[UpDownCounterInstrumentKind-3]
|
||||||
|
_ = x[CounterObserverInstrumentKind-4]
|
||||||
|
_ = x[UpDownCounterObserverInstrumentKind-5]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _InstrumentKind_name = "HistogramInstrumentKindGaugeObserverInstrumentKindCounterInstrumentKindUpDownCounterInstrumentKindCounterObserverInstrumentKindUpDownCounterObserverInstrumentKind"
|
||||||
|
|
||||||
|
var _InstrumentKind_index = [...]uint8{0, 23, 50, 71, 98, 127, 162}
|
||||||
|
|
||||||
|
func (i InstrumentKind) String() string {
|
||||||
|
if i < 0 || i >= InstrumentKind(len(_InstrumentKind_index)-1) {
|
||||||
|
return "InstrumentKind(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _InstrumentKind_name[_InstrumentKind_index[i]:_InstrumentKind_index[i+1]]
|
||||||
|
}
|
||||||
64
vendor/go.opentelemetry.io/otel/metric/sdkapi/noop.go
generated
vendored
Normal file
64
vendor/go.opentelemetry.io/otel/metric/sdkapi/noop.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// Copyright The 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 sdkapi // import "go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
)
|
||||||
|
|
||||||
|
type noopInstrument struct{}
|
||||||
|
type noopBoundInstrument struct{}
|
||||||
|
type noopSyncInstrument struct{ noopInstrument }
|
||||||
|
type noopAsyncInstrument struct{ noopInstrument }
|
||||||
|
|
||||||
|
var _ SyncImpl = noopSyncInstrument{}
|
||||||
|
var _ BoundSyncImpl = noopBoundInstrument{}
|
||||||
|
var _ AsyncImpl = noopAsyncInstrument{}
|
||||||
|
|
||||||
|
// NewNoopSyncInstrument returns a No-op implementation of the
|
||||||
|
// synchronous instrument interface.
|
||||||
|
func NewNoopSyncInstrument() SyncImpl {
|
||||||
|
return noopSyncInstrument{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNoopAsyncInstrument returns a No-op implementation of the
|
||||||
|
// asynchronous instrument interface.
|
||||||
|
func NewNoopAsyncInstrument() AsyncImpl {
|
||||||
|
return noopAsyncInstrument{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (noopInstrument) Implementation() interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (noopInstrument) Descriptor() Descriptor {
|
||||||
|
return Descriptor{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (noopBoundInstrument) RecordOne(context.Context, number.Number) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (noopBoundInstrument) Unbind() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (noopSyncInstrument) Bind([]attribute.KeyValue) BoundSyncImpl {
|
||||||
|
return noopBoundInstrument{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (noopSyncInstrument) RecordOne(context.Context, number.Number, []attribute.KeyValue) {
|
||||||
|
}
|
||||||
175
vendor/go.opentelemetry.io/otel/metric/sdkapi/sdkapi.go
generated
vendored
Normal file
175
vendor/go.opentelemetry.io/otel/metric/sdkapi/sdkapi.go
generated
vendored
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
// Copyright The 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 sdkapi // import "go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MeterImpl is the interface an SDK must implement to supply a Meter
|
||||||
|
// implementation.
|
||||||
|
type MeterImpl interface {
|
||||||
|
// RecordBatch atomically records a batch of measurements.
|
||||||
|
RecordBatch(ctx context.Context, labels []attribute.KeyValue, measurement ...Measurement)
|
||||||
|
|
||||||
|
// NewSyncInstrument returns a newly constructed
|
||||||
|
// synchronous instrument implementation or an error, should
|
||||||
|
// one occur.
|
||||||
|
NewSyncInstrument(descriptor Descriptor) (SyncImpl, error)
|
||||||
|
|
||||||
|
// NewAsyncInstrument returns a newly constructed
|
||||||
|
// asynchronous instrument implementation or an error, should
|
||||||
|
// one occur.
|
||||||
|
NewAsyncInstrument(
|
||||||
|
descriptor Descriptor,
|
||||||
|
runner AsyncRunner,
|
||||||
|
) (AsyncImpl, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstrumentImpl is a common interface for synchronous and
|
||||||
|
// asynchronous instruments.
|
||||||
|
type InstrumentImpl interface {
|
||||||
|
// Implementation returns the underlying implementation of the
|
||||||
|
// instrument, which allows the implementation to gain access
|
||||||
|
// to its own representation especially from a `Measurement`.
|
||||||
|
Implementation() interface{}
|
||||||
|
|
||||||
|
// Descriptor returns a copy of the instrument's Descriptor.
|
||||||
|
Descriptor() Descriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncImpl is the implementation-level interface to a generic
|
||||||
|
// synchronous instrument (e.g., Histogram and Counter instruments).
|
||||||
|
type SyncImpl interface {
|
||||||
|
InstrumentImpl
|
||||||
|
|
||||||
|
// Bind creates an implementation-level bound instrument,
|
||||||
|
// binding a label set with this instrument implementation.
|
||||||
|
Bind(labels []attribute.KeyValue) BoundSyncImpl
|
||||||
|
|
||||||
|
// RecordOne captures a single synchronous metric event.
|
||||||
|
RecordOne(ctx context.Context, number number.Number, labels []attribute.KeyValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoundSyncImpl is the implementation-level interface to a
|
||||||
|
// generic bound synchronous instrument
|
||||||
|
type BoundSyncImpl interface {
|
||||||
|
|
||||||
|
// RecordOne captures a single synchronous metric event.
|
||||||
|
RecordOne(ctx context.Context, number number.Number)
|
||||||
|
|
||||||
|
// Unbind frees the resources associated with this bound instrument. It
|
||||||
|
// does not affect the metric this bound instrument was created through.
|
||||||
|
Unbind()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncImpl is an implementation-level interface to an
|
||||||
|
// asynchronous instrument (e.g., Observer instruments).
|
||||||
|
type AsyncImpl interface {
|
||||||
|
InstrumentImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncRunner is expected to convert into an AsyncSingleRunner or an
|
||||||
|
// AsyncBatchRunner. SDKs will encounter an error if the AsyncRunner
|
||||||
|
// does not satisfy one of these interfaces.
|
||||||
|
type AsyncRunner interface {
|
||||||
|
// AnyRunner() is a non-exported method with no functional use
|
||||||
|
// other than to make this a non-empty interface.
|
||||||
|
AnyRunner()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncSingleRunner is an interface implemented by single-observer
|
||||||
|
// callbacks.
|
||||||
|
type AsyncSingleRunner interface {
|
||||||
|
// Run accepts a single instrument and function for capturing
|
||||||
|
// observations of that instrument. Each call to the function
|
||||||
|
// receives one captured observation. (The function accepts
|
||||||
|
// multiple observations so the same implementation can be
|
||||||
|
// used for batch runners.)
|
||||||
|
Run(ctx context.Context, single AsyncImpl, capture func([]attribute.KeyValue, ...Observation))
|
||||||
|
|
||||||
|
AsyncRunner
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncBatchRunner is an interface implemented by batch-observer
|
||||||
|
// callbacks.
|
||||||
|
type AsyncBatchRunner interface {
|
||||||
|
// Run accepts a function for capturing observations of
|
||||||
|
// multiple instruments.
|
||||||
|
Run(ctx context.Context, capture func([]attribute.KeyValue, ...Observation))
|
||||||
|
|
||||||
|
AsyncRunner
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMeasurement constructs a single observation, a binding between
|
||||||
|
// an asynchronous instrument and a number.
|
||||||
|
func NewMeasurement(instrument SyncImpl, number number.Number) Measurement {
|
||||||
|
return Measurement{
|
||||||
|
instrument: instrument,
|
||||||
|
number: number,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measurement is a low-level type used with synchronous instruments
|
||||||
|
// as a direct interface to the SDK via `RecordBatch`.
|
||||||
|
type Measurement struct {
|
||||||
|
// number needs to be aligned for 64-bit atomic operations.
|
||||||
|
number number.Number
|
||||||
|
instrument SyncImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncImpl returns the instrument that created this measurement.
|
||||||
|
// This returns an implementation-level object for use by the SDK,
|
||||||
|
// users should not refer to this.
|
||||||
|
func (m Measurement) SyncImpl() SyncImpl {
|
||||||
|
return m.instrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number returns a number recorded in this measurement.
|
||||||
|
func (m Measurement) Number() number.Number {
|
||||||
|
return m.number
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewObservation constructs a single observation, a binding between
|
||||||
|
// an asynchronous instrument and a number.
|
||||||
|
func NewObservation(instrument AsyncImpl, number number.Number) Observation {
|
||||||
|
return Observation{
|
||||||
|
instrument: instrument,
|
||||||
|
number: number,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observation is a low-level type used with asynchronous instruments
|
||||||
|
// as a direct interface to the SDK via `BatchObserver`.
|
||||||
|
type Observation struct {
|
||||||
|
// number needs to be aligned for 64-bit atomic operations.
|
||||||
|
number number.Number
|
||||||
|
instrument AsyncImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncImpl returns the instrument that created this observation.
|
||||||
|
// This returns an implementation-level object for use by the SDK,
|
||||||
|
// users should not refer to this.
|
||||||
|
func (m Observation) AsyncImpl() AsyncImpl {
|
||||||
|
return m.instrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number returns a number recorded in this observation.
|
||||||
|
func (m Observation) Number() number.Number {
|
||||||
|
return m.number
|
||||||
|
}
|
||||||
20
vendor/go.opentelemetry.io/otel/metric/unit/doc.go
generated
vendored
Normal file
20
vendor/go.opentelemetry.io/otel/metric/unit/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright The 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 unit provides units.
|
||||||
|
//
|
||||||
|
// This package is currently in a pre-GA phase. Backwards incompatible changes
|
||||||
|
// may be introduced in subsequent minor version releases as we work to track
|
||||||
|
// the evolving OpenTelemetry specification and user feedback.
|
||||||
|
package unit // import "go.opentelemetry.io/otel/metric/unit"
|
||||||
24
vendor/go.opentelemetry.io/otel/metric/unit/unit.go
generated
vendored
Normal file
24
vendor/go.opentelemetry.io/otel/metric/unit/unit.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright The 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 unit // import "go.opentelemetry.io/otel/metric/unit"
|
||||||
|
|
||||||
|
type Unit string
|
||||||
|
|
||||||
|
// Units defined by OpenTelemetry.
|
||||||
|
const (
|
||||||
|
Dimensionless Unit = "1"
|
||||||
|
Bytes Unit = "By"
|
||||||
|
Milliseconds Unit = "ms"
|
||||||
|
)
|
||||||
95
vendor/go.opentelemetry.io/otel/pre_release.sh
generated
vendored
Normal file
95
vendor/go.opentelemetry.io/otel/pre_release.sh
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright The 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.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
help()
|
||||||
|
{
|
||||||
|
printf "\n"
|
||||||
|
printf "Usage: $0 -t tag\n"
|
||||||
|
printf "\t-t Unreleased tag. Update all go.mod with this tag.\n"
|
||||||
|
exit 1 # Exit script after printing help
|
||||||
|
}
|
||||||
|
|
||||||
|
while getopts "t:" opt
|
||||||
|
do
|
||||||
|
case "$opt" in
|
||||||
|
t ) TAG="$OPTARG" ;;
|
||||||
|
? ) help ;; # Print help
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print help in case parameters are empty
|
||||||
|
if [ -z "$TAG" ]
|
||||||
|
then
|
||||||
|
printf "Tag is missing\n";
|
||||||
|
help
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate semver
|
||||||
|
SEMVER_REGEX="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"
|
||||||
|
if [[ "${TAG}" =~ ${SEMVER_REGEX} ]]; then
|
||||||
|
printf "${TAG} is valid semver tag.\n"
|
||||||
|
else
|
||||||
|
printf "${TAG} is not a valid semver tag.\n"
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TAG_FOUND=`git tag --list ${TAG}`
|
||||||
|
if [[ ${TAG_FOUND} = ${TAG} ]] ; then
|
||||||
|
printf "Tag ${TAG} already exists\n"
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get version for version.go
|
||||||
|
OTEL_VERSION=$(echo "${TAG}" | grep -o '^v[0-9]\+\.[0-9]\+\.[0-9]\+')
|
||||||
|
# Strip leading v
|
||||||
|
OTEL_VERSION="${OTEL_VERSION#v}"
|
||||||
|
|
||||||
|
cd $(dirname $0)
|
||||||
|
|
||||||
|
if ! git diff --quiet; then \
|
||||||
|
printf "Working tree is not clean, can't proceed with the release process\n"
|
||||||
|
git status
|
||||||
|
git diff
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update version.go
|
||||||
|
cp ./version.go ./version.go.bak
|
||||||
|
sed "s/\(return \"\)[0-9]*\.[0-9]*\.[0-9]*\"/\1${OTEL_VERSION}\"/" ./version.go.bak >./version.go
|
||||||
|
rm -f ./version.go.bak
|
||||||
|
|
||||||
|
# Update go.mod
|
||||||
|
git checkout -b pre_release_${TAG} main
|
||||||
|
PACKAGE_DIRS=$(find . -mindepth 2 -type f -name 'go.mod' -exec dirname {} \; | egrep -v 'tools' | sed 's/^\.\///' | sort)
|
||||||
|
|
||||||
|
for dir in $PACKAGE_DIRS; do
|
||||||
|
cp "${dir}/go.mod" "${dir}/go.mod.bak"
|
||||||
|
sed "s/opentelemetry.io\/otel\([^ ]*\) v[0-9]*\.[0-9]*\.[0-9]/opentelemetry.io\/otel\1 ${TAG}/" "${dir}/go.mod.bak" >"${dir}/go.mod"
|
||||||
|
rm -f "${dir}/go.mod.bak"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Run lint to update go.sum
|
||||||
|
make lint
|
||||||
|
|
||||||
|
# Add changes and commit.
|
||||||
|
git add .
|
||||||
|
make ci
|
||||||
|
git commit -m "Prepare for releasing $TAG"
|
||||||
|
|
||||||
|
printf "Now run following to verify the changes.\ngit diff main\n"
|
||||||
|
printf "\nThen push the changes to upstream\n"
|
||||||
31
vendor/go.opentelemetry.io/otel/propagation.go
generated
vendored
Normal file
31
vendor/go.opentelemetry.io/otel/propagation.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright The 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 otel // import "go.opentelemetry.io/otel"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.opentelemetry.io/otel/internal/global"
|
||||||
|
"go.opentelemetry.io/otel/propagation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetTextMapPropagator returns the global TextMapPropagator. If none has been
|
||||||
|
// set, a No-Op TextMapPropagator is returned.
|
||||||
|
func GetTextMapPropagator() propagation.TextMapPropagator {
|
||||||
|
return global.TextMapPropagator()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTextMapPropagator sets propagator as the global TextMapPropagator.
|
||||||
|
func SetTextMapPropagator(propagator propagation.TextMapPropagator) {
|
||||||
|
global.SetTextMapPropagator(propagator)
|
||||||
|
}
|
||||||
58
vendor/go.opentelemetry.io/otel/propagation/baggage.go
generated
vendored
Normal file
58
vendor/go.opentelemetry.io/otel/propagation/baggage.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// Copyright The 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 propagation // import "go.opentelemetry.io/otel/propagation"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/baggage"
|
||||||
|
)
|
||||||
|
|
||||||
|
const baggageHeader = "baggage"
|
||||||
|
|
||||||
|
// Baggage is a propagator that supports the W3C Baggage format.
|
||||||
|
//
|
||||||
|
// This propagates user-defined baggage associated with a trace. The complete
|
||||||
|
// specification is defined at https://w3c.github.io/baggage/.
|
||||||
|
type Baggage struct{}
|
||||||
|
|
||||||
|
var _ TextMapPropagator = Baggage{}
|
||||||
|
|
||||||
|
// Inject sets baggage key-values from ctx into the carrier.
|
||||||
|
func (b Baggage) Inject(ctx context.Context, carrier TextMapCarrier) {
|
||||||
|
bStr := baggage.FromContext(ctx).String()
|
||||||
|
if bStr != "" {
|
||||||
|
carrier.Set(baggageHeader, bStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract returns a copy of parent with the baggage from the carrier added.
|
||||||
|
func (b Baggage) Extract(parent context.Context, carrier TextMapCarrier) context.Context {
|
||||||
|
bStr := carrier.Get(baggageHeader)
|
||||||
|
if bStr == "" {
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
|
||||||
|
bag, err := baggage.Parse(bStr)
|
||||||
|
if err != nil {
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
return baggage.ContextWithBaggage(parent, bag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fields returns the keys who's values are set with Inject.
|
||||||
|
func (b Baggage) Fields() []string {
|
||||||
|
return []string{baggageHeader}
|
||||||
|
}
|
||||||
24
vendor/go.opentelemetry.io/otel/propagation/doc.go
generated
vendored
Normal file
24
vendor/go.opentelemetry.io/otel/propagation/doc.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright The 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 propagation contains OpenTelemetry context propagators.
|
||||||
|
|
||||||
|
OpenTelemetry propagators are used to extract and inject context data from and
|
||||||
|
into messages exchanged by applications. The propagator supported by this
|
||||||
|
package is the W3C Trace Context encoding
|
||||||
|
(https://www.w3.org/TR/trace-context/), and W3C Baggage
|
||||||
|
(https://w3c.github.io/baggage/).
|
||||||
|
*/
|
||||||
|
package propagation // import "go.opentelemetry.io/otel/propagation"
|
||||||
153
vendor/go.opentelemetry.io/otel/propagation/propagation.go
generated
vendored
Normal file
153
vendor/go.opentelemetry.io/otel/propagation/propagation.go
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
// Copyright The 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 propagation // import "go.opentelemetry.io/otel/propagation"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TextMapCarrier is the storage medium used by a TextMapPropagator.
|
||||||
|
type TextMapCarrier interface {
|
||||||
|
// DO NOT CHANGE: any modification will not be backwards compatible and
|
||||||
|
// must never be done outside of a new major release.
|
||||||
|
|
||||||
|
// Get returns the value associated with the passed key.
|
||||||
|
Get(key string) string
|
||||||
|
// DO NOT CHANGE: any modification will not be backwards compatible and
|
||||||
|
// must never be done outside of a new major release.
|
||||||
|
|
||||||
|
// Set stores the key-value pair.
|
||||||
|
Set(key string, value string)
|
||||||
|
// DO NOT CHANGE: any modification will not be backwards compatible and
|
||||||
|
// must never be done outside of a new major release.
|
||||||
|
|
||||||
|
// Keys lists the keys stored in this carrier.
|
||||||
|
Keys() []string
|
||||||
|
// DO NOT CHANGE: any modification will not be backwards compatible and
|
||||||
|
// must never be done outside of a new major release.
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapCarrier is a TextMapCarrier that uses a map held in memory as a storage
|
||||||
|
// medium for propagated key-value pairs.
|
||||||
|
type MapCarrier map[string]string
|
||||||
|
|
||||||
|
// Compile time check that MapCarrier implements the TextMapCarrier.
|
||||||
|
var _ TextMapCarrier = MapCarrier{}
|
||||||
|
|
||||||
|
// Get returns the value associated with the passed key.
|
||||||
|
func (c MapCarrier) Get(key string) string {
|
||||||
|
return c[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set stores the key-value pair.
|
||||||
|
func (c MapCarrier) Set(key, value string) {
|
||||||
|
c[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys lists the keys stored in this carrier.
|
||||||
|
func (c MapCarrier) Keys() []string {
|
||||||
|
keys := make([]string, 0, len(c))
|
||||||
|
for k := range c {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeaderCarrier adapts http.Header to satisfy the TextMapCarrier interface.
|
||||||
|
type HeaderCarrier http.Header
|
||||||
|
|
||||||
|
// Get returns the value associated with the passed key.
|
||||||
|
func (hc HeaderCarrier) Get(key string) string {
|
||||||
|
return http.Header(hc).Get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set stores the key-value pair.
|
||||||
|
func (hc HeaderCarrier) Set(key string, value string) {
|
||||||
|
http.Header(hc).Set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys lists the keys stored in this carrier.
|
||||||
|
func (hc HeaderCarrier) Keys() []string {
|
||||||
|
keys := make([]string, 0, len(hc))
|
||||||
|
for k := range hc {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextMapPropagator propagates cross-cutting concerns as key-value text
|
||||||
|
// pairs within a carrier that travels in-band across process boundaries.
|
||||||
|
type TextMapPropagator interface {
|
||||||
|
// DO NOT CHANGE: any modification will not be backwards compatible and
|
||||||
|
// must never be done outside of a new major release.
|
||||||
|
|
||||||
|
// Inject set cross-cutting concerns from the Context into the carrier.
|
||||||
|
Inject(ctx context.Context, carrier TextMapCarrier)
|
||||||
|
// DO NOT CHANGE: any modification will not be backwards compatible and
|
||||||
|
// must never be done outside of a new major release.
|
||||||
|
|
||||||
|
// Extract reads cross-cutting concerns from the carrier into a Context.
|
||||||
|
Extract(ctx context.Context, carrier TextMapCarrier) context.Context
|
||||||
|
// DO NOT CHANGE: any modification will not be backwards compatible and
|
||||||
|
// must never be done outside of a new major release.
|
||||||
|
|
||||||
|
// Fields returns the keys whose values are set with Inject.
|
||||||
|
Fields() []string
|
||||||
|
// DO NOT CHANGE: any modification will not be backwards compatible and
|
||||||
|
// must never be done outside of a new major release.
|
||||||
|
}
|
||||||
|
|
||||||
|
type compositeTextMapPropagator []TextMapPropagator
|
||||||
|
|
||||||
|
func (p compositeTextMapPropagator) Inject(ctx context.Context, carrier TextMapCarrier) {
|
||||||
|
for _, i := range p {
|
||||||
|
i.Inject(ctx, carrier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p compositeTextMapPropagator) Extract(ctx context.Context, carrier TextMapCarrier) context.Context {
|
||||||
|
for _, i := range p {
|
||||||
|
ctx = i.Extract(ctx, carrier)
|
||||||
|
}
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p compositeTextMapPropagator) Fields() []string {
|
||||||
|
unique := make(map[string]struct{})
|
||||||
|
for _, i := range p {
|
||||||
|
for _, k := range i.Fields() {
|
||||||
|
unique[k] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := make([]string, 0, len(unique))
|
||||||
|
for k := range unique {
|
||||||
|
fields = append(fields, k)
|
||||||
|
}
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCompositeTextMapPropagator returns a unified TextMapPropagator from the
|
||||||
|
// group of passed TextMapPropagator. This allows different cross-cutting
|
||||||
|
// concerns to be propagates in a unified manner.
|
||||||
|
//
|
||||||
|
// The returned TextMapPropagator will inject and extract cross-cutting
|
||||||
|
// concerns in the order the TextMapPropagators were provided. Additionally,
|
||||||
|
// the Fields method will return a de-duplicated slice of the keys that are
|
||||||
|
// set with the Inject method.
|
||||||
|
func NewCompositeTextMapPropagator(p ...TextMapPropagator) TextMapPropagator {
|
||||||
|
return compositeTextMapPropagator(p)
|
||||||
|
}
|
||||||
159
vendor/go.opentelemetry.io/otel/propagation/trace_context.go
generated
vendored
Normal file
159
vendor/go.opentelemetry.io/otel/propagation/trace_context.go
generated
vendored
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
// Copyright The 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 propagation // import "go.opentelemetry.io/otel/propagation"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
supportedVersion = 0
|
||||||
|
maxVersion = 254
|
||||||
|
traceparentHeader = "traceparent"
|
||||||
|
tracestateHeader = "tracestate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TraceContext is a propagator that supports the W3C Trace Context format
|
||||||
|
// (https://www.w3.org/TR/trace-context/)
|
||||||
|
//
|
||||||
|
// This propagator will propagate the traceparent and tracestate headers to
|
||||||
|
// guarantee traces are not broken. It is up to the users of this propagator
|
||||||
|
// to choose if they want to participate in a trace by modifying the
|
||||||
|
// traceparent header and relevant parts of the tracestate header containing
|
||||||
|
// their proprietary information.
|
||||||
|
type TraceContext struct{}
|
||||||
|
|
||||||
|
var _ TextMapPropagator = TraceContext{}
|
||||||
|
var traceCtxRegExp = regexp.MustCompile("^(?P<version>[0-9a-f]{2})-(?P<traceID>[a-f0-9]{32})-(?P<spanID>[a-f0-9]{16})-(?P<traceFlags>[a-f0-9]{2})(?:-.*)?$")
|
||||||
|
|
||||||
|
// Inject set tracecontext from the Context into the carrier.
|
||||||
|
func (tc TraceContext) Inject(ctx context.Context, carrier TextMapCarrier) {
|
||||||
|
sc := trace.SpanContextFromContext(ctx)
|
||||||
|
if !sc.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ts := sc.TraceState().String(); ts != "" {
|
||||||
|
carrier.Set(tracestateHeader, ts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all flags other than the trace-context supported sampling bit.
|
||||||
|
flags := sc.TraceFlags() & trace.FlagsSampled
|
||||||
|
|
||||||
|
h := fmt.Sprintf("%.2x-%s-%s-%s",
|
||||||
|
supportedVersion,
|
||||||
|
sc.TraceID(),
|
||||||
|
sc.SpanID(),
|
||||||
|
flags)
|
||||||
|
carrier.Set(traceparentHeader, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract reads tracecontext from the carrier into a returned Context.
|
||||||
|
//
|
||||||
|
// The returned Context will be a copy of ctx and contain the extracted
|
||||||
|
// tracecontext as the remote SpanContext. If the extracted tracecontext is
|
||||||
|
// invalid, the passed ctx will be returned directly instead.
|
||||||
|
func (tc TraceContext) Extract(ctx context.Context, carrier TextMapCarrier) context.Context {
|
||||||
|
sc := tc.extract(carrier)
|
||||||
|
if !sc.IsValid() {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
return trace.ContextWithRemoteSpanContext(ctx, sc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tc TraceContext) extract(carrier TextMapCarrier) trace.SpanContext {
|
||||||
|
h := carrier.Get(traceparentHeader)
|
||||||
|
if h == "" {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := traceCtxRegExp.FindStringSubmatch(h)
|
||||||
|
|
||||||
|
if len(matches) == 0 {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(matches) < 5 { // four subgroups plus the overall match
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(matches[1]) != 2 {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
ver, err := hex.DecodeString(matches[1])
|
||||||
|
if err != nil {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
version := int(ver[0])
|
||||||
|
if version > maxVersion {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if version == 0 && len(matches) != 5 { // four subgroups plus the overall match
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(matches[2]) != 32 {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var scc trace.SpanContextConfig
|
||||||
|
|
||||||
|
scc.TraceID, err = trace.TraceIDFromHex(matches[2][:32])
|
||||||
|
if err != nil {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(matches[3]) != 16 {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
scc.SpanID, err = trace.SpanIDFromHex(matches[3])
|
||||||
|
if err != nil {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(matches[4]) != 2 {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
opts, err := hex.DecodeString(matches[4])
|
||||||
|
if err != nil || len(opts) < 1 || (version == 0 && opts[0] > 2) {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
// Clear all flags other than the trace-context supported sampling bit.
|
||||||
|
scc.TraceFlags = trace.TraceFlags(opts[0]) & trace.FlagsSampled
|
||||||
|
|
||||||
|
// Ignore the error returned here. Failure to parse tracestate MUST NOT
|
||||||
|
// affect the parsing of traceparent according to the W3C tracecontext
|
||||||
|
// specification.
|
||||||
|
scc.TraceState, _ = trace.ParseTraceState(carrier.Get(tracestateHeader))
|
||||||
|
scc.Remote = true
|
||||||
|
|
||||||
|
sc := trace.NewSpanContext(scc)
|
||||||
|
if !sc.IsValid() {
|
||||||
|
return trace.SpanContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fields returns the keys who's values are set with Inject.
|
||||||
|
func (tc TraceContext) Fields() []string {
|
||||||
|
return []string{traceparentHeader, tracestateHeader}
|
||||||
|
}
|
||||||
201
vendor/go.opentelemetry.io/otel/sdk/LICENSE
generated
vendored
Normal file
201
vendor/go.opentelemetry.io/otel/sdk/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
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.
|
||||||
201
vendor/go.opentelemetry.io/otel/sdk/export/metric/LICENSE
generated
vendored
Normal file
201
vendor/go.opentelemetry.io/otel/sdk/export/metric/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
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.
|
||||||
156
vendor/go.opentelemetry.io/otel/sdk/export/metric/aggregation/aggregation.go
generated
vendored
Normal file
156
vendor/go.opentelemetry.io/otel/sdk/export/metric/aggregation/aggregation.go
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// Copyright The 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 aggregation // import "go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
)
|
||||||
|
|
||||||
|
// These interfaces describe the various ways to access state from an
|
||||||
|
// Aggregation.
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Aggregation is an interface returned by the Aggregator
|
||||||
|
// containing an interval of metric data.
|
||||||
|
Aggregation interface {
|
||||||
|
// Kind returns a short identifying string to identify
|
||||||
|
// the Aggregator that was used to produce the
|
||||||
|
// Aggregation (e.g., "Sum").
|
||||||
|
Kind() Kind
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum returns an aggregated sum.
|
||||||
|
Sum interface {
|
||||||
|
Aggregation
|
||||||
|
Sum() (number.Number, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count returns the number of values that were aggregated.
|
||||||
|
Count interface {
|
||||||
|
Aggregation
|
||||||
|
Count() (uint64, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Min returns the minimum value over the set of values that were aggregated.
|
||||||
|
Min interface {
|
||||||
|
Aggregation
|
||||||
|
Min() (number.Number, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max returns the maximum value over the set of values that were aggregated.
|
||||||
|
Max interface {
|
||||||
|
Aggregation
|
||||||
|
Max() (number.Number, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastValue returns the latest value that was aggregated.
|
||||||
|
LastValue interface {
|
||||||
|
Aggregation
|
||||||
|
LastValue() (number.Number, time.Time, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Points returns the raw values that were aggregated.
|
||||||
|
Points interface {
|
||||||
|
Aggregation
|
||||||
|
|
||||||
|
// Points returns points in the order they were
|
||||||
|
// recorded. Points are approximately ordered by
|
||||||
|
// timestamp, but this is not guaranteed.
|
||||||
|
Points() ([]Point, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Point is a raw data point, consisting of a number and value.
|
||||||
|
Point struct {
|
||||||
|
number.Number
|
||||||
|
time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buckets represents histogram buckets boundaries and counts.
|
||||||
|
//
|
||||||
|
// For a Histogram with N defined boundaries, e.g, [x, y, z].
|
||||||
|
// There are N+1 counts: [-inf, x), [x, y), [y, z), [z, +inf]
|
||||||
|
Buckets struct {
|
||||||
|
// Boundaries are floating point numbers, even when
|
||||||
|
// aggregating integers.
|
||||||
|
Boundaries []float64
|
||||||
|
|
||||||
|
// Counts holds the count in each bucket.
|
||||||
|
Counts []uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Histogram returns the count of events in pre-determined buckets.
|
||||||
|
Histogram interface {
|
||||||
|
Aggregation
|
||||||
|
Count() (uint64, error)
|
||||||
|
Sum() (number.Number, error)
|
||||||
|
Histogram() (Buckets, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MinMaxSumCount supports the Min, Max, Sum, and Count interfaces.
|
||||||
|
MinMaxSumCount interface {
|
||||||
|
Aggregation
|
||||||
|
Min() (number.Number, error)
|
||||||
|
Max() (number.Number, error)
|
||||||
|
Sum() (number.Number, error)
|
||||||
|
Count() (uint64, error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Kind is a short name for the Aggregator that produces an
|
||||||
|
// Aggregation, used for descriptive purpose only. Kind is a
|
||||||
|
// string to allow user-defined Aggregators.
|
||||||
|
//
|
||||||
|
// When deciding how to handle an Aggregation, Exporters are
|
||||||
|
// encouraged to decide based on conversion to the above
|
||||||
|
// interfaces based on strength, not on Kind value, when
|
||||||
|
// deciding how to expose metric data. This enables
|
||||||
|
// user-supplied Aggregators to replace builtin Aggregators.
|
||||||
|
//
|
||||||
|
// For example, test for a Distribution before testing for a
|
||||||
|
// MinMaxSumCount, test for a Histogram before testing for a
|
||||||
|
// Sum, and so on.
|
||||||
|
Kind string
|
||||||
|
)
|
||||||
|
|
||||||
|
// Kind description constants.
|
||||||
|
const (
|
||||||
|
SumKind Kind = "Sum"
|
||||||
|
MinMaxSumCountKind Kind = "MinMaxSumCount"
|
||||||
|
HistogramKind Kind = "Histogram"
|
||||||
|
LastValueKind Kind = "Lastvalue"
|
||||||
|
ExactKind Kind = "Exact"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sentinel errors for Aggregation interface.
|
||||||
|
var (
|
||||||
|
ErrNegativeInput = fmt.Errorf("negative value is out of range for this instrument")
|
||||||
|
ErrNaNInput = fmt.Errorf("NaN value is an invalid input")
|
||||||
|
ErrInconsistentType = fmt.Errorf("inconsistent aggregator types")
|
||||||
|
ErrNoSubtraction = fmt.Errorf("aggregator does not subtract")
|
||||||
|
|
||||||
|
// ErrNoData is returned when (due to a race with collection)
|
||||||
|
// the Aggregator is check-pointed before the first value is set.
|
||||||
|
// The aggregator should simply be skipped in this case.
|
||||||
|
ErrNoData = fmt.Errorf("no data collected by this aggregator")
|
||||||
|
)
|
||||||
|
|
||||||
|
// String returns the string value of Kind.
|
||||||
|
func (k Kind) String() string {
|
||||||
|
return string(k)
|
||||||
|
}
|
||||||
117
vendor/go.opentelemetry.io/otel/sdk/export/metric/aggregation/temporality.go
generated
vendored
Normal file
117
vendor/go.opentelemetry.io/otel/sdk/export/metric/aggregation/temporality.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
// Copyright The 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.
|
||||||
|
|
||||||
|
//go:generate stringer -type=Temporality
|
||||||
|
|
||||||
|
package aggregation // import "go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Temporality indicates the temporal aggregation exported by an exporter.
|
||||||
|
// These bits may be OR-d together when multiple exporters are in use.
|
||||||
|
type Temporality uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
// CumulativeTemporality indicates that an Exporter expects a
|
||||||
|
// Cumulative Aggregation.
|
||||||
|
CumulativeTemporality Temporality = 1
|
||||||
|
|
||||||
|
// DeltaTemporality indicates that an Exporter expects a
|
||||||
|
// Delta Aggregation.
|
||||||
|
DeltaTemporality Temporality = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Includes returns if t includes support for other temporality.
|
||||||
|
func (t Temporality) Includes(other Temporality) bool {
|
||||||
|
return t&other != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MemoryRequired returns whether an exporter of this temporality requires
|
||||||
|
// memory to export correctly.
|
||||||
|
func (t Temporality) MemoryRequired(mkind sdkapi.InstrumentKind) bool {
|
||||||
|
switch mkind {
|
||||||
|
case sdkapi.HistogramInstrumentKind, sdkapi.GaugeObserverInstrumentKind,
|
||||||
|
sdkapi.CounterInstrumentKind, sdkapi.UpDownCounterInstrumentKind:
|
||||||
|
// Delta-oriented instruments:
|
||||||
|
return t.Includes(CumulativeTemporality)
|
||||||
|
|
||||||
|
case sdkapi.CounterObserverInstrumentKind, sdkapi.UpDownCounterObserverInstrumentKind:
|
||||||
|
// Cumulative-oriented instruments:
|
||||||
|
return t.Includes(DeltaTemporality)
|
||||||
|
}
|
||||||
|
// Something unexpected is happening--we could panic. This
|
||||||
|
// will become an error when the exporter tries to access a
|
||||||
|
// checkpoint, presumably, so let it be.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
constantTemporalitySelector Temporality
|
||||||
|
statelessTemporalitySelector struct{}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ TemporalitySelector = constantTemporalitySelector(0)
|
||||||
|
_ TemporalitySelector = statelessTemporalitySelector{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConstantTemporalitySelector returns an TemporalitySelector that returns
|
||||||
|
// a constant Temporality.
|
||||||
|
func ConstantTemporalitySelector(t Temporality) TemporalitySelector {
|
||||||
|
return constantTemporalitySelector(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CumulativeTemporalitySelector returns an TemporalitySelector that
|
||||||
|
// always returns CumulativeTemporality.
|
||||||
|
func CumulativeTemporalitySelector() TemporalitySelector {
|
||||||
|
return ConstantTemporalitySelector(CumulativeTemporality)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeltaTemporalitySelector returns an TemporalitySelector that
|
||||||
|
// always returns DeltaTemporality.
|
||||||
|
func DeltaTemporalitySelector() TemporalitySelector {
|
||||||
|
return ConstantTemporalitySelector(DeltaTemporality)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatelessTemporalitySelector returns an TemporalitySelector that
|
||||||
|
// always returns the Temporality that avoids long-term memory
|
||||||
|
// requirements.
|
||||||
|
func StatelessTemporalitySelector() TemporalitySelector {
|
||||||
|
return statelessTemporalitySelector{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemporalityFor implements TemporalitySelector.
|
||||||
|
func (c constantTemporalitySelector) TemporalityFor(_ *sdkapi.Descriptor, _ Kind) Temporality {
|
||||||
|
return Temporality(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemporalityFor implements TemporalitySelector.
|
||||||
|
func (s statelessTemporalitySelector) TemporalityFor(desc *sdkapi.Descriptor, kind Kind) Temporality {
|
||||||
|
if kind == SumKind && desc.InstrumentKind().PrecomputedSum() {
|
||||||
|
return CumulativeTemporality
|
||||||
|
}
|
||||||
|
return DeltaTemporality
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemporalitySelector is a sub-interface of Exporter used to indicate
|
||||||
|
// whether the Processor should compute Delta or Cumulative
|
||||||
|
// Aggregations.
|
||||||
|
type TemporalitySelector interface {
|
||||||
|
// TemporalityFor should return the correct Temporality that
|
||||||
|
// should be used when exporting data for the given metric
|
||||||
|
// instrument and Aggregator kind.
|
||||||
|
TemporalityFor(descriptor *sdkapi.Descriptor, aggregationKind Kind) Temporality
|
||||||
|
}
|
||||||
25
vendor/go.opentelemetry.io/otel/sdk/export/metric/aggregation/temporality_string.go
generated
vendored
Normal file
25
vendor/go.opentelemetry.io/otel/sdk/export/metric/aggregation/temporality_string.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Code generated by "stringer -type=Temporality"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package aggregation
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[CumulativeTemporality-1]
|
||||||
|
_ = x[DeltaTemporality-2]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _Temporality_name = "CumulativeTemporalityDeltaTemporality"
|
||||||
|
|
||||||
|
var _Temporality_index = [...]uint8{0, 21, 37}
|
||||||
|
|
||||||
|
func (i Temporality) String() string {
|
||||||
|
i -= 1
|
||||||
|
if i >= Temporality(len(_Temporality_index)-1) {
|
||||||
|
return "Temporality(" + strconv.FormatInt(int64(i+1), 10) + ")"
|
||||||
|
}
|
||||||
|
return _Temporality_name[_Temporality_index[i]:_Temporality_index[i+1]]
|
||||||
|
}
|
||||||
354
vendor/go.opentelemetry.io/otel/sdk/export/metric/metric.go
generated
vendored
Normal file
354
vendor/go.opentelemetry.io/otel/sdk/export/metric/metric.go
generated
vendored
Normal file
@@ -0,0 +1,354 @@
|
|||||||
|
// Copyright The 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 "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||||
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Processor is responsible for deciding which kind of aggregation to
|
||||||
|
// use (via AggregatorSelector), gathering exported results from the
|
||||||
|
// SDK during collection, and deciding over which dimensions to group
|
||||||
|
// the exported data.
|
||||||
|
//
|
||||||
|
// The SDK supports binding only one of these interfaces, as it has
|
||||||
|
// the sole responsibility of determining which Aggregator to use for
|
||||||
|
// each record.
|
||||||
|
//
|
||||||
|
// The embedded AggregatorSelector interface is called (concurrently)
|
||||||
|
// in instrumentation context to select the appropriate Aggregator for
|
||||||
|
// an instrument.
|
||||||
|
//
|
||||||
|
// The `Process` method is called during collection in a
|
||||||
|
// single-threaded context from the SDK, after the aggregator is
|
||||||
|
// checkpointed, allowing the processor to build the set of metrics
|
||||||
|
// currently being exported.
|
||||||
|
type Processor interface {
|
||||||
|
// AggregatorSelector is responsible for selecting the
|
||||||
|
// concrete type of Aggregator used for a metric in the SDK.
|
||||||
|
//
|
||||||
|
// This may be a static decision based on fields of the
|
||||||
|
// Descriptor, or it could use an external configuration
|
||||||
|
// source to customize the treatment of each metric
|
||||||
|
// instrument.
|
||||||
|
//
|
||||||
|
// The result from AggregatorSelector.AggregatorFor should be
|
||||||
|
// the same type for a given Descriptor or else nil. The same
|
||||||
|
// type should be returned for a given descriptor, because
|
||||||
|
// Aggregators only know how to Merge with their own type. If
|
||||||
|
// the result is nil, the metric instrument will be disabled.
|
||||||
|
//
|
||||||
|
// Note that the SDK only calls AggregatorFor when new records
|
||||||
|
// require an Aggregator. This does not provide a way to
|
||||||
|
// disable metrics with active records.
|
||||||
|
AggregatorSelector
|
||||||
|
|
||||||
|
// Process is called by the SDK once per internal record,
|
||||||
|
// passing the export Accumulation (a Descriptor, the corresponding
|
||||||
|
// Labels, and the checkpointed Aggregator). This call has no
|
||||||
|
// Context argument because it is expected to perform only
|
||||||
|
// computation. An SDK is not expected to call exporters from
|
||||||
|
// with Process, use a controller for that (see
|
||||||
|
// ./controllers/{pull,push}.
|
||||||
|
Process(accum Accumulation) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// AggregatorSelector supports selecting the kind of Aggregator to
|
||||||
|
// use at runtime for a specific metric instrument.
|
||||||
|
type AggregatorSelector interface {
|
||||||
|
// AggregatorFor allocates a variable number of aggregators of
|
||||||
|
// a kind suitable for the requested export. This method
|
||||||
|
// initializes a `...*Aggregator`, to support making a single
|
||||||
|
// allocation.
|
||||||
|
//
|
||||||
|
// When the call returns without initializing the *Aggregator
|
||||||
|
// to a non-nil value, the metric instrument is explicitly
|
||||||
|
// disabled.
|
||||||
|
//
|
||||||
|
// This must return a consistent type to avoid confusion in
|
||||||
|
// later stages of the metrics export process, i.e., when
|
||||||
|
// Merging or Checkpointing aggregators for a specific
|
||||||
|
// instrument.
|
||||||
|
//
|
||||||
|
// Note: This is context-free because the aggregator should
|
||||||
|
// not relate to the incoming context. This call should not
|
||||||
|
// block.
|
||||||
|
AggregatorFor(descriptor *sdkapi.Descriptor, aggregator ...*Aggregator)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checkpointer is the interface used by a Controller to coordinate
|
||||||
|
// the Processor with Accumulator(s) and Exporter(s). The
|
||||||
|
// StartCollection() and FinishCollection() methods start and finish a
|
||||||
|
// collection interval. Controllers call the Accumulator(s) during
|
||||||
|
// collection to process Accumulations.
|
||||||
|
type Checkpointer interface {
|
||||||
|
// Processor processes metric data for export. The Process
|
||||||
|
// method is bracketed by StartCollection and FinishCollection
|
||||||
|
// calls. The embedded AggregatorSelector can be called at
|
||||||
|
// any time.
|
||||||
|
Processor
|
||||||
|
|
||||||
|
// Reader returns the current data set. This may be
|
||||||
|
// called before and after collection. The
|
||||||
|
// implementation is required to return the same value
|
||||||
|
// throughout its lifetime, since Reader exposes a
|
||||||
|
// sync.Locker interface. The caller is responsible for
|
||||||
|
// locking the Reader before initiating collection.
|
||||||
|
Reader() Reader
|
||||||
|
|
||||||
|
// StartCollection begins a collection interval.
|
||||||
|
StartCollection()
|
||||||
|
|
||||||
|
// FinishCollection ends a collection interval.
|
||||||
|
FinishCollection() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckpointerFactory is an interface for producing configured
|
||||||
|
// Checkpointer instances.
|
||||||
|
type CheckpointerFactory interface {
|
||||||
|
NewCheckpointer() Checkpointer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregator implements a specific aggregation behavior, e.g., a
|
||||||
|
// behavior to track a sequence of updates to an instrument. Counter
|
||||||
|
// instruments commonly use a simple Sum aggregator, but for the
|
||||||
|
// distribution instruments (Histogram, GaugeObserver) there are a
|
||||||
|
// number of possible aggregators with different cost and accuracy
|
||||||
|
// tradeoffs.
|
||||||
|
//
|
||||||
|
// Note that any Aggregator may be attached to any instrument--this is
|
||||||
|
// the result of the OpenTelemetry API/SDK separation. It is possible
|
||||||
|
// to attach a Sum aggregator to a Histogram instrument or a
|
||||||
|
// MinMaxSumCount aggregator to a Counter instrument.
|
||||||
|
type Aggregator interface {
|
||||||
|
// Aggregation returns an Aggregation interface to access the
|
||||||
|
// current state of this Aggregator. The caller is
|
||||||
|
// responsible for synchronization and must not call any the
|
||||||
|
// other methods in this interface concurrently while using
|
||||||
|
// the Aggregation.
|
||||||
|
Aggregation() aggregation.Aggregation
|
||||||
|
|
||||||
|
// Update receives a new measured value and incorporates it
|
||||||
|
// into the aggregation. Update() calls may be called
|
||||||
|
// concurrently.
|
||||||
|
//
|
||||||
|
// Descriptor.NumberKind() should be consulted to determine
|
||||||
|
// whether the provided number is an int64 or float64.
|
||||||
|
//
|
||||||
|
// The Context argument comes from user-level code and could be
|
||||||
|
// inspected for a `correlation.Map` or `trace.SpanContext`.
|
||||||
|
Update(ctx context.Context, number number.Number, descriptor *sdkapi.Descriptor) error
|
||||||
|
|
||||||
|
// SynchronizedMove is called during collection to finish one
|
||||||
|
// period of aggregation by atomically saving the
|
||||||
|
// currently-updating state into the argument Aggregator AND
|
||||||
|
// resetting the current value to the zero state.
|
||||||
|
//
|
||||||
|
// SynchronizedMove() is called concurrently with Update(). These
|
||||||
|
// two methods must be synchronized with respect to each
|
||||||
|
// other, for correctness.
|
||||||
|
//
|
||||||
|
// After saving a synchronized copy, the Aggregator can be converted
|
||||||
|
// into one or more of the interfaces in the `aggregation` sub-package,
|
||||||
|
// according to kind of Aggregator that was selected.
|
||||||
|
//
|
||||||
|
// This method will return an InconsistentAggregatorError if
|
||||||
|
// this Aggregator cannot be copied into the destination due
|
||||||
|
// to an incompatible type.
|
||||||
|
//
|
||||||
|
// This call has no Context argument because it is expected to
|
||||||
|
// perform only computation.
|
||||||
|
//
|
||||||
|
// When called with a nil `destination`, this Aggregator is reset
|
||||||
|
// and the current value is discarded.
|
||||||
|
SynchronizedMove(destination Aggregator, descriptor *sdkapi.Descriptor) error
|
||||||
|
|
||||||
|
// Merge combines the checkpointed state from the argument
|
||||||
|
// Aggregator into this Aggregator. Merge is not synchronized
|
||||||
|
// with respect to Update or SynchronizedMove.
|
||||||
|
//
|
||||||
|
// The owner of an Aggregator being merged is responsible for
|
||||||
|
// synchronization of both Aggregator states.
|
||||||
|
Merge(aggregator Aggregator, descriptor *sdkapi.Descriptor) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtractor is an optional interface implemented by some
|
||||||
|
// Aggregators. An Aggregator must support `Subtract()` in order to
|
||||||
|
// be configured for a Precomputed-Sum instrument (CounterObserver,
|
||||||
|
// UpDownCounterObserver) using a DeltaExporter.
|
||||||
|
type Subtractor interface {
|
||||||
|
// Subtract subtracts the `operand` from this Aggregator and
|
||||||
|
// outputs the value in `result`.
|
||||||
|
Subtract(operand, result Aggregator, descriptor *sdkapi.Descriptor) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exporter handles presentation of the checkpoint of aggregate
|
||||||
|
// metrics. This is the final stage of a metrics export pipeline,
|
||||||
|
// where metric data are formatted for a specific system.
|
||||||
|
type Exporter interface {
|
||||||
|
// Export is called immediately after completing a collection
|
||||||
|
// pass in the SDK.
|
||||||
|
//
|
||||||
|
// The Context comes from the controller that initiated
|
||||||
|
// collection.
|
||||||
|
//
|
||||||
|
// The InstrumentationLibraryReader interface refers to the
|
||||||
|
// Processor that just completed collection.
|
||||||
|
Export(ctx context.Context, resource *resource.Resource, reader InstrumentationLibraryReader) error
|
||||||
|
|
||||||
|
// TemporalitySelector is an interface used by the Processor
|
||||||
|
// in deciding whether to compute Delta or Cumulative
|
||||||
|
// Aggregations when passing Records to this Exporter.
|
||||||
|
aggregation.TemporalitySelector
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstrumentationLibraryReader is an interface for exporters to iterate
|
||||||
|
// over one instrumentation library of metric data at a time.
|
||||||
|
type InstrumentationLibraryReader interface {
|
||||||
|
// ForEach calls the passed function once per instrumentation library,
|
||||||
|
// allowing the caller to emit metrics grouped by the library that
|
||||||
|
// produced them.
|
||||||
|
ForEach(readerFunc func(instrumentation.Library, Reader) error) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader allows a controller to access a complete checkpoint of
|
||||||
|
// aggregated metrics from the Processor for a single library of
|
||||||
|
// metric data. This is passed to the Exporter which may then use
|
||||||
|
// ForEach to iterate over the collection of aggregated metrics.
|
||||||
|
type Reader interface {
|
||||||
|
// ForEach iterates over aggregated checkpoints for all
|
||||||
|
// metrics that were updated during the last collection
|
||||||
|
// period. Each aggregated checkpoint returned by the
|
||||||
|
// function parameter may return an error.
|
||||||
|
//
|
||||||
|
// The TemporalitySelector argument is used to determine
|
||||||
|
// whether the Record is computed using Delta or Cumulative
|
||||||
|
// aggregation.
|
||||||
|
//
|
||||||
|
// ForEach tolerates ErrNoData silently, as this is
|
||||||
|
// expected from the Meter implementation. Any other kind
|
||||||
|
// of error will immediately halt ForEach and return
|
||||||
|
// the error to the caller.
|
||||||
|
ForEach(tempSelector aggregation.TemporalitySelector, recordFunc func(Record) error) error
|
||||||
|
|
||||||
|
// Locker supports locking the checkpoint set. Collection
|
||||||
|
// into the checkpoint set cannot take place (in case of a
|
||||||
|
// stateful processor) while it is locked.
|
||||||
|
//
|
||||||
|
// The Processor attached to the Accumulator MUST be called
|
||||||
|
// with the lock held.
|
||||||
|
sync.Locker
|
||||||
|
|
||||||
|
// RLock acquires a read lock corresponding to this Locker.
|
||||||
|
RLock()
|
||||||
|
// RUnlock releases a read lock corresponding to this Locker.
|
||||||
|
RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metadata contains the common elements for exported metric data that
|
||||||
|
// are shared by the Accumulator->Processor and Processor->Exporter
|
||||||
|
// steps.
|
||||||
|
type Metadata struct {
|
||||||
|
descriptor *sdkapi.Descriptor
|
||||||
|
labels *attribute.Set
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accumulation contains the exported data for a single metric instrument
|
||||||
|
// and label set, as prepared by an Accumulator for the Processor.
|
||||||
|
type Accumulation struct {
|
||||||
|
Metadata
|
||||||
|
aggregator Aggregator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record contains the exported data for a single metric instrument
|
||||||
|
// and label set, as prepared by the Processor for the Exporter.
|
||||||
|
// This includes the effective start and end time for the aggregation.
|
||||||
|
type Record struct {
|
||||||
|
Metadata
|
||||||
|
aggregation aggregation.Aggregation
|
||||||
|
start time.Time
|
||||||
|
end time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// Descriptor describes the metric instrument being exported.
|
||||||
|
func (m Metadata) Descriptor() *sdkapi.Descriptor {
|
||||||
|
return m.descriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
// Labels describes the labels associated with the instrument and the
|
||||||
|
// aggregated data.
|
||||||
|
func (m Metadata) Labels() *attribute.Set {
|
||||||
|
return m.labels
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAccumulation allows Accumulator implementations to construct new
|
||||||
|
// Accumulations to send to Processors. The Descriptor, Labels,
|
||||||
|
// and Aggregator represent aggregate metric events received over a single
|
||||||
|
// collection period.
|
||||||
|
func NewAccumulation(descriptor *sdkapi.Descriptor, labels *attribute.Set, aggregator Aggregator) Accumulation {
|
||||||
|
return Accumulation{
|
||||||
|
Metadata: Metadata{
|
||||||
|
descriptor: descriptor,
|
||||||
|
labels: labels,
|
||||||
|
},
|
||||||
|
aggregator: aggregator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregator returns the checkpointed aggregator. It is safe to
|
||||||
|
// access the checkpointed state without locking.
|
||||||
|
func (r Accumulation) Aggregator() Aggregator {
|
||||||
|
return r.aggregator
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRecord allows Processor implementations to construct export
|
||||||
|
// records. The Descriptor, Labels, and Aggregator represent
|
||||||
|
// aggregate metric events received over a single collection period.
|
||||||
|
func NewRecord(descriptor *sdkapi.Descriptor, labels *attribute.Set, aggregation aggregation.Aggregation, start, end time.Time) Record {
|
||||||
|
return Record{
|
||||||
|
Metadata: Metadata{
|
||||||
|
descriptor: descriptor,
|
||||||
|
labels: labels,
|
||||||
|
},
|
||||||
|
aggregation: aggregation,
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregation returns the aggregation, an interface to the record and
|
||||||
|
// its aggregator, dependent on the kind of both the input and exporter.
|
||||||
|
func (r Record) Aggregation() aggregation.Aggregation {
|
||||||
|
return r.aggregation
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartTime is the start time of the interval covered by this aggregation.
|
||||||
|
func (r Record) StartTime() time.Time {
|
||||||
|
return r.start
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndTime is the end time of the interval covered by this aggregation.
|
||||||
|
func (r Record) EndTime() time.Time {
|
||||||
|
return r.end
|
||||||
|
}
|
||||||
33
vendor/go.opentelemetry.io/otel/sdk/instrumentation/library.go
generated
vendored
Normal file
33
vendor/go.opentelemetry.io/otel/sdk/instrumentation/library.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright The 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 instrumentation provides an instrumentation library structure to be
|
||||||
|
passed to both the OpenTelemetry Tracer and Meter components.
|
||||||
|
|
||||||
|
For more information see
|
||||||
|
[this](https://github.com/open-telemetry/oteps/blob/main/text/0083-component.md).
|
||||||
|
*/
|
||||||
|
package instrumentation // import "go.opentelemetry.io/otel/sdk/instrumentation"
|
||||||
|
|
||||||
|
// Library represents the instrumentation library.
|
||||||
|
type Library struct {
|
||||||
|
// Name is the name of the instrumentation library. This should be the
|
||||||
|
// Go package name of that library.
|
||||||
|
Name string
|
||||||
|
// Version is the version of the instrumentation library.
|
||||||
|
Version string
|
||||||
|
// SchemaURL of the telemetry emitted by the library.
|
||||||
|
SchemaURL string
|
||||||
|
}
|
||||||
201
vendor/go.opentelemetry.io/otel/sdk/metric/LICENSE
generated
vendored
Normal file
201
vendor/go.opentelemetry.io/otel/sdk/metric/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
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.
|
||||||
52
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/aggregator.go
generated
vendored
Normal file
52
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/aggregator.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright The 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 aggregator // import "go.opentelemetry.io/otel/sdk/metric/aggregator"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewInconsistentAggregatorError formats an error describing an attempt to
|
||||||
|
// Checkpoint or Merge different-type aggregators. The result can be unwrapped as
|
||||||
|
// an ErrInconsistentType.
|
||||||
|
func NewInconsistentAggregatorError(a1, a2 export.Aggregator) error {
|
||||||
|
return fmt.Errorf("%w: %T and %T", aggregation.ErrInconsistentType, a1, a2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RangeTest is a common routine for testing for valid input values.
|
||||||
|
// This rejects NaN values. This rejects negative values when the
|
||||||
|
// metric instrument does not support negative values, including
|
||||||
|
// monotonic counter metrics and absolute Histogram metrics.
|
||||||
|
func RangeTest(num number.Number, descriptor *sdkapi.Descriptor) error {
|
||||||
|
numberKind := descriptor.NumberKind()
|
||||||
|
|
||||||
|
if numberKind == number.Float64Kind && math.IsNaN(num.AsFloat64()) {
|
||||||
|
return aggregation.ErrNaNInput
|
||||||
|
}
|
||||||
|
|
||||||
|
switch descriptor.InstrumentKind() {
|
||||||
|
case sdkapi.CounterInstrumentKind, sdkapi.CounterObserverInstrumentKind:
|
||||||
|
if num.IsNegative(numberKind) {
|
||||||
|
return aggregation.ErrNegativeInput
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
130
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/exact/exact.go
generated
vendored
Normal file
130
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/exact/exact.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
// Copyright The 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 exact // import "go.opentelemetry.io/otel/sdk/metric/aggregator/exact"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Aggregator aggregates events that form a distribution, keeping
|
||||||
|
// an array with the exact set of values.
|
||||||
|
Aggregator struct {
|
||||||
|
lock sync.Mutex
|
||||||
|
samples []aggregation.Point
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ export.Aggregator = &Aggregator{}
|
||||||
|
var _ aggregation.Points = &Aggregator{}
|
||||||
|
var _ aggregation.Count = &Aggregator{}
|
||||||
|
|
||||||
|
// New returns cnt many new exact aggregators, which aggregate recorded
|
||||||
|
// measurements by storing them in an array. This type uses a mutex
|
||||||
|
// for Update() and SynchronizedMove() concurrency.
|
||||||
|
func New(cnt int) []Aggregator {
|
||||||
|
return make([]Aggregator, cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregation returns an interface for reading the state of this aggregator.
|
||||||
|
func (c *Aggregator) Aggregation() aggregation.Aggregation {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns aggregation.ExactKind.
|
||||||
|
func (c *Aggregator) Kind() aggregation.Kind {
|
||||||
|
return aggregation.ExactKind
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count returns the number of values in the checkpoint.
|
||||||
|
func (c *Aggregator) Count() (uint64, error) {
|
||||||
|
return uint64(len(c.samples)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Points returns access to the raw data set.
|
||||||
|
func (c *Aggregator) Points() ([]aggregation.Point, error) {
|
||||||
|
return c.samples, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SynchronizedMove saves the current state to oa and resets the current state to
|
||||||
|
// the empty set, taking a lock to prevent concurrent Update() calls.
|
||||||
|
func (c *Aggregator) SynchronizedMove(oa export.Aggregator, desc *sdkapi.Descriptor) error {
|
||||||
|
o, _ := oa.(*Aggregator)
|
||||||
|
|
||||||
|
if oa != nil && o == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(c, oa)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
if o != nil {
|
||||||
|
o.samples = c.samples
|
||||||
|
}
|
||||||
|
c.samples = nil
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update adds the recorded measurement to the current data set.
|
||||||
|
// Update takes a lock to prevent concurrent Update() and SynchronizedMove()
|
||||||
|
// calls.
|
||||||
|
func (c *Aggregator) Update(_ context.Context, number number.Number, desc *sdkapi.Descriptor) error {
|
||||||
|
now := time.Now()
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
c.samples = append(c.samples, aggregation.Point{
|
||||||
|
Number: number,
|
||||||
|
Time: now,
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge combines two data sets into one.
|
||||||
|
func (c *Aggregator) Merge(oa export.Aggregator, desc *sdkapi.Descriptor) error {
|
||||||
|
o, _ := oa.(*Aggregator)
|
||||||
|
if o == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(c, oa)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.samples = combine(c.samples, o.samples)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func combine(a, b []aggregation.Point) []aggregation.Point {
|
||||||
|
result := make([]aggregation.Point, 0, len(a)+len(b))
|
||||||
|
|
||||||
|
for len(a) != 0 && len(b) != 0 {
|
||||||
|
if a[0].Time.Before(b[0].Time) {
|
||||||
|
result = append(result, a[0])
|
||||||
|
a = a[1:]
|
||||||
|
} else {
|
||||||
|
result = append(result, b[0])
|
||||||
|
b = b[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = append(result, a...)
|
||||||
|
result = append(result, b...)
|
||||||
|
return result
|
||||||
|
}
|
||||||
270
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/histogram/histogram.go
generated
vendored
Normal file
270
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/histogram/histogram.go
generated
vendored
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
// Copyright The 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 histogram // import "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Note: This code uses a Mutex to govern access to the exclusive
|
||||||
|
// aggregator state. This is in contrast to a lock-free approach
|
||||||
|
// (as in the Go prometheus client) that was reverted here:
|
||||||
|
// https://github.com/open-telemetry/opentelemetry-go/pull/669
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Aggregator observe events and counts them in pre-determined buckets.
|
||||||
|
// It also calculates the sum and count of all events.
|
||||||
|
Aggregator struct {
|
||||||
|
lock sync.Mutex
|
||||||
|
boundaries []float64
|
||||||
|
kind number.Kind
|
||||||
|
state *state
|
||||||
|
}
|
||||||
|
|
||||||
|
// config describes how the histogram is aggregated.
|
||||||
|
config struct {
|
||||||
|
// explicitBoundaries support arbitrary bucketing schemes. This
|
||||||
|
// is the general case.
|
||||||
|
explicitBoundaries []float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option configures a histogram config.
|
||||||
|
Option interface {
|
||||||
|
// apply sets one or more config fields.
|
||||||
|
apply(*config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// state represents the state of a histogram, consisting of
|
||||||
|
// the sum and counts for all observed values and
|
||||||
|
// the less than equal bucket count for the pre-determined boundaries.
|
||||||
|
state struct {
|
||||||
|
bucketCounts []uint64
|
||||||
|
sum number.Number
|
||||||
|
count uint64
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithExplicitBoundaries sets the ExplicitBoundaries configuration option of a config.
|
||||||
|
func WithExplicitBoundaries(explicitBoundaries []float64) Option {
|
||||||
|
return explicitBoundariesOption{explicitBoundaries}
|
||||||
|
}
|
||||||
|
|
||||||
|
type explicitBoundariesOption struct {
|
||||||
|
boundaries []float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o explicitBoundariesOption) apply(config *config) {
|
||||||
|
config.explicitBoundaries = o.boundaries
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultExplicitBoundaries have been copied from prometheus.DefBuckets.
|
||||||
|
//
|
||||||
|
// Note we anticipate the use of a high-precision histogram sketch as
|
||||||
|
// the standard histogram aggregator for OTLP export.
|
||||||
|
// (https://github.com/open-telemetry/opentelemetry-specification/issues/982).
|
||||||
|
var defaultFloat64ExplicitBoundaries = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}
|
||||||
|
|
||||||
|
// defaultInt64ExplicitBoundaryMultiplier determines the default
|
||||||
|
// integer histogram boundaries.
|
||||||
|
const defaultInt64ExplicitBoundaryMultiplier = 1e6
|
||||||
|
|
||||||
|
// defaultInt64ExplicitBoundaries applies a multiplier to the default
|
||||||
|
// float64 boundaries: [ 5K, 10K, 25K, ..., 2.5M, 5M, 10M ]
|
||||||
|
var defaultInt64ExplicitBoundaries = func(bounds []float64) (asint []float64) {
|
||||||
|
for _, f := range bounds {
|
||||||
|
asint = append(asint, defaultInt64ExplicitBoundaryMultiplier*f)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}(defaultFloat64ExplicitBoundaries)
|
||||||
|
|
||||||
|
var _ export.Aggregator = &Aggregator{}
|
||||||
|
var _ aggregation.Sum = &Aggregator{}
|
||||||
|
var _ aggregation.Count = &Aggregator{}
|
||||||
|
var _ aggregation.Histogram = &Aggregator{}
|
||||||
|
|
||||||
|
// New returns a new aggregator for computing Histograms.
|
||||||
|
//
|
||||||
|
// A Histogram observe events and counts them in pre-defined buckets.
|
||||||
|
// And also provides the total sum and count of all observations.
|
||||||
|
//
|
||||||
|
// Note that this aggregator maintains each value using independent
|
||||||
|
// atomic operations, which introduces the possibility that
|
||||||
|
// checkpoints are inconsistent.
|
||||||
|
func New(cnt int, desc *sdkapi.Descriptor, opts ...Option) []Aggregator {
|
||||||
|
var cfg config
|
||||||
|
|
||||||
|
if desc.NumberKind() == number.Int64Kind {
|
||||||
|
cfg.explicitBoundaries = defaultInt64ExplicitBoundaries
|
||||||
|
} else {
|
||||||
|
cfg.explicitBoundaries = defaultFloat64ExplicitBoundaries
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt.apply(&cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
aggs := make([]Aggregator, cnt)
|
||||||
|
|
||||||
|
// Boundaries MUST be ordered otherwise the histogram could not
|
||||||
|
// be properly computed.
|
||||||
|
sortedBoundaries := make([]float64, len(cfg.explicitBoundaries))
|
||||||
|
|
||||||
|
copy(sortedBoundaries, cfg.explicitBoundaries)
|
||||||
|
sort.Float64s(sortedBoundaries)
|
||||||
|
|
||||||
|
for i := range aggs {
|
||||||
|
aggs[i] = Aggregator{
|
||||||
|
kind: desc.NumberKind(),
|
||||||
|
boundaries: sortedBoundaries,
|
||||||
|
}
|
||||||
|
aggs[i].state = aggs[i].newState()
|
||||||
|
}
|
||||||
|
return aggs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregation returns an interface for reading the state of this aggregator.
|
||||||
|
func (c *Aggregator) Aggregation() aggregation.Aggregation {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns aggregation.HistogramKind.
|
||||||
|
func (c *Aggregator) Kind() aggregation.Kind {
|
||||||
|
return aggregation.HistogramKind
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum returns the sum of all values in the checkpoint.
|
||||||
|
func (c *Aggregator) Sum() (number.Number, error) {
|
||||||
|
return c.state.sum, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count returns the number of values in the checkpoint.
|
||||||
|
func (c *Aggregator) Count() (uint64, error) {
|
||||||
|
return c.state.count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Histogram returns the count of events in pre-determined buckets.
|
||||||
|
func (c *Aggregator) Histogram() (aggregation.Buckets, error) {
|
||||||
|
return aggregation.Buckets{
|
||||||
|
Boundaries: c.boundaries,
|
||||||
|
Counts: c.state.bucketCounts,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SynchronizedMove saves the current state into oa and resets the current state to
|
||||||
|
// the empty set. Since no locks are taken, there is a chance that
|
||||||
|
// the independent Sum, Count and Bucket Count are not consistent with each
|
||||||
|
// other.
|
||||||
|
func (c *Aggregator) SynchronizedMove(oa export.Aggregator, desc *sdkapi.Descriptor) error {
|
||||||
|
o, _ := oa.(*Aggregator)
|
||||||
|
|
||||||
|
if oa != nil && o == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(c, oa)
|
||||||
|
}
|
||||||
|
|
||||||
|
if o != nil {
|
||||||
|
// Swap case: This is the ordinary case for a
|
||||||
|
// synchronous instrument, where the SDK allocates two
|
||||||
|
// Aggregators and lock contention is anticipated.
|
||||||
|
// Reset the target state before swapping it under the
|
||||||
|
// lock below.
|
||||||
|
o.clearState()
|
||||||
|
}
|
||||||
|
|
||||||
|
c.lock.Lock()
|
||||||
|
if o != nil {
|
||||||
|
c.state, o.state = o.state, c.state
|
||||||
|
} else {
|
||||||
|
// No swap case: This is the ordinary case for an
|
||||||
|
// asynchronous instrument, where the SDK allocates a
|
||||||
|
// single Aggregator and there is no anticipated lock
|
||||||
|
// contention.
|
||||||
|
c.clearState()
|
||||||
|
}
|
||||||
|
c.lock.Unlock()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Aggregator) newState() *state {
|
||||||
|
return &state{
|
||||||
|
bucketCounts: make([]uint64, len(c.boundaries)+1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Aggregator) clearState() {
|
||||||
|
for i := range c.state.bucketCounts {
|
||||||
|
c.state.bucketCounts[i] = 0
|
||||||
|
}
|
||||||
|
c.state.sum = 0
|
||||||
|
c.state.count = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update adds the recorded measurement to the current data set.
|
||||||
|
func (c *Aggregator) Update(_ context.Context, number number.Number, desc *sdkapi.Descriptor) error {
|
||||||
|
kind := desc.NumberKind()
|
||||||
|
asFloat := number.CoerceToFloat64(kind)
|
||||||
|
|
||||||
|
bucketID := len(c.boundaries)
|
||||||
|
for i, boundary := range c.boundaries {
|
||||||
|
if asFloat < boundary {
|
||||||
|
bucketID = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Note: Binary-search was compared using the benchmarks. The following
|
||||||
|
// code is equivalent to the linear search above:
|
||||||
|
//
|
||||||
|
// bucketID := sort.Search(len(c.boundaries), func(i int) bool {
|
||||||
|
// return asFloat < c.boundaries[i]
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// The binary search wins for very large boundary sets, but
|
||||||
|
// the linear search performs better up through arrays between
|
||||||
|
// 256 and 512 elements, which is a relatively large histogram, so we
|
||||||
|
// continue to prefer linear search.
|
||||||
|
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
c.state.count++
|
||||||
|
c.state.sum.AddNumber(kind, number)
|
||||||
|
c.state.bucketCounts[bucketID]++
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge combines two histograms that have the same buckets into a single one.
|
||||||
|
func (c *Aggregator) Merge(oa export.Aggregator, desc *sdkapi.Descriptor) error {
|
||||||
|
o, _ := oa.(*Aggregator)
|
||||||
|
if o == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(c, oa)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.state.sum.AddNumber(desc.NumberKind(), o.state.sum)
|
||||||
|
c.state.count += o.state.count
|
||||||
|
|
||||||
|
for i := 0; i < len(c.state.bucketCounts); i++ {
|
||||||
|
c.state.bucketCounts[i] += o.state.bucketCounts[i]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
135
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue/lastvalue.go
generated
vendored
Normal file
135
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue/lastvalue.go
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
// Copyright The 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 lastvalue // import "go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
|
||||||
|
// Aggregator aggregates lastValue events.
|
||||||
|
Aggregator struct {
|
||||||
|
// value is an atomic pointer to *lastValueData. It is never nil.
|
||||||
|
value unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
// lastValueData stores the current value of a lastValue along with
|
||||||
|
// a sequence number to determine the winner of a race.
|
||||||
|
lastValueData struct {
|
||||||
|
// value is the int64- or float64-encoded Set() data
|
||||||
|
//
|
||||||
|
// value needs to be aligned for 64-bit atomic operations.
|
||||||
|
value number.Number
|
||||||
|
|
||||||
|
// timestamp indicates when this record was submitted.
|
||||||
|
// this can be used to pick a winner when multiple
|
||||||
|
// records contain lastValue data for the same labels due
|
||||||
|
// to races.
|
||||||
|
timestamp time.Time
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ export.Aggregator = &Aggregator{}
|
||||||
|
var _ aggregation.LastValue = &Aggregator{}
|
||||||
|
|
||||||
|
// An unset lastValue has zero timestamp and zero value.
|
||||||
|
var unsetLastValue = &lastValueData{}
|
||||||
|
|
||||||
|
// New returns a new lastValue aggregator. This aggregator retains the
|
||||||
|
// last value and timestamp that were recorded.
|
||||||
|
func New(cnt int) []Aggregator {
|
||||||
|
aggs := make([]Aggregator, cnt)
|
||||||
|
for i := range aggs {
|
||||||
|
aggs[i] = Aggregator{
|
||||||
|
value: unsafe.Pointer(unsetLastValue),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aggs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregation returns an interface for reading the state of this aggregator.
|
||||||
|
func (g *Aggregator) Aggregation() aggregation.Aggregation {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns aggregation.LastValueKind.
|
||||||
|
func (g *Aggregator) Kind() aggregation.Kind {
|
||||||
|
return aggregation.LastValueKind
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastValue returns the last-recorded lastValue value and the
|
||||||
|
// corresponding timestamp. The error value aggregation.ErrNoData
|
||||||
|
// will be returned if (due to a race condition) the checkpoint was
|
||||||
|
// computed before the first value was set.
|
||||||
|
func (g *Aggregator) LastValue() (number.Number, time.Time, error) {
|
||||||
|
gd := (*lastValueData)(g.value)
|
||||||
|
if gd == unsetLastValue {
|
||||||
|
return 0, time.Time{}, aggregation.ErrNoData
|
||||||
|
}
|
||||||
|
return gd.value.AsNumber(), gd.timestamp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SynchronizedMove atomically saves the current value.
|
||||||
|
func (g *Aggregator) SynchronizedMove(oa export.Aggregator, _ *sdkapi.Descriptor) error {
|
||||||
|
if oa == nil {
|
||||||
|
atomic.StorePointer(&g.value, unsafe.Pointer(unsetLastValue))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
o, _ := oa.(*Aggregator)
|
||||||
|
if o == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(g, oa)
|
||||||
|
}
|
||||||
|
o.value = atomic.SwapPointer(&g.value, unsafe.Pointer(unsetLastValue))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update atomically sets the current "last" value.
|
||||||
|
func (g *Aggregator) Update(_ context.Context, number number.Number, desc *sdkapi.Descriptor) error {
|
||||||
|
ngd := &lastValueData{
|
||||||
|
value: number,
|
||||||
|
timestamp: time.Now(),
|
||||||
|
}
|
||||||
|
atomic.StorePointer(&g.value, unsafe.Pointer(ngd))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge combines state from two aggregators. The most-recently set
|
||||||
|
// value is chosen.
|
||||||
|
func (g *Aggregator) Merge(oa export.Aggregator, desc *sdkapi.Descriptor) error {
|
||||||
|
o, _ := oa.(*Aggregator)
|
||||||
|
if o == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(g, oa)
|
||||||
|
}
|
||||||
|
|
||||||
|
ggd := (*lastValueData)(atomic.LoadPointer(&g.value))
|
||||||
|
ogd := (*lastValueData)(atomic.LoadPointer(&o.value))
|
||||||
|
|
||||||
|
if ggd.timestamp.After(ogd.timestamp) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
g.value = unsafe.Pointer(ogd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
165
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/minmaxsumcount/mmsc.go
generated
vendored
Normal file
165
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/minmaxsumcount/mmsc.go
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
// Copyright The 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 minmaxsumcount // import "go.opentelemetry.io/otel/sdk/metric/aggregator/minmaxsumcount"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Aggregator aggregates events that form a distribution,
|
||||||
|
// keeping only the min, max, sum, and count.
|
||||||
|
Aggregator struct {
|
||||||
|
lock sync.Mutex
|
||||||
|
kind number.Kind
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
state struct {
|
||||||
|
sum number.Number
|
||||||
|
min number.Number
|
||||||
|
max number.Number
|
||||||
|
count uint64
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ export.Aggregator = &Aggregator{}
|
||||||
|
var _ aggregation.MinMaxSumCount = &Aggregator{}
|
||||||
|
|
||||||
|
// New returns a new aggregator for computing the min, max, sum, and
|
||||||
|
// count.
|
||||||
|
//
|
||||||
|
// This type uses a mutex for Update() and SynchronizedMove() concurrency.
|
||||||
|
func New(cnt int, desc *sdkapi.Descriptor) []Aggregator {
|
||||||
|
kind := desc.NumberKind()
|
||||||
|
aggs := make([]Aggregator, cnt)
|
||||||
|
for i := range aggs {
|
||||||
|
aggs[i] = Aggregator{
|
||||||
|
kind: kind,
|
||||||
|
state: emptyState(kind),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aggs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregation returns an interface for reading the state of this aggregator.
|
||||||
|
func (c *Aggregator) Aggregation() aggregation.Aggregation {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns aggregation.MinMaxSumCountKind.
|
||||||
|
func (c *Aggregator) Kind() aggregation.Kind {
|
||||||
|
return aggregation.MinMaxSumCountKind
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum returns the sum of values in the checkpoint.
|
||||||
|
func (c *Aggregator) Sum() (number.Number, error) {
|
||||||
|
return c.sum, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count returns the number of values in the checkpoint.
|
||||||
|
func (c *Aggregator) Count() (uint64, error) {
|
||||||
|
return c.count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Min returns the minimum value in the checkpoint.
|
||||||
|
// The error value aggregation.ErrNoData will be returned
|
||||||
|
// if there were no measurements recorded during the checkpoint.
|
||||||
|
func (c *Aggregator) Min() (number.Number, error) {
|
||||||
|
if c.count == 0 {
|
||||||
|
return 0, aggregation.ErrNoData
|
||||||
|
}
|
||||||
|
return c.min, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max returns the maximum value in the checkpoint.
|
||||||
|
// The error value aggregation.ErrNoData will be returned
|
||||||
|
// if there were no measurements recorded during the checkpoint.
|
||||||
|
func (c *Aggregator) Max() (number.Number, error) {
|
||||||
|
if c.count == 0 {
|
||||||
|
return 0, aggregation.ErrNoData
|
||||||
|
}
|
||||||
|
return c.max, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SynchronizedMove saves the current state into oa and resets the current state to
|
||||||
|
// the empty set.
|
||||||
|
func (c *Aggregator) SynchronizedMove(oa export.Aggregator, desc *sdkapi.Descriptor) error {
|
||||||
|
o, _ := oa.(*Aggregator)
|
||||||
|
|
||||||
|
if oa != nil && o == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(c, oa)
|
||||||
|
}
|
||||||
|
c.lock.Lock()
|
||||||
|
if o != nil {
|
||||||
|
o.state = c.state
|
||||||
|
}
|
||||||
|
c.state = emptyState(c.kind)
|
||||||
|
c.lock.Unlock()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func emptyState(kind number.Kind) state {
|
||||||
|
return state{
|
||||||
|
count: 0,
|
||||||
|
sum: 0,
|
||||||
|
min: kind.Maximum(),
|
||||||
|
max: kind.Minimum(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update adds the recorded measurement to the current data set.
|
||||||
|
func (c *Aggregator) Update(_ context.Context, number number.Number, desc *sdkapi.Descriptor) error {
|
||||||
|
kind := desc.NumberKind()
|
||||||
|
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
c.count++
|
||||||
|
c.sum.AddNumber(kind, number)
|
||||||
|
if number.CompareNumber(kind, c.min) < 0 {
|
||||||
|
c.min = number
|
||||||
|
}
|
||||||
|
if number.CompareNumber(kind, c.max) > 0 {
|
||||||
|
c.max = number
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge combines two data sets into one.
|
||||||
|
func (c *Aggregator) Merge(oa export.Aggregator, desc *sdkapi.Descriptor) error {
|
||||||
|
o, _ := oa.(*Aggregator)
|
||||||
|
if o == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(c, oa)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.count += o.count
|
||||||
|
c.sum.AddNumber(desc.NumberKind(), o.sum)
|
||||||
|
|
||||||
|
if c.min.CompareNumber(desc.NumberKind(), o.min) > 0 {
|
||||||
|
c.min.SetNumber(o.min)
|
||||||
|
}
|
||||||
|
if c.max.CompareNumber(desc.NumberKind(), o.max) < 0 {
|
||||||
|
c.max.SetNumber(o.max)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
106
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/sum/sum.go
generated
vendored
Normal file
106
vendor/go.opentelemetry.io/otel/sdk/metric/aggregator/sum/sum.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
// Copyright The 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 sum // import "go.opentelemetry.io/otel/sdk/metric/aggregator/sum"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Aggregator aggregates counter events.
|
||||||
|
type Aggregator struct {
|
||||||
|
// current holds current increments to this counter record
|
||||||
|
// current needs to be aligned for 64-bit atomic operations.
|
||||||
|
value number.Number
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ export.Aggregator = &Aggregator{}
|
||||||
|
var _ export.Subtractor = &Aggregator{}
|
||||||
|
var _ aggregation.Sum = &Aggregator{}
|
||||||
|
|
||||||
|
// New returns a new counter aggregator implemented by atomic
|
||||||
|
// operations. This aggregator implements the aggregation.Sum
|
||||||
|
// export interface.
|
||||||
|
func New(cnt int) []Aggregator {
|
||||||
|
return make([]Aggregator, cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregation returns an interface for reading the state of this aggregator.
|
||||||
|
func (c *Aggregator) Aggregation() aggregation.Aggregation {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns aggregation.SumKind.
|
||||||
|
func (c *Aggregator) Kind() aggregation.Kind {
|
||||||
|
return aggregation.SumKind
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum returns the last-checkpointed sum. This will never return an
|
||||||
|
// error.
|
||||||
|
func (c *Aggregator) Sum() (number.Number, error) {
|
||||||
|
return c.value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SynchronizedMove atomically saves the current value into oa and resets the
|
||||||
|
// current sum to zero.
|
||||||
|
func (c *Aggregator) SynchronizedMove(oa export.Aggregator, _ *sdkapi.Descriptor) error {
|
||||||
|
if oa == nil {
|
||||||
|
c.value.SetRawAtomic(0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
o, _ := oa.(*Aggregator)
|
||||||
|
if o == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(c, oa)
|
||||||
|
}
|
||||||
|
o.value = c.value.SwapNumberAtomic(number.Number(0))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update atomically adds to the current value.
|
||||||
|
func (c *Aggregator) Update(_ context.Context, num number.Number, desc *sdkapi.Descriptor) error {
|
||||||
|
c.value.AddNumberAtomic(desc.NumberKind(), num)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge combines two counters by adding their sums.
|
||||||
|
func (c *Aggregator) Merge(oa export.Aggregator, desc *sdkapi.Descriptor) error {
|
||||||
|
o, _ := oa.(*Aggregator)
|
||||||
|
if o == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(c, oa)
|
||||||
|
}
|
||||||
|
c.value.AddNumber(desc.NumberKind(), o.value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Aggregator) Subtract(opAgg, resAgg export.Aggregator, descriptor *sdkapi.Descriptor) error {
|
||||||
|
op, _ := opAgg.(*Aggregator)
|
||||||
|
if op == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(c, opAgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, _ := resAgg.(*Aggregator)
|
||||||
|
if res == nil {
|
||||||
|
return aggregator.NewInconsistentAggregatorError(c, resAgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
res.value = c.value
|
||||||
|
res.value.AddNumber(descriptor.NumberKind(), number.NewNumberSignChange(descriptor.NumberKind(), op.value))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
24
vendor/go.opentelemetry.io/otel/sdk/metric/atomicfields.go
generated
vendored
Normal file
24
vendor/go.opentelemetry.io/otel/sdk/metric/atomicfields.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright The 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 "go.opentelemetry.io/otel/sdk/metric"
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func AtomicFieldOffsets() map[string]uintptr {
|
||||||
|
return map[string]uintptr{
|
||||||
|
"record.refMapped.value": unsafe.Offsetof(record{}.refMapped.value),
|
||||||
|
"record.updateCount": unsafe.Offsetof(record{}.updateCount),
|
||||||
|
}
|
||||||
|
}
|
||||||
126
vendor/go.opentelemetry.io/otel/sdk/metric/controller/basic/config.go
generated
vendored
Normal file
126
vendor/go.opentelemetry.io/otel/sdk/metric/controller/basic/config.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
// Copyright The 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 basic // import "go.opentelemetry.io/otel/sdk/metric/controller/basic"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
// config contains configuration for a basic Controller.
|
||||||
|
type config struct {
|
||||||
|
// Resource is the OpenTelemetry resource associated with all Meters
|
||||||
|
// created by the Controller.
|
||||||
|
Resource *resource.Resource
|
||||||
|
|
||||||
|
// CollectPeriod is the interval between calls to Collect a
|
||||||
|
// checkpoint.
|
||||||
|
//
|
||||||
|
// When pulling metrics and not exporting, this is the minimum
|
||||||
|
// time between calls to Collect. In a pull-only
|
||||||
|
// configuration, collection is performed on demand; set
|
||||||
|
// CollectPeriod to 0 always recompute the export record set.
|
||||||
|
//
|
||||||
|
// When exporting metrics, this must be > 0.
|
||||||
|
//
|
||||||
|
// Default value is 10s.
|
||||||
|
CollectPeriod time.Duration
|
||||||
|
|
||||||
|
// CollectTimeout is the timeout of the Context passed to
|
||||||
|
// Collect() and subsequently to Observer instrument callbacks.
|
||||||
|
//
|
||||||
|
// Default value is 10s. If zero, no Collect timeout is applied.
|
||||||
|
CollectTimeout time.Duration
|
||||||
|
|
||||||
|
// Exporter is used for exporting metric data.
|
||||||
|
//
|
||||||
|
// Note: Exporters such as Prometheus that pull data do not implement
|
||||||
|
// export.Exporter. These will directly call Collect() and ForEach().
|
||||||
|
Exporter export.Exporter
|
||||||
|
|
||||||
|
// PushTimeout is the timeout of the Context when a exporter is configured.
|
||||||
|
//
|
||||||
|
// Default value is 10s. If zero, no Export timeout is applied.
|
||||||
|
PushTimeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option is the interface that applies the value to a configuration option.
|
||||||
|
type Option interface {
|
||||||
|
// apply sets the Option value of a Config.
|
||||||
|
apply(*config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithResource sets the Resource configuration option of a Config by merging it
|
||||||
|
// with the Resource configuration in the environment.
|
||||||
|
func WithResource(r *resource.Resource) Option {
|
||||||
|
return resourceOption{r}
|
||||||
|
}
|
||||||
|
|
||||||
|
type resourceOption struct{ *resource.Resource }
|
||||||
|
|
||||||
|
func (o resourceOption) apply(cfg *config) {
|
||||||
|
res, err := resource.Merge(cfg.Resource, o.Resource)
|
||||||
|
if err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
}
|
||||||
|
cfg.Resource = res
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCollectPeriod sets the CollectPeriod configuration option of a Config.
|
||||||
|
func WithCollectPeriod(period time.Duration) Option {
|
||||||
|
return collectPeriodOption(period)
|
||||||
|
}
|
||||||
|
|
||||||
|
type collectPeriodOption time.Duration
|
||||||
|
|
||||||
|
func (o collectPeriodOption) apply(cfg *config) {
|
||||||
|
cfg.CollectPeriod = time.Duration(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCollectTimeout sets the CollectTimeout configuration option of a Config.
|
||||||
|
func WithCollectTimeout(timeout time.Duration) Option {
|
||||||
|
return collectTimeoutOption(timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
type collectTimeoutOption time.Duration
|
||||||
|
|
||||||
|
func (o collectTimeoutOption) apply(cfg *config) {
|
||||||
|
cfg.CollectTimeout = time.Duration(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithExporter sets the exporter configuration option of a Config.
|
||||||
|
func WithExporter(exporter export.Exporter) Option {
|
||||||
|
return exporterOption{exporter}
|
||||||
|
}
|
||||||
|
|
||||||
|
type exporterOption struct{ exporter export.Exporter }
|
||||||
|
|
||||||
|
func (o exporterOption) apply(cfg *config) {
|
||||||
|
cfg.Exporter = o.exporter
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPushTimeout sets the PushTimeout configuration option of a Config.
|
||||||
|
func WithPushTimeout(timeout time.Duration) Option {
|
||||||
|
return pushTimeoutOption(timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
type pushTimeoutOption time.Duration
|
||||||
|
|
||||||
|
func (o pushTimeoutOption) apply(cfg *config) {
|
||||||
|
cfg.PushTimeout = time.Duration(o)
|
||||||
|
}
|
||||||
388
vendor/go.opentelemetry.io/otel/sdk/metric/controller/basic/controller.go
generated
vendored
Normal file
388
vendor/go.opentelemetry.io/otel/sdk/metric/controller/basic/controller.go
generated
vendored
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
// Copyright The 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 basic // import "go.opentelemetry.io/otel/sdk/metric/controller/basic"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/internal/metric/registry"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||||
|
sdk "go.opentelemetry.io/otel/sdk/metric"
|
||||||
|
controllerTime "go.opentelemetry.io/otel/sdk/metric/controller/time"
|
||||||
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultPeriod is used for:
|
||||||
|
//
|
||||||
|
// - the minimum time between calls to Collect()
|
||||||
|
// - the timeout for Export()
|
||||||
|
// - the timeout for Collect().
|
||||||
|
const DefaultPeriod = 10 * time.Second
|
||||||
|
|
||||||
|
// ErrControllerStarted indicates that a controller was started more
|
||||||
|
// than once.
|
||||||
|
var ErrControllerStarted = fmt.Errorf("controller already started")
|
||||||
|
|
||||||
|
// Controller organizes and synchronizes collection of metric data in
|
||||||
|
// both "pull" and "push" configurations. This supports two distinct
|
||||||
|
// modes:
|
||||||
|
//
|
||||||
|
// - Push and Pull: Start() must be called to begin calling the exporter;
|
||||||
|
// Collect() is called periodically by a background thread after starting
|
||||||
|
// the controller.
|
||||||
|
// - Pull-Only: Start() is optional in this case, to call Collect periodically.
|
||||||
|
// If Start() is not called, Collect() can be called manually to initiate
|
||||||
|
// collection
|
||||||
|
//
|
||||||
|
// The controller supports mixing push and pull access to metric data
|
||||||
|
// using the export.Reader RWLock interface. Collection will
|
||||||
|
// be blocked by a pull request in the basic controller.
|
||||||
|
type Controller struct {
|
||||||
|
// lock protects libraries and synchronizes Start() and Stop().
|
||||||
|
lock sync.Mutex
|
||||||
|
// TODO: libraries is synchronized by lock, but could be
|
||||||
|
// accomplished using a sync.Map. The SDK specification will
|
||||||
|
// probably require this, as the draft already states that
|
||||||
|
// Stop() and MeterProvider.Meter() should not block each
|
||||||
|
// other.
|
||||||
|
libraries map[instrumentation.Library]*registry.UniqueInstrumentMeterImpl
|
||||||
|
checkpointerFactory export.CheckpointerFactory
|
||||||
|
|
||||||
|
resource *resource.Resource
|
||||||
|
exporter export.Exporter
|
||||||
|
wg sync.WaitGroup
|
||||||
|
stopCh chan struct{}
|
||||||
|
clock controllerTime.Clock
|
||||||
|
ticker controllerTime.Ticker
|
||||||
|
|
||||||
|
collectPeriod time.Duration
|
||||||
|
collectTimeout time.Duration
|
||||||
|
pushTimeout time.Duration
|
||||||
|
|
||||||
|
// collectedTime is used only in configurations with no
|
||||||
|
// exporter, when ticker != nil.
|
||||||
|
collectedTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ export.InstrumentationLibraryReader = &Controller{}
|
||||||
|
var _ metric.MeterProvider = &Controller{}
|
||||||
|
|
||||||
|
func (c *Controller) Meter(instrumentationName string, opts ...metric.MeterOption) metric.Meter {
|
||||||
|
cfg := metric.NewMeterConfig(opts...)
|
||||||
|
library := instrumentation.Library{
|
||||||
|
Name: instrumentationName,
|
||||||
|
Version: cfg.InstrumentationVersion(),
|
||||||
|
SchemaURL: cfg.SchemaURL(),
|
||||||
|
}
|
||||||
|
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
m, ok := c.libraries[library]
|
||||||
|
if !ok {
|
||||||
|
checkpointer := c.checkpointerFactory.NewCheckpointer()
|
||||||
|
accumulator := sdk.NewAccumulator(checkpointer)
|
||||||
|
m = registry.NewUniqueInstrumentMeterImpl(&accumulatorCheckpointer{
|
||||||
|
Accumulator: accumulator,
|
||||||
|
checkpointer: checkpointer,
|
||||||
|
library: library,
|
||||||
|
})
|
||||||
|
|
||||||
|
c.libraries[library] = m
|
||||||
|
}
|
||||||
|
return metric.WrapMeterImpl(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
type accumulatorCheckpointer struct {
|
||||||
|
*sdk.Accumulator
|
||||||
|
checkpointer export.Checkpointer
|
||||||
|
library instrumentation.Library
|
||||||
|
}
|
||||||
|
|
||||||
|
// New constructs a Controller using the provided checkpointer factory
|
||||||
|
// and options (including optional exporter) to configure a metric
|
||||||
|
// export pipeline.
|
||||||
|
func New(checkpointerFactory export.CheckpointerFactory, opts ...Option) *Controller {
|
||||||
|
c := &config{
|
||||||
|
CollectPeriod: DefaultPeriod,
|
||||||
|
CollectTimeout: DefaultPeriod,
|
||||||
|
PushTimeout: DefaultPeriod,
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt.apply(c)
|
||||||
|
}
|
||||||
|
if c.Resource == nil {
|
||||||
|
c.Resource = resource.Default()
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
c.Resource, err = resource.Merge(resource.Environment(), c.Resource)
|
||||||
|
if err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &Controller{
|
||||||
|
libraries: map[instrumentation.Library]*registry.UniqueInstrumentMeterImpl{},
|
||||||
|
checkpointerFactory: checkpointerFactory,
|
||||||
|
exporter: c.Exporter,
|
||||||
|
resource: c.Resource,
|
||||||
|
stopCh: nil,
|
||||||
|
clock: controllerTime.RealClock{},
|
||||||
|
|
||||||
|
collectPeriod: c.CollectPeriod,
|
||||||
|
collectTimeout: c.CollectTimeout,
|
||||||
|
pushTimeout: c.PushTimeout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetClock supports setting a mock clock for testing. This must be
|
||||||
|
// called before Start().
|
||||||
|
func (c *Controller) SetClock(clock controllerTime.Clock) {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
c.clock = clock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resource returns the *resource.Resource associated with this
|
||||||
|
// controller.
|
||||||
|
func (c *Controller) Resource() *resource.Resource {
|
||||||
|
return c.resource
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start begins a ticker that periodically collects and exports
|
||||||
|
// metrics with the configured interval. This is required for calling
|
||||||
|
// a configured Exporter (see WithExporter) and is otherwise optional
|
||||||
|
// when only pulling metric data.
|
||||||
|
//
|
||||||
|
// The passed context is passed to Collect() and subsequently to
|
||||||
|
// asynchronous instrument callbacks. Returns an error when the
|
||||||
|
// controller was already started.
|
||||||
|
//
|
||||||
|
// Note that it is not necessary to Start a controller when only
|
||||||
|
// pulling data; use the Collect() and ForEach() methods directly in
|
||||||
|
// this case.
|
||||||
|
func (c *Controller) Start(ctx context.Context) error {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
if c.stopCh != nil {
|
||||||
|
return ErrControllerStarted
|
||||||
|
}
|
||||||
|
|
||||||
|
c.wg.Add(1)
|
||||||
|
c.stopCh = make(chan struct{})
|
||||||
|
c.ticker = c.clock.Ticker(c.collectPeriod)
|
||||||
|
go c.runTicker(ctx, c.stopCh)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop waits for the background goroutine to return and then collects
|
||||||
|
// and exports metrics one last time before returning. The passed
|
||||||
|
// context is passed to the final Collect() and subsequently to the
|
||||||
|
// final asynchronous instruments.
|
||||||
|
//
|
||||||
|
// Note that Stop() will not cancel an ongoing collection or export.
|
||||||
|
func (c *Controller) Stop(ctx context.Context) error {
|
||||||
|
if lastCollection := func() bool {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
if c.stopCh == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
close(c.stopCh)
|
||||||
|
c.stopCh = nil
|
||||||
|
c.wg.Wait()
|
||||||
|
c.ticker.Stop()
|
||||||
|
c.ticker = nil
|
||||||
|
return true
|
||||||
|
}(); !lastCollection {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.collect(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// runTicker collection on ticker events until the stop channel is closed.
|
||||||
|
func (c *Controller) runTicker(ctx context.Context, stopCh chan struct{}) {
|
||||||
|
defer c.wg.Done()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-stopCh:
|
||||||
|
return
|
||||||
|
case <-c.ticker.C():
|
||||||
|
if err := c.collect(ctx); err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect computes a checkpoint and optionally exports it.
|
||||||
|
func (c *Controller) collect(ctx context.Context) error {
|
||||||
|
if err := c.checkpoint(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.exporter == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: this is not subject to collectTimeout. This blocks the next
|
||||||
|
// collection despite collectTimeout because it holds a lock.
|
||||||
|
return c.export(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// accumulatorList returns a snapshot of current accumulators
|
||||||
|
// registered to this controller. This briefly locks the controller.
|
||||||
|
func (c *Controller) accumulatorList() []*accumulatorCheckpointer {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
var r []*accumulatorCheckpointer
|
||||||
|
for _, entry := range c.libraries {
|
||||||
|
acc, ok := entry.MeterImpl().(*accumulatorCheckpointer)
|
||||||
|
if ok {
|
||||||
|
r = append(r, acc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkpoint calls the Accumulator and Checkpointer interfaces to
|
||||||
|
// compute the Reader. This applies the configured collection
|
||||||
|
// timeout. Note that this does not try to cancel a Collect or Export
|
||||||
|
// when Stop() is called.
|
||||||
|
func (c *Controller) checkpoint(ctx context.Context) error {
|
||||||
|
for _, impl := range c.accumulatorList() {
|
||||||
|
if err := c.checkpointSingleAccumulator(ctx, impl); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkpointSingleAccumulator checkpoints a single instrumentation
|
||||||
|
// library's accumulator, which involves calling
|
||||||
|
// checkpointer.StartCollection, accumulator.Collect, and
|
||||||
|
// checkpointer.FinishCollection in sequence.
|
||||||
|
func (c *Controller) checkpointSingleAccumulator(ctx context.Context, ac *accumulatorCheckpointer) error {
|
||||||
|
ckpt := ac.checkpointer.Reader()
|
||||||
|
ckpt.Lock()
|
||||||
|
defer ckpt.Unlock()
|
||||||
|
|
||||||
|
ac.checkpointer.StartCollection()
|
||||||
|
|
||||||
|
if c.collectTimeout > 0 {
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
ctx, cancel = context.WithTimeout(ctx, c.collectTimeout)
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = ac.Accumulator.Collect(ctx)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
err = ctx.Err()
|
||||||
|
default:
|
||||||
|
// The context wasn't done, ok.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish the checkpoint whether the accumulator timed out or not.
|
||||||
|
if cerr := ac.checkpointer.FinishCollection(); cerr != nil {
|
||||||
|
if err == nil {
|
||||||
|
err = cerr
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("%s: %w", cerr.Error(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// export calls the exporter with a read lock on the Reader,
|
||||||
|
// applying the configured export timeout.
|
||||||
|
func (c *Controller) export(ctx context.Context) error {
|
||||||
|
if c.pushTimeout > 0 {
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
ctx, cancel = context.WithTimeout(ctx, c.pushTimeout)
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.exporter.Export(ctx, c.resource, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForEach implements export.InstrumentationLibraryReader.
|
||||||
|
func (c *Controller) ForEach(readerFunc func(l instrumentation.Library, r export.Reader) error) error {
|
||||||
|
for _, acPair := range c.accumulatorList() {
|
||||||
|
reader := acPair.checkpointer.Reader()
|
||||||
|
// TODO: We should not fail fast; instead accumulate errors.
|
||||||
|
if err := func() error {
|
||||||
|
reader.RLock()
|
||||||
|
defer reader.RUnlock()
|
||||||
|
return readerFunc(acPair.library, reader)
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRunning returns true if the controller was started via Start(),
|
||||||
|
// indicating that the current export.Reader is being kept
|
||||||
|
// up-to-date.
|
||||||
|
func (c *Controller) IsRunning() bool {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
return c.ticker != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect requests a collection. The collection will be skipped if
|
||||||
|
// the last collection is aged less than the configured collection
|
||||||
|
// period.
|
||||||
|
func (c *Controller) Collect(ctx context.Context) error {
|
||||||
|
if c.IsRunning() {
|
||||||
|
// When there's a non-nil ticker, there's a goroutine
|
||||||
|
// computing checkpoints with the collection period.
|
||||||
|
return ErrControllerStarted
|
||||||
|
}
|
||||||
|
if !c.shouldCollect() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.checkpoint(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// shouldCollect returns true if the collector should collect now,
|
||||||
|
// based on the timestamp, the last collection time, and the
|
||||||
|
// configured period.
|
||||||
|
func (c *Controller) shouldCollect() bool {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
if c.collectPeriod == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
now := c.clock.Now()
|
||||||
|
if now.Sub(c.collectedTime) < c.collectPeriod {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
c.collectedTime = now
|
||||||
|
return true
|
||||||
|
}
|
||||||
59
vendor/go.opentelemetry.io/otel/sdk/metric/controller/time/time.go
generated
vendored
Normal file
59
vendor/go.opentelemetry.io/otel/sdk/metric/controller/time/time.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// Copyright The 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 time // import "go.opentelemetry.io/otel/sdk/metric/controller/time"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
lib "time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Several types below are created to match "github.com/benbjohnson/clock"
|
||||||
|
// so that it remains a test-only dependency.
|
||||||
|
|
||||||
|
type Clock interface {
|
||||||
|
Now() lib.Time
|
||||||
|
Ticker(duration lib.Duration) Ticker
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ticker interface {
|
||||||
|
Stop()
|
||||||
|
C() <-chan lib.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type RealClock struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type RealTicker struct {
|
||||||
|
ticker *lib.Ticker
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Clock = RealClock{}
|
||||||
|
var _ Ticker = RealTicker{}
|
||||||
|
|
||||||
|
func (RealClock) Now() time.Time {
|
||||||
|
return time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (RealClock) Ticker(period time.Duration) Ticker {
|
||||||
|
return RealTicker{time.NewTicker(period)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t RealTicker) Stop() {
|
||||||
|
t.ticker.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t RealTicker) C() <-chan time.Time {
|
||||||
|
return t.ticker.C
|
||||||
|
}
|
||||||
141
vendor/go.opentelemetry.io/otel/sdk/metric/doc.go
generated
vendored
Normal file
141
vendor/go.opentelemetry.io/otel/sdk/metric/doc.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
// Copyright The 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 implements the OpenTelemetry metric API.
|
||||||
|
|
||||||
|
This package is currently in a pre-GA phase. Backwards incompatible changes
|
||||||
|
may be introduced in subsequent minor version releases as we work to track the
|
||||||
|
evolving OpenTelemetry specification and user feedback.
|
||||||
|
|
||||||
|
The Accumulator type supports configurable metrics export behavior through a
|
||||||
|
collection of export interfaces that support various export strategies,
|
||||||
|
described below.
|
||||||
|
|
||||||
|
The OpenTelemetry metric API consists of methods for constructing synchronous
|
||||||
|
and asynchronous instruments. There are two constructors per instrument for
|
||||||
|
the two kinds of number (int64, float64).
|
||||||
|
|
||||||
|
Synchronous instruments are managed by a sync.Map containing a *record
|
||||||
|
with the current state for each synchronous instrument. A bound
|
||||||
|
instrument encapsulates a direct pointer to the record, allowing
|
||||||
|
bound metric events to bypass a sync.Map lookup. A lock-free
|
||||||
|
algorithm is used to protect against races when adding and removing
|
||||||
|
items from the sync.Map.
|
||||||
|
|
||||||
|
Asynchronous instruments are managed by an internal
|
||||||
|
AsyncInstrumentState, which coordinates calling batch and single
|
||||||
|
instrument callbacks.
|
||||||
|
|
||||||
|
Internal Structure
|
||||||
|
|
||||||
|
Each observer also has its own kind of record stored in the SDK. This
|
||||||
|
record contains a set of recorders for every specific label set used in the
|
||||||
|
callback.
|
||||||
|
|
||||||
|
A sync.Map maintains the mapping of current instruments and label sets to
|
||||||
|
internal records. To create a new bound instrument, the SDK consults the Map to
|
||||||
|
locate an existing record, otherwise it constructs a new record. The SDK
|
||||||
|
maintains a count of the number of references to each record, ensuring
|
||||||
|
that records are not reclaimed from the Map while they are still active
|
||||||
|
from the user's perspective.
|
||||||
|
|
||||||
|
Metric collection is performed via a single-threaded call to Collect that
|
||||||
|
sweeps through all records in the SDK, checkpointing their state. When a
|
||||||
|
record is discovered that has no references and has not been updated since
|
||||||
|
the prior collection pass, it is removed from the Map.
|
||||||
|
|
||||||
|
Both synchronous and asynchronous instruments have an associated
|
||||||
|
aggregator, which maintains the current state resulting from all metric
|
||||||
|
events since its last checkpoint. Aggregators may be lock-free or they may
|
||||||
|
use locking, but they should expect to be called concurrently. Aggregators
|
||||||
|
must be capable of merging with another aggregator of the same type.
|
||||||
|
|
||||||
|
Export Pipeline
|
||||||
|
|
||||||
|
While the SDK serves to maintain a current set of records and
|
||||||
|
coordinate collection, the behavior of a metrics export pipeline is
|
||||||
|
configured through the export types in
|
||||||
|
go.opentelemetry.io/otel/sdk/export/metric. It is important to keep
|
||||||
|
in mind the context these interfaces are called from. There are two
|
||||||
|
contexts, instrumentation context, where a user-level goroutine that
|
||||||
|
enters the SDK resulting in a new record, and collection context,
|
||||||
|
where a system-level thread performs a collection pass through the
|
||||||
|
SDK.
|
||||||
|
|
||||||
|
Descriptor is a struct that describes the metric instrument to the
|
||||||
|
export pipeline, containing the name, units, description, metric kind,
|
||||||
|
number kind (int64 or float64). A Descriptor accompanies metric data
|
||||||
|
as it passes through the export pipeline.
|
||||||
|
|
||||||
|
The AggregatorSelector interface supports choosing the method of
|
||||||
|
aggregation to apply to a particular instrument, by delegating the
|
||||||
|
construction of an Aggregator to this interface. Given the Descriptor,
|
||||||
|
the AggregatorFor method returns an implementation of Aggregator. If this
|
||||||
|
interface returns nil, the metric will be disabled. The aggregator should
|
||||||
|
be matched to the capabilities of the exporter. Selecting the aggregator
|
||||||
|
for Adding instruments is relatively straightforward, but many options
|
||||||
|
are available for aggregating distributions from Grouping instruments.
|
||||||
|
|
||||||
|
Aggregator is an interface which implements a concrete strategy for
|
||||||
|
aggregating metric updates. Several Aggregator implementations are
|
||||||
|
provided by the SDK. Aggregators may be lock-free or use locking,
|
||||||
|
depending on their structure and semantics. Aggregators implement an
|
||||||
|
Update method, called in instrumentation context, to receive a single
|
||||||
|
metric event. Aggregators implement a Checkpoint method, called in
|
||||||
|
collection context, to save a checkpoint of the current state.
|
||||||
|
Aggregators implement a Merge method, also called in collection
|
||||||
|
context, that combines state from two aggregators into one. Each SDK
|
||||||
|
record has an associated aggregator.
|
||||||
|
|
||||||
|
Processor is an interface which sits between the SDK and an exporter.
|
||||||
|
The Processor embeds an AggregatorSelector, used by the SDK to assign
|
||||||
|
new Aggregators. The Processor supports a Process() API for submitting
|
||||||
|
checkpointed aggregators to the processor, and a Reader() API
|
||||||
|
for producing a complete checkpoint for the exporter. Two default
|
||||||
|
Processor implementations are provided, the "defaultkeys" Processor groups
|
||||||
|
aggregate metrics by their recommended Descriptor.Keys(), the
|
||||||
|
"simple" Processor aggregates metrics at full dimensionality.
|
||||||
|
|
||||||
|
LabelEncoder is an optional optimization that allows an exporter to
|
||||||
|
provide the serialization logic for labels. This allows avoiding
|
||||||
|
duplicate serialization of labels, once as a unique key in the SDK (or
|
||||||
|
Processor) and once in the exporter.
|
||||||
|
|
||||||
|
Reader is an interface between the Processor and the Exporter.
|
||||||
|
After completing a collection pass, the Processor.Reader() method
|
||||||
|
returns a Reader, which the Exporter uses to iterate over all
|
||||||
|
the updated metrics.
|
||||||
|
|
||||||
|
Record is a struct containing the state of an individual exported
|
||||||
|
metric. This is the result of one collection interface for one
|
||||||
|
instrument and one label set.
|
||||||
|
|
||||||
|
Labels is a struct containing an ordered set of labels, the
|
||||||
|
corresponding unique encoding, and the encoder that produced it.
|
||||||
|
|
||||||
|
Exporter is the final stage of an export pipeline. It is called with
|
||||||
|
a Reader capable of enumerating all the updated metrics.
|
||||||
|
|
||||||
|
Controller is not an export interface per se, but it orchestrates the
|
||||||
|
export pipeline. For example, a "push" controller will establish a
|
||||||
|
periodic timer to regularly collect and export metrics. A "pull"
|
||||||
|
controller will await a pull request before initiating metric
|
||||||
|
collection. Either way, the job of the controller is to call the SDK
|
||||||
|
Collect() method, then read the checkpoint, then invoke the exporter.
|
||||||
|
Controllers are expected to implement the public metric.MeterProvider
|
||||||
|
API, meaning they can be installed as the global Meter provider.
|
||||||
|
|
||||||
|
*/
|
||||||
|
package metric // import "go.opentelemetry.io/otel/sdk/metric"
|
||||||
396
vendor/go.opentelemetry.io/otel/sdk/metric/processor/basic/basic.go
generated
vendored
Normal file
396
vendor/go.opentelemetry.io/otel/sdk/metric/processor/basic/basic.go
generated
vendored
Normal file
@@ -0,0 +1,396 @@
|
|||||||
|
// Copyright The 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 basic // import "go.opentelemetry.io/otel/sdk/metric/processor/basic"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Processor struct {
|
||||||
|
aggregation.TemporalitySelector
|
||||||
|
export.AggregatorSelector
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
stateKey struct {
|
||||||
|
// TODO: This code is organized to support multiple
|
||||||
|
// accumulators which could theoretically produce the
|
||||||
|
// data for the same instrument, and this code has
|
||||||
|
// logic to combine data properly from multiple
|
||||||
|
// accumulators. However, the use of
|
||||||
|
// *sdkapi.Descriptor in the stateKey makes such
|
||||||
|
// combination impossible, because each accumulator
|
||||||
|
// allocates its own instruments. This can be fixed
|
||||||
|
// by using the instrument name and kind instead of
|
||||||
|
// the descriptor pointer. See
|
||||||
|
// https://github.com/open-telemetry/opentelemetry-go/issues/862.
|
||||||
|
descriptor *sdkapi.Descriptor
|
||||||
|
distinct attribute.Distinct
|
||||||
|
}
|
||||||
|
|
||||||
|
stateValue struct {
|
||||||
|
// labels corresponds to the stateKey.distinct field.
|
||||||
|
labels *attribute.Set
|
||||||
|
|
||||||
|
// updated indicates the last sequence number when this value had
|
||||||
|
// Process() called by an accumulator.
|
||||||
|
updated int64
|
||||||
|
|
||||||
|
// stateful indicates that a cumulative aggregation is
|
||||||
|
// being maintained, taken from the process start time.
|
||||||
|
stateful bool
|
||||||
|
|
||||||
|
// currentOwned indicates that "current" was allocated
|
||||||
|
// by the processor in order to merge results from
|
||||||
|
// multiple Accumulators during a single collection
|
||||||
|
// round, which may happen either because:
|
||||||
|
// (1) multiple Accumulators output the same Accumulation.
|
||||||
|
// (2) one Accumulator is configured with dimensionality reduction.
|
||||||
|
currentOwned bool
|
||||||
|
|
||||||
|
// current refers to the output from a single Accumulator
|
||||||
|
// (if !currentOwned) or it refers to an Aggregator
|
||||||
|
// owned by the processor used to accumulate multiple
|
||||||
|
// values in a single collection round.
|
||||||
|
current export.Aggregator
|
||||||
|
|
||||||
|
// delta, if non-nil, refers to an Aggregator owned by
|
||||||
|
// the processor used to compute deltas between
|
||||||
|
// precomputed sums.
|
||||||
|
delta export.Aggregator
|
||||||
|
|
||||||
|
// cumulative, if non-nil, refers to an Aggregator owned
|
||||||
|
// by the processor used to store the last cumulative
|
||||||
|
// value.
|
||||||
|
cumulative export.Aggregator
|
||||||
|
}
|
||||||
|
|
||||||
|
state struct {
|
||||||
|
config config
|
||||||
|
|
||||||
|
// RWMutex implements locking for the `Reader` interface.
|
||||||
|
sync.RWMutex
|
||||||
|
values map[stateKey]*stateValue
|
||||||
|
|
||||||
|
// Note: the timestamp logic currently assumes all
|
||||||
|
// exports are deltas.
|
||||||
|
|
||||||
|
processStart time.Time
|
||||||
|
intervalStart time.Time
|
||||||
|
intervalEnd time.Time
|
||||||
|
|
||||||
|
// startedCollection and finishedCollection are the
|
||||||
|
// number of StartCollection() and FinishCollection()
|
||||||
|
// calls, used to ensure that the sequence of starts
|
||||||
|
// and finishes are correctly balanced.
|
||||||
|
|
||||||
|
startedCollection int64
|
||||||
|
finishedCollection int64
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ export.Processor = &Processor{}
|
||||||
|
var _ export.Checkpointer = &Processor{}
|
||||||
|
var _ export.Reader = &state{}
|
||||||
|
|
||||||
|
// ErrInconsistentState is returned when the sequence of collection's starts and finishes are incorrectly balanced.
|
||||||
|
var ErrInconsistentState = fmt.Errorf("inconsistent processor state")
|
||||||
|
|
||||||
|
// ErrInvalidTemporality is returned for unknown metric.Temporality.
|
||||||
|
var ErrInvalidTemporality = fmt.Errorf("invalid aggregation temporality")
|
||||||
|
|
||||||
|
// New returns a basic Processor that is also a Checkpointer using the provided
|
||||||
|
// AggregatorSelector to select Aggregators. The TemporalitySelector
|
||||||
|
// is consulted to determine the kind(s) of exporter that will consume
|
||||||
|
// data, so that this Processor can prepare to compute Delta or
|
||||||
|
// Cumulative Aggregations as needed.
|
||||||
|
func New(aselector export.AggregatorSelector, tselector aggregation.TemporalitySelector, opts ...Option) *Processor {
|
||||||
|
return NewFactory(aselector, tselector, opts...).NewCheckpointer().(*Processor)
|
||||||
|
}
|
||||||
|
|
||||||
|
type factory struct {
|
||||||
|
aselector export.AggregatorSelector
|
||||||
|
tselector aggregation.TemporalitySelector
|
||||||
|
config config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFactory(aselector export.AggregatorSelector, tselector aggregation.TemporalitySelector, opts ...Option) export.CheckpointerFactory {
|
||||||
|
var config config
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt.applyProcessor(&config)
|
||||||
|
}
|
||||||
|
return factory{
|
||||||
|
aselector: aselector,
|
||||||
|
tselector: tselector,
|
||||||
|
config: config,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ export.CheckpointerFactory = factory{}
|
||||||
|
|
||||||
|
func (f factory) NewCheckpointer() export.Checkpointer {
|
||||||
|
now := time.Now()
|
||||||
|
p := &Processor{
|
||||||
|
AggregatorSelector: f.aselector,
|
||||||
|
TemporalitySelector: f.tselector,
|
||||||
|
state: state{
|
||||||
|
values: map[stateKey]*stateValue{},
|
||||||
|
processStart: now,
|
||||||
|
intervalStart: now,
|
||||||
|
config: f.config,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process implements export.Processor.
|
||||||
|
func (b *Processor) Process(accum export.Accumulation) error {
|
||||||
|
if b.startedCollection != b.finishedCollection+1 {
|
||||||
|
return ErrInconsistentState
|
||||||
|
}
|
||||||
|
desc := accum.Descriptor()
|
||||||
|
key := stateKey{
|
||||||
|
descriptor: desc,
|
||||||
|
distinct: accum.Labels().Equivalent(),
|
||||||
|
}
|
||||||
|
agg := accum.Aggregator()
|
||||||
|
|
||||||
|
// Check if there is an existing value.
|
||||||
|
value, ok := b.state.values[key]
|
||||||
|
if !ok {
|
||||||
|
stateful := b.TemporalityFor(desc, agg.Aggregation().Kind()).MemoryRequired(desc.InstrumentKind())
|
||||||
|
|
||||||
|
newValue := &stateValue{
|
||||||
|
labels: accum.Labels(),
|
||||||
|
updated: b.state.finishedCollection,
|
||||||
|
stateful: stateful,
|
||||||
|
current: agg,
|
||||||
|
}
|
||||||
|
if stateful {
|
||||||
|
if desc.InstrumentKind().PrecomputedSum() {
|
||||||
|
// If we know we need to compute deltas, allocate two aggregators.
|
||||||
|
b.AggregatorFor(desc, &newValue.cumulative, &newValue.delta)
|
||||||
|
} else {
|
||||||
|
// In this case we are certain not to need a delta, only allocate
|
||||||
|
// a cumulative aggregator.
|
||||||
|
b.AggregatorFor(desc, &newValue.cumulative)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.state.values[key] = newValue
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance the update sequence number.
|
||||||
|
sameCollection := b.state.finishedCollection == value.updated
|
||||||
|
value.updated = b.state.finishedCollection
|
||||||
|
|
||||||
|
// At this point in the code, we have located an existing
|
||||||
|
// value for some stateKey. This can be because:
|
||||||
|
//
|
||||||
|
// (a) stateful aggregation is being used, the entry was
|
||||||
|
// entered during a prior collection, and this is the first
|
||||||
|
// time processing an accumulation for this stateKey in the
|
||||||
|
// current collection. Since this is the first time
|
||||||
|
// processing an accumulation for this stateKey during this
|
||||||
|
// collection, we don't know yet whether there are multiple
|
||||||
|
// accumulators at work. If there are multiple accumulators,
|
||||||
|
// they'll hit case (b) the second time through.
|
||||||
|
//
|
||||||
|
// (b) multiple accumulators are being used, whether stateful
|
||||||
|
// or not.
|
||||||
|
//
|
||||||
|
// Case (a) occurs when the instrument and the exporter
|
||||||
|
// require memory to work correctly, either because the
|
||||||
|
// instrument reports a PrecomputedSum to a DeltaExporter or
|
||||||
|
// the reverse, a non-PrecomputedSum instrument with a
|
||||||
|
// CumulativeExporter. This logic is encapsulated in
|
||||||
|
// Temporality.MemoryRequired(InstrumentKind).
|
||||||
|
//
|
||||||
|
// Case (b) occurs when the variable `sameCollection` is true,
|
||||||
|
// indicating that the stateKey for Accumulation has already
|
||||||
|
// been seen in the same collection. When this happens, it
|
||||||
|
// implies that multiple Accumulators are being used, or that
|
||||||
|
// a single Accumulator has been configured with a label key
|
||||||
|
// filter.
|
||||||
|
|
||||||
|
if !sameCollection {
|
||||||
|
if !value.currentOwned {
|
||||||
|
// This is the first Accumulation we've seen
|
||||||
|
// for this stateKey during this collection.
|
||||||
|
// Just keep a reference to the Accumulator's
|
||||||
|
// Aggregator. All the other cases copy
|
||||||
|
// Aggregator state.
|
||||||
|
value.current = agg
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return agg.SynchronizedMove(value.current, desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the current is not owned, take ownership of a copy
|
||||||
|
// before merging below.
|
||||||
|
if !value.currentOwned {
|
||||||
|
tmp := value.current
|
||||||
|
b.AggregatorSelector.AggregatorFor(desc, &value.current)
|
||||||
|
value.currentOwned = true
|
||||||
|
if err := tmp.SynchronizedMove(value.current, desc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine this Accumulation with the prior Accumulation.
|
||||||
|
return value.current.Merge(agg, desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader returns the associated Reader. Use the
|
||||||
|
// Reader Locker interface to synchronize access to this
|
||||||
|
// object. The Reader.ForEach() method cannot be called
|
||||||
|
// concurrently with Process().
|
||||||
|
func (b *Processor) Reader() export.Reader {
|
||||||
|
return &b.state
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartCollection signals to the Processor one or more Accumulators
|
||||||
|
// will begin calling Process() calls during collection.
|
||||||
|
func (b *Processor) StartCollection() {
|
||||||
|
if b.startedCollection != 0 {
|
||||||
|
b.intervalStart = b.intervalEnd
|
||||||
|
}
|
||||||
|
b.startedCollection++
|
||||||
|
}
|
||||||
|
|
||||||
|
// FinishCollection signals to the Processor that a complete
|
||||||
|
// collection has finished and that ForEach will be called to access
|
||||||
|
// the Reader.
|
||||||
|
func (b *Processor) FinishCollection() error {
|
||||||
|
b.intervalEnd = time.Now()
|
||||||
|
if b.startedCollection != b.finishedCollection+1 {
|
||||||
|
return ErrInconsistentState
|
||||||
|
}
|
||||||
|
defer func() { b.finishedCollection++ }()
|
||||||
|
|
||||||
|
for key, value := range b.values {
|
||||||
|
mkind := key.descriptor.InstrumentKind()
|
||||||
|
stale := value.updated != b.finishedCollection
|
||||||
|
stateless := !value.stateful
|
||||||
|
|
||||||
|
// The following branch updates stateful aggregators. Skip
|
||||||
|
// these updates if the aggregator is not stateful or if the
|
||||||
|
// aggregator is stale.
|
||||||
|
if stale || stateless {
|
||||||
|
// If this processor does not require memeory,
|
||||||
|
// stale, stateless entries can be removed.
|
||||||
|
// This implies that they were not updated
|
||||||
|
// over the previous full collection interval.
|
||||||
|
if stale && stateless && !b.config.Memory {
|
||||||
|
delete(b.values, key)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Aggregator state to support exporting either a
|
||||||
|
// delta or a cumulative aggregation.
|
||||||
|
var err error
|
||||||
|
if mkind.PrecomputedSum() {
|
||||||
|
if currentSubtractor, ok := value.current.(export.Subtractor); ok {
|
||||||
|
// This line is equivalent to:
|
||||||
|
// value.delta = currentSubtractor - value.cumulative
|
||||||
|
err = currentSubtractor.Subtract(value.cumulative, value.delta, key.descriptor)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
err = value.current.SynchronizedMove(value.cumulative, key.descriptor)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = aggregation.ErrNoSubtraction
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This line is equivalent to:
|
||||||
|
// value.cumulative = value.cumulative + value.delta
|
||||||
|
err = value.cumulative.Merge(value.current, key.descriptor)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForEach iterates through the Reader, passing an
|
||||||
|
// export.Record with the appropriate Cumulative or Delta aggregation
|
||||||
|
// to an exporter.
|
||||||
|
func (b *state) ForEach(exporter aggregation.TemporalitySelector, f func(export.Record) error) error {
|
||||||
|
if b.startedCollection != b.finishedCollection {
|
||||||
|
return ErrInconsistentState
|
||||||
|
}
|
||||||
|
for key, value := range b.values {
|
||||||
|
mkind := key.descriptor.InstrumentKind()
|
||||||
|
|
||||||
|
var agg aggregation.Aggregation
|
||||||
|
var start time.Time
|
||||||
|
|
||||||
|
// If the processor does not have Config.Memory and it was not updated
|
||||||
|
// in the prior round, do not visit this value.
|
||||||
|
if !b.config.Memory && value.updated != (b.finishedCollection-1) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
aggTemp := exporter.TemporalityFor(key.descriptor, value.current.Aggregation().Kind())
|
||||||
|
switch aggTemp {
|
||||||
|
case aggregation.CumulativeTemporality:
|
||||||
|
// If stateful, the sum has been computed. If stateless, the
|
||||||
|
// input was already cumulative. Either way, use the checkpointed
|
||||||
|
// value:
|
||||||
|
if value.stateful {
|
||||||
|
agg = value.cumulative.Aggregation()
|
||||||
|
} else {
|
||||||
|
agg = value.current.Aggregation()
|
||||||
|
}
|
||||||
|
start = b.processStart
|
||||||
|
|
||||||
|
case aggregation.DeltaTemporality:
|
||||||
|
// Precomputed sums are a special case.
|
||||||
|
if mkind.PrecomputedSum() {
|
||||||
|
agg = value.delta.Aggregation()
|
||||||
|
} else {
|
||||||
|
agg = value.current.Aggregation()
|
||||||
|
}
|
||||||
|
start = b.intervalStart
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("%v: %w", aggTemp, ErrInvalidTemporality)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := f(export.NewRecord(
|
||||||
|
key.descriptor,
|
||||||
|
value.labels,
|
||||||
|
agg,
|
||||||
|
start,
|
||||||
|
b.intervalEnd,
|
||||||
|
)); err != nil && !errors.Is(err, aggregation.ErrNoData) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
42
vendor/go.opentelemetry.io/otel/sdk/metric/processor/basic/config.go
generated
vendored
Normal file
42
vendor/go.opentelemetry.io/otel/sdk/metric/processor/basic/config.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright The 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 basic // import "go.opentelemetry.io/otel/sdk/metric/processor/basic"
|
||||||
|
|
||||||
|
// config contains the options for configuring a basic metric processor.
|
||||||
|
type config struct {
|
||||||
|
// Memory controls whether the processor remembers metric
|
||||||
|
// instruments and label sets that were previously reported.
|
||||||
|
// When Memory is true, Reader.ForEach() will visit
|
||||||
|
// metrics that were not updated in the most recent interval.
|
||||||
|
Memory bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Option interface {
|
||||||
|
applyProcessor(*config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMemory sets the memory behavior of a Processor. If this is
|
||||||
|
// true, the processor will report metric instruments and label sets
|
||||||
|
// that were previously reported but not updated in the most recent
|
||||||
|
// interval.
|
||||||
|
func WithMemory(memory bool) Option {
|
||||||
|
return memoryOption(memory)
|
||||||
|
}
|
||||||
|
|
||||||
|
type memoryOption bool
|
||||||
|
|
||||||
|
func (m memoryOption) applyProcessor(cfg *config) {
|
||||||
|
cfg.Memory = bool(m)
|
||||||
|
}
|
||||||
59
vendor/go.opentelemetry.io/otel/sdk/metric/refcount_mapped.go
generated
vendored
Normal file
59
vendor/go.opentelemetry.io/otel/sdk/metric/refcount_mapped.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// Copyright The 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 "go.opentelemetry.io/otel/sdk/metric"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// refcountMapped atomically counts the number of references (usages) of an entry
|
||||||
|
// while also keeping a state of mapped/unmapped into a different data structure
|
||||||
|
// (an external map or list for example).
|
||||||
|
//
|
||||||
|
// refcountMapped uses an atomic value where the least significant bit is used to
|
||||||
|
// keep the state of mapping ('1' is used for unmapped and '0' is for mapped) and
|
||||||
|
// the rest of the bits are used for refcounting.
|
||||||
|
type refcountMapped struct {
|
||||||
|
// refcount has to be aligned for 64-bit atomic operations.
|
||||||
|
value int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ref returns true if the entry is still mapped and increases the
|
||||||
|
// reference usages, if unmapped returns false.
|
||||||
|
func (rm *refcountMapped) ref() bool {
|
||||||
|
// Check if this entry was marked as unmapped between the moment
|
||||||
|
// we got a reference to it (or will be removed very soon) and here.
|
||||||
|
return atomic.AddInt64(&rm.value, 2)&1 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rm *refcountMapped) unref() {
|
||||||
|
atomic.AddInt64(&rm.value, -2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tryUnmap flips the mapped bit to "unmapped" state and returns true if both of the
|
||||||
|
// following conditions are true upon entry to this function:
|
||||||
|
// * There are no active references;
|
||||||
|
// * The mapped bit is in "mapped" state.
|
||||||
|
// Otherwise no changes are done to mapped bit and false is returned.
|
||||||
|
func (rm *refcountMapped) tryUnmap() bool {
|
||||||
|
if atomic.LoadInt64(&rm.value) != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return atomic.CompareAndSwapInt64(
|
||||||
|
&rm.value,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
551
vendor/go.opentelemetry.io/otel/sdk/metric/sdk.go
generated
vendored
Normal file
551
vendor/go.opentelemetry.io/otel/sdk/metric/sdk.go
generated
vendored
Normal file
@@ -0,0 +1,551 @@
|
|||||||
|
// Copyright The 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 "go.opentelemetry.io/otel/sdk/metric"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
internal "go.opentelemetry.io/otel/internal/metric"
|
||||||
|
"go.opentelemetry.io/otel/metric/number"
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Accumulator implements the OpenTelemetry Meter API. The
|
||||||
|
// Accumulator is bound to a single export.Processor in
|
||||||
|
// `NewAccumulator()`.
|
||||||
|
//
|
||||||
|
// The Accumulator supports a Collect() API to gather and export
|
||||||
|
// current data. Collect() should be arranged according to
|
||||||
|
// the processor model. Push-based processors will setup a
|
||||||
|
// timer to call Collect() periodically. Pull-based processors
|
||||||
|
// will call Collect() when a pull request arrives.
|
||||||
|
Accumulator struct {
|
||||||
|
// current maps `mapkey` to *record.
|
||||||
|
current sync.Map
|
||||||
|
|
||||||
|
// asyncInstruments is a set of
|
||||||
|
// `*asyncInstrument` instances
|
||||||
|
asyncLock sync.Mutex
|
||||||
|
asyncInstruments *internal.AsyncInstrumentState
|
||||||
|
|
||||||
|
// currentEpoch is the current epoch number. It is
|
||||||
|
// incremented in `Collect()`.
|
||||||
|
currentEpoch int64
|
||||||
|
|
||||||
|
// processor is the configured processor+configuration.
|
||||||
|
processor export.Processor
|
||||||
|
|
||||||
|
// collectLock prevents simultaneous calls to Collect().
|
||||||
|
collectLock sync.Mutex
|
||||||
|
|
||||||
|
// asyncSortSlice has a single purpose - as a temporary
|
||||||
|
// place for sorting during labels creation to avoid
|
||||||
|
// allocation. It is cleared after use.
|
||||||
|
asyncSortSlice attribute.Sortable
|
||||||
|
}
|
||||||
|
|
||||||
|
syncInstrument struct {
|
||||||
|
instrument
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapkey uniquely describes a metric instrument in terms of
|
||||||
|
// its InstrumentID and the encoded form of its labels.
|
||||||
|
mapkey struct {
|
||||||
|
descriptor *sdkapi.Descriptor
|
||||||
|
ordered attribute.Distinct
|
||||||
|
}
|
||||||
|
|
||||||
|
// record maintains the state of one metric instrument. Due
|
||||||
|
// the use of lock-free algorithms, there may be more than one
|
||||||
|
// `record` in existence at a time, although at most one can
|
||||||
|
// be referenced from the `Accumulator.current` map.
|
||||||
|
record struct {
|
||||||
|
// refMapped keeps track of refcounts and the mapping state to the
|
||||||
|
// Accumulator.current map.
|
||||||
|
refMapped refcountMapped
|
||||||
|
|
||||||
|
// updateCount is incremented on every Update.
|
||||||
|
updateCount int64
|
||||||
|
|
||||||
|
// collectedCount is set to updateCount on collection,
|
||||||
|
// supports checking for no updates during a round.
|
||||||
|
collectedCount int64
|
||||||
|
|
||||||
|
// storage is the stored label set for this record,
|
||||||
|
// except in cases where a label set is shared due to
|
||||||
|
// batch recording.
|
||||||
|
storage attribute.Set
|
||||||
|
|
||||||
|
// labels is the processed label set for this record.
|
||||||
|
// this may refer to the `storage` field in another
|
||||||
|
// record if this label set is shared resulting from
|
||||||
|
// `RecordBatch`.
|
||||||
|
labels *attribute.Set
|
||||||
|
|
||||||
|
// sortSlice has a single purpose - as a temporary
|
||||||
|
// place for sorting during labels creation to avoid
|
||||||
|
// allocation.
|
||||||
|
sortSlice attribute.Sortable
|
||||||
|
|
||||||
|
// inst is a pointer to the corresponding instrument.
|
||||||
|
inst *syncInstrument
|
||||||
|
|
||||||
|
// current implements the actual RecordOne() API,
|
||||||
|
// depending on the type of aggregation. If nil, the
|
||||||
|
// metric was disabled by the exporter.
|
||||||
|
current export.Aggregator
|
||||||
|
checkpoint export.Aggregator
|
||||||
|
}
|
||||||
|
|
||||||
|
instrument struct {
|
||||||
|
meter *Accumulator
|
||||||
|
descriptor sdkapi.Descriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncInstrument struct {
|
||||||
|
instrument
|
||||||
|
// recorders maps ordered labels to the pair of
|
||||||
|
// labelset and recorder
|
||||||
|
recorders map[attribute.Distinct]*labeledRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
labeledRecorder struct {
|
||||||
|
observedEpoch int64
|
||||||
|
labels *attribute.Set
|
||||||
|
observed export.Aggregator
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ sdkapi.MeterImpl = &Accumulator{}
|
||||||
|
_ sdkapi.AsyncImpl = &asyncInstrument{}
|
||||||
|
_ sdkapi.SyncImpl = &syncInstrument{}
|
||||||
|
_ sdkapi.BoundSyncImpl = &record{}
|
||||||
|
|
||||||
|
// ErrUninitializedInstrument is returned when an instrument is used when uninitialized.
|
||||||
|
ErrUninitializedInstrument = fmt.Errorf("use of an uninitialized instrument")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (inst *instrument) Descriptor() sdkapi.Descriptor {
|
||||||
|
return inst.descriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *asyncInstrument) Implementation() interface{} {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncInstrument) Implementation() interface{} {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *asyncInstrument) observe(num number.Number, labels *attribute.Set) {
|
||||||
|
if err := aggregator.RangeTest(num, &a.descriptor); err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
recorder := a.getRecorder(labels)
|
||||||
|
if recorder == nil {
|
||||||
|
// The instrument is disabled according to the
|
||||||
|
// AggregatorSelector.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := recorder.Update(context.Background(), num, &a.descriptor); err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *asyncInstrument) getRecorder(labels *attribute.Set) export.Aggregator {
|
||||||
|
lrec, ok := a.recorders[labels.Equivalent()]
|
||||||
|
if ok {
|
||||||
|
// Note: SynchronizedMove(nil) can't return an error
|
||||||
|
_ = lrec.observed.SynchronizedMove(nil, &a.descriptor)
|
||||||
|
lrec.observedEpoch = a.meter.currentEpoch
|
||||||
|
a.recorders[labels.Equivalent()] = lrec
|
||||||
|
return lrec.observed
|
||||||
|
}
|
||||||
|
var rec export.Aggregator
|
||||||
|
a.meter.processor.AggregatorFor(&a.descriptor, &rec)
|
||||||
|
if a.recorders == nil {
|
||||||
|
a.recorders = make(map[attribute.Distinct]*labeledRecorder)
|
||||||
|
}
|
||||||
|
// This may store nil recorder in the map, thus disabling the
|
||||||
|
// asyncInstrument for the labelset for good. This is intentional,
|
||||||
|
// but will be revisited later.
|
||||||
|
a.recorders[labels.Equivalent()] = &labeledRecorder{
|
||||||
|
observed: rec,
|
||||||
|
labels: labels,
|
||||||
|
observedEpoch: a.meter.currentEpoch,
|
||||||
|
}
|
||||||
|
return rec
|
||||||
|
}
|
||||||
|
|
||||||
|
// acquireHandle gets or creates a `*record` corresponding to `kvs`,
|
||||||
|
// the input labels. The second argument `labels` is passed in to
|
||||||
|
// support re-use of the orderedLabels computed by a previous
|
||||||
|
// measurement in the same batch. This performs two allocations
|
||||||
|
// in the common case.
|
||||||
|
func (s *syncInstrument) acquireHandle(kvs []attribute.KeyValue, labelPtr *attribute.Set) *record {
|
||||||
|
var rec *record
|
||||||
|
var equiv attribute.Distinct
|
||||||
|
|
||||||
|
if labelPtr == nil {
|
||||||
|
// This memory allocation may not be used, but it's
|
||||||
|
// needed for the `sortSlice` field, to avoid an
|
||||||
|
// allocation while sorting.
|
||||||
|
rec = &record{}
|
||||||
|
rec.storage = attribute.NewSetWithSortable(kvs, &rec.sortSlice)
|
||||||
|
rec.labels = &rec.storage
|
||||||
|
equiv = rec.storage.Equivalent()
|
||||||
|
} else {
|
||||||
|
equiv = labelPtr.Equivalent()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create lookup key for sync.Map (one allocation, as this
|
||||||
|
// passes through an interface{})
|
||||||
|
mk := mapkey{
|
||||||
|
descriptor: &s.descriptor,
|
||||||
|
ordered: equiv,
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual, ok := s.meter.current.Load(mk); ok {
|
||||||
|
// Existing record case.
|
||||||
|
existingRec := actual.(*record)
|
||||||
|
if existingRec.refMapped.ref() {
|
||||||
|
// At this moment it is guaranteed that the entry is in
|
||||||
|
// the map and will not be removed.
|
||||||
|
return existingRec
|
||||||
|
}
|
||||||
|
// This entry is no longer mapped, try to add a new entry.
|
||||||
|
}
|
||||||
|
|
||||||
|
if rec == nil {
|
||||||
|
rec = &record{}
|
||||||
|
rec.labels = labelPtr
|
||||||
|
}
|
||||||
|
rec.refMapped = refcountMapped{value: 2}
|
||||||
|
rec.inst = s
|
||||||
|
|
||||||
|
s.meter.processor.AggregatorFor(&s.descriptor, &rec.current, &rec.checkpoint)
|
||||||
|
|
||||||
|
for {
|
||||||
|
// Load/Store: there's a memory allocation to place `mk` into
|
||||||
|
// an interface here.
|
||||||
|
if actual, loaded := s.meter.current.LoadOrStore(mk, rec); loaded {
|
||||||
|
// Existing record case. Cannot change rec here because if fail
|
||||||
|
// will try to add rec again to avoid new allocations.
|
||||||
|
oldRec := actual.(*record)
|
||||||
|
if oldRec.refMapped.ref() {
|
||||||
|
// At this moment it is guaranteed that the entry is in
|
||||||
|
// the map and will not be removed.
|
||||||
|
return oldRec
|
||||||
|
}
|
||||||
|
// This loaded entry is marked as unmapped (so Collect will remove
|
||||||
|
// it from the map immediately), try again - this is a busy waiting
|
||||||
|
// strategy to wait until Collect() removes this entry from the map.
|
||||||
|
//
|
||||||
|
// This can be improved by having a list of "Unmapped" entries for
|
||||||
|
// one time only usages, OR we can make this a blocking path and use
|
||||||
|
// a Mutex that protects the delete operation (delete only if the old
|
||||||
|
// record is associated with the key).
|
||||||
|
|
||||||
|
// Let collector get work done to remove the entry from the map.
|
||||||
|
runtime.Gosched()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// The new entry was added to the map, good to go.
|
||||||
|
return rec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The order of the input array `kvs` may be sorted after the function is called.
|
||||||
|
func (s *syncInstrument) Bind(kvs []attribute.KeyValue) sdkapi.BoundSyncImpl {
|
||||||
|
return s.acquireHandle(kvs, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The order of the input array `kvs` may be sorted after the function is called.
|
||||||
|
func (s *syncInstrument) RecordOne(ctx context.Context, num number.Number, kvs []attribute.KeyValue) {
|
||||||
|
h := s.acquireHandle(kvs, nil)
|
||||||
|
defer h.Unbind()
|
||||||
|
h.RecordOne(ctx, num)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAccumulator constructs a new Accumulator for the given
|
||||||
|
// processor. This Accumulator supports only a single processor.
|
||||||
|
//
|
||||||
|
// The Accumulator does not start any background process to collect itself
|
||||||
|
// periodically, this responsibility lies with the processor, typically,
|
||||||
|
// depending on the type of export. For example, a pull-based
|
||||||
|
// processor will call Collect() when it receives a request to scrape
|
||||||
|
// current metric values. A push-based processor should configure its
|
||||||
|
// own periodic collection.
|
||||||
|
func NewAccumulator(processor export.Processor) *Accumulator {
|
||||||
|
return &Accumulator{
|
||||||
|
processor: processor,
|
||||||
|
asyncInstruments: internal.NewAsyncInstrumentState(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSyncInstrument implements sdkapi.MetricImpl.
|
||||||
|
func (m *Accumulator) NewSyncInstrument(descriptor sdkapi.Descriptor) (sdkapi.SyncImpl, error) {
|
||||||
|
return &syncInstrument{
|
||||||
|
instrument: instrument{
|
||||||
|
descriptor: descriptor,
|
||||||
|
meter: m,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAsyncInstrument implements sdkapi.MetricImpl.
|
||||||
|
func (m *Accumulator) NewAsyncInstrument(descriptor sdkapi.Descriptor, runner sdkapi.AsyncRunner) (sdkapi.AsyncImpl, error) {
|
||||||
|
a := &asyncInstrument{
|
||||||
|
instrument: instrument{
|
||||||
|
descriptor: descriptor,
|
||||||
|
meter: m,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
m.asyncLock.Lock()
|
||||||
|
defer m.asyncLock.Unlock()
|
||||||
|
m.asyncInstruments.Register(a, runner)
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect traverses the list of active records and observers and
|
||||||
|
// exports data for each active instrument. Collect() may not be
|
||||||
|
// called concurrently.
|
||||||
|
//
|
||||||
|
// During the collection pass, the export.Processor will receive
|
||||||
|
// one Export() call per current aggregation.
|
||||||
|
//
|
||||||
|
// Returns the number of records that were checkpointed.
|
||||||
|
func (m *Accumulator) Collect(ctx context.Context) int {
|
||||||
|
m.collectLock.Lock()
|
||||||
|
defer m.collectLock.Unlock()
|
||||||
|
|
||||||
|
checkpointed := m.observeAsyncInstruments(ctx)
|
||||||
|
checkpointed += m.collectSyncInstruments()
|
||||||
|
m.currentEpoch++
|
||||||
|
|
||||||
|
return checkpointed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Accumulator) collectSyncInstruments() int {
|
||||||
|
checkpointed := 0
|
||||||
|
|
||||||
|
m.current.Range(func(key interface{}, value interface{}) bool {
|
||||||
|
// Note: always continue to iterate over the entire
|
||||||
|
// map by returning `true` in this function.
|
||||||
|
inuse := value.(*record)
|
||||||
|
|
||||||
|
mods := atomic.LoadInt64(&inuse.updateCount)
|
||||||
|
coll := inuse.collectedCount
|
||||||
|
|
||||||
|
if mods != coll {
|
||||||
|
// Updates happened in this interval,
|
||||||
|
// checkpoint and continue.
|
||||||
|
checkpointed += m.checkpointRecord(inuse)
|
||||||
|
inuse.collectedCount = mods
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Having no updates since last collection, try to unmap:
|
||||||
|
if unmapped := inuse.refMapped.tryUnmap(); !unmapped {
|
||||||
|
// The record is referenced by a binding, continue.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any other goroutines are now trying to re-insert this
|
||||||
|
// entry in the map, they are busy calling Gosched() awaiting
|
||||||
|
// this deletion:
|
||||||
|
m.current.Delete(inuse.mapkey())
|
||||||
|
|
||||||
|
// There's a potential race between `LoadInt64` and
|
||||||
|
// `tryUnmap` in this function. Since this is the
|
||||||
|
// last we'll see of this record, checkpoint
|
||||||
|
mods = atomic.LoadInt64(&inuse.updateCount)
|
||||||
|
if mods != coll {
|
||||||
|
checkpointed += m.checkpointRecord(inuse)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
return checkpointed
|
||||||
|
}
|
||||||
|
|
||||||
|
// CollectAsync implements internal.AsyncCollector.
|
||||||
|
// The order of the input array `kvs` may be sorted after the function is called.
|
||||||
|
func (m *Accumulator) CollectAsync(kv []attribute.KeyValue, obs ...sdkapi.Observation) {
|
||||||
|
labels := attribute.NewSetWithSortable(kv, &m.asyncSortSlice)
|
||||||
|
|
||||||
|
for _, ob := range obs {
|
||||||
|
if a := m.fromAsync(ob.AsyncImpl()); a != nil {
|
||||||
|
a.observe(ob.Number(), &labels)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Accumulator) observeAsyncInstruments(ctx context.Context) int {
|
||||||
|
m.asyncLock.Lock()
|
||||||
|
defer m.asyncLock.Unlock()
|
||||||
|
|
||||||
|
asyncCollected := 0
|
||||||
|
|
||||||
|
m.asyncInstruments.Run(ctx, m)
|
||||||
|
|
||||||
|
for _, inst := range m.asyncInstruments.Instruments() {
|
||||||
|
if a := m.fromAsync(inst); a != nil {
|
||||||
|
asyncCollected += m.checkpointAsync(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return asyncCollected
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Accumulator) checkpointRecord(r *record) int {
|
||||||
|
if r.current == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
err := r.current.SynchronizedMove(r.checkpoint, &r.inst.descriptor)
|
||||||
|
if err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
a := export.NewAccumulation(&r.inst.descriptor, r.labels, r.checkpoint)
|
||||||
|
err = m.processor.Process(a)
|
||||||
|
if err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Accumulator) checkpointAsync(a *asyncInstrument) int {
|
||||||
|
if len(a.recorders) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
checkpointed := 0
|
||||||
|
for encodedLabels, lrec := range a.recorders {
|
||||||
|
lrec := lrec
|
||||||
|
epochDiff := m.currentEpoch - lrec.observedEpoch
|
||||||
|
if epochDiff == 0 {
|
||||||
|
if lrec.observed != nil {
|
||||||
|
a := export.NewAccumulation(&a.descriptor, lrec.labels, lrec.observed)
|
||||||
|
err := m.processor.Process(a)
|
||||||
|
if err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
}
|
||||||
|
checkpointed++
|
||||||
|
}
|
||||||
|
} else if epochDiff > 1 {
|
||||||
|
// This is second collection cycle with no
|
||||||
|
// observations for this labelset. Remove the
|
||||||
|
// recorder.
|
||||||
|
delete(a.recorders, encodedLabels)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(a.recorders) == 0 {
|
||||||
|
a.recorders = nil
|
||||||
|
}
|
||||||
|
return checkpointed
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordBatch enters a batch of metric events.
|
||||||
|
// The order of the input array `kvs` may be sorted after the function is called.
|
||||||
|
func (m *Accumulator) RecordBatch(ctx context.Context, kvs []attribute.KeyValue, measurements ...sdkapi.Measurement) {
|
||||||
|
// Labels will be computed the first time acquireHandle is
|
||||||
|
// called. Subsequent calls to acquireHandle will re-use the
|
||||||
|
// previously computed value instead of recomputing the
|
||||||
|
// ordered labels.
|
||||||
|
var labelsPtr *attribute.Set
|
||||||
|
for i, meas := range measurements {
|
||||||
|
s := m.fromSync(meas.SyncImpl())
|
||||||
|
if s == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
h := s.acquireHandle(kvs, labelsPtr)
|
||||||
|
|
||||||
|
// Re-use labels for the next measurement.
|
||||||
|
if i == 0 {
|
||||||
|
labelsPtr = h.labels
|
||||||
|
}
|
||||||
|
|
||||||
|
defer h.Unbind()
|
||||||
|
h.RecordOne(ctx, meas.Number())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordOne implements sdkapi.SyncImpl.
|
||||||
|
func (r *record) RecordOne(ctx context.Context, num number.Number) {
|
||||||
|
if r.current == nil {
|
||||||
|
// The instrument is disabled according to the AggregatorSelector.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := aggregator.RangeTest(num, &r.inst.descriptor); err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := r.current.Update(ctx, num, &r.inst.descriptor); err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Record was modified, inform the Collect() that things need
|
||||||
|
// to be collected while the record is still mapped.
|
||||||
|
atomic.AddInt64(&r.updateCount, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unbind implements sdkapi.SyncImpl.
|
||||||
|
func (r *record) Unbind() {
|
||||||
|
r.refMapped.unref()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *record) mapkey() mapkey {
|
||||||
|
return mapkey{
|
||||||
|
descriptor: &r.inst.descriptor,
|
||||||
|
ordered: r.labels.Equivalent(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fromSync gets a sync implementation object, checking for
|
||||||
|
// uninitialized instruments and instruments created by another SDK.
|
||||||
|
func (m *Accumulator) fromSync(sync sdkapi.SyncImpl) *syncInstrument {
|
||||||
|
if sync != nil {
|
||||||
|
if inst, ok := sync.Implementation().(*syncInstrument); ok {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
otel.Handle(ErrUninitializedInstrument)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fromSync gets an async implementation object, checking for
|
||||||
|
// uninitialized instruments and instruments created by another SDK.
|
||||||
|
func (m *Accumulator) fromAsync(async sdkapi.AsyncImpl) *asyncInstrument {
|
||||||
|
if async != nil {
|
||||||
|
if inst, ok := async.Implementation().(*asyncInstrument); ok {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
otel.Handle(ErrUninitializedInstrument)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
120
vendor/go.opentelemetry.io/otel/sdk/metric/selector/simple/simple.go
generated
vendored
Normal file
120
vendor/go.opentelemetry.io/otel/sdk/metric/selector/simple/simple.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
// Copyright The 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 simple // import "go.opentelemetry.io/otel/sdk/metric/selector/simple"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.opentelemetry.io/otel/metric/sdkapi"
|
||||||
|
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator/exact"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator/histogram"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator/minmaxsumcount"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/aggregator/sum"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
selectorInexpensive struct{}
|
||||||
|
selectorExact struct{}
|
||||||
|
selectorHistogram struct {
|
||||||
|
options []histogram.Option
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ export.AggregatorSelector = selectorInexpensive{}
|
||||||
|
_ export.AggregatorSelector = selectorExact{}
|
||||||
|
_ export.AggregatorSelector = selectorHistogram{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewWithInexpensiveDistribution returns a simple aggregator selector
|
||||||
|
// that uses minmaxsumcount aggregators for `Histogram`
|
||||||
|
// instruments. This selector is faster and uses less memory than the
|
||||||
|
// others in this package because minmaxsumcount aggregators maintain
|
||||||
|
// the least information about the distribution among these choices.
|
||||||
|
func NewWithInexpensiveDistribution() export.AggregatorSelector {
|
||||||
|
return selectorInexpensive{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithExactDistribution returns a simple aggregator selector that
|
||||||
|
// uses exact aggregators for `Histogram` instruments. This
|
||||||
|
// selector uses more memory than the others in this package because
|
||||||
|
// exact aggregators maintain the most information about the
|
||||||
|
// distribution among these choices.
|
||||||
|
func NewWithExactDistribution() export.AggregatorSelector {
|
||||||
|
return selectorExact{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithHistogramDistribution returns a simple aggregator selector
|
||||||
|
// that uses histogram aggregators for `Histogram` instruments.
|
||||||
|
// This selector is a good default choice for most metric exporters.
|
||||||
|
func NewWithHistogramDistribution(options ...histogram.Option) export.AggregatorSelector {
|
||||||
|
return selectorHistogram{options: options}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sumAggs(aggPtrs []*export.Aggregator) {
|
||||||
|
aggs := sum.New(len(aggPtrs))
|
||||||
|
for i := range aggPtrs {
|
||||||
|
*aggPtrs[i] = &aggs[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func lastValueAggs(aggPtrs []*export.Aggregator) {
|
||||||
|
aggs := lastvalue.New(len(aggPtrs))
|
||||||
|
for i := range aggPtrs {
|
||||||
|
*aggPtrs[i] = &aggs[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (selectorInexpensive) AggregatorFor(descriptor *sdkapi.Descriptor, aggPtrs ...*export.Aggregator) {
|
||||||
|
switch descriptor.InstrumentKind() {
|
||||||
|
case sdkapi.GaugeObserverInstrumentKind:
|
||||||
|
lastValueAggs(aggPtrs)
|
||||||
|
case sdkapi.HistogramInstrumentKind:
|
||||||
|
aggs := minmaxsumcount.New(len(aggPtrs), descriptor)
|
||||||
|
for i := range aggPtrs {
|
||||||
|
*aggPtrs[i] = &aggs[i]
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
sumAggs(aggPtrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (selectorExact) AggregatorFor(descriptor *sdkapi.Descriptor, aggPtrs ...*export.Aggregator) {
|
||||||
|
switch descriptor.InstrumentKind() {
|
||||||
|
case sdkapi.GaugeObserverInstrumentKind:
|
||||||
|
lastValueAggs(aggPtrs)
|
||||||
|
case sdkapi.HistogramInstrumentKind:
|
||||||
|
aggs := exact.New(len(aggPtrs))
|
||||||
|
for i := range aggPtrs {
|
||||||
|
*aggPtrs[i] = &aggs[i]
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
sumAggs(aggPtrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s selectorHistogram) AggregatorFor(descriptor *sdkapi.Descriptor, aggPtrs ...*export.Aggregator) {
|
||||||
|
switch descriptor.InstrumentKind() {
|
||||||
|
case sdkapi.GaugeObserverInstrumentKind:
|
||||||
|
lastValueAggs(aggPtrs)
|
||||||
|
case sdkapi.HistogramInstrumentKind:
|
||||||
|
aggs := histogram.New(len(aggPtrs), descriptor, s.options...)
|
||||||
|
for i := range aggPtrs {
|
||||||
|
*aggPtrs[i] = &aggs[i]
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
sumAggs(aggPtrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user