mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 19:17:58 +00:00
Create helpers which integrate with OpenTelemetry for diagnose collection (#11454)
* Create helpers which integrate with OpenTelemetry for diagnose collection * Go mod vendor * Comments * Update vault/diagnose/helpers.go Co-authored-by: swayne275 <swayne275@gmail.com> * Add unit test/example * tweak output * More comments * add spot check concept * Get unit tests working on Result structs * Fix unit test * Get unit tests working, and make diagnose sessions local rather than global * Comments * Last comments * No need for init * :| * Fix helpers_test Co-authored-by: swayne275 <swayne275@gmail.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -26,6 +26,7 @@ var (
|
||||
|
||||
type OperatorDiagnoseCommand struct {
|
||||
*BaseCommand
|
||||
diagnose *diagnose.Session
|
||||
|
||||
flagDebug bool
|
||||
flagSkips []string
|
||||
@@ -129,6 +130,16 @@ func (c *OperatorDiagnoseCommand) RunWithParsedFlags() int {
|
||||
}
|
||||
|
||||
c.UI.Output(version.GetVersion().FullVersionNumber(true))
|
||||
ctx := diagnose.Context(context.Background(), c.diagnose)
|
||||
err := c.offlineDiagnostics(ctx)
|
||||
|
||||
if err != nil {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *OperatorDiagnoseCommand) offlineDiagnostics(ctx context.Context) error {
|
||||
rloadFuncs := make(map[string][]reloadutil.ReloadFunc)
|
||||
server := &ServerCommand{
|
||||
// TODO: set up a different one?
|
||||
@@ -150,126 +161,106 @@ func (c *OperatorDiagnoseCommand) RunWithParsedFlags() int {
|
||||
reloadFuncsLock: new(sync.RWMutex),
|
||||
}
|
||||
|
||||
phase := "Parse configuration"
|
||||
ctx, span := diagnose.StartSpan(ctx, "initialization")
|
||||
defer span.End()
|
||||
|
||||
server.flagConfigs = c.flagConfigs
|
||||
config, err := server.parseConfig()
|
||||
if err != nil {
|
||||
c.outputErrorsAndWarnings(fmt.Sprintf("Error while reading configuration files: %s", err.Error()), phase, nil)
|
||||
return 1
|
||||
return diagnose.SpotError(ctx, "parse-config", err)
|
||||
} else {
|
||||
diagnose.SpotOk(ctx, "parse-config", "")
|
||||
}
|
||||
c.UI.Output(same_line + status_ok + phase)
|
||||
|
||||
// Check Listener Information
|
||||
phase = "Check Listeners"
|
||||
// TODO: Run Diagnose checks on the actual net.Listeners
|
||||
var warnings []string
|
||||
disableClustering := config.HAStorage.DisableClustering
|
||||
infoKeys := make([]string, 0, 10)
|
||||
info := make(map[string]string)
|
||||
status, lns, _, errMsg := server.InitListeners(config, disableClustering, &infoKeys, &info)
|
||||
|
||||
if status != 0 {
|
||||
c.outputErrorsAndWarnings(fmt.Sprintf("Error parsing listener configuration. %s", errMsg.Error()), phase, nil)
|
||||
return 1
|
||||
}
|
||||
if err := diagnose.Test(ctx, "init-listeners", func(ctx context.Context) error {
|
||||
disableClustering := config.HAStorage.DisableClustering
|
||||
infoKeys := make([]string, 0, 10)
|
||||
info := make(map[string]string)
|
||||
status, lns, _, errMsg := server.InitListeners(config, disableClustering, &infoKeys, &info)
|
||||
|
||||
// Make sure we close all listeners from this point on
|
||||
listenerCloseFunc := func() {
|
||||
if status != 0 {
|
||||
return errMsg
|
||||
}
|
||||
|
||||
// Make sure we close all listeners from this point on
|
||||
listenerCloseFunc := func() {
|
||||
for _, ln := range lns {
|
||||
ln.Listener.Close()
|
||||
}
|
||||
}
|
||||
|
||||
defer c.cleanupGuard.Do(listenerCloseFunc)
|
||||
|
||||
sanitizedListeners := make([]listenerutil.Listener, 0, len(config.Listeners))
|
||||
for _, ln := range lns {
|
||||
ln.Listener.Close()
|
||||
if ln.Config.TLSDisable {
|
||||
diagnose.Warn(ctx, "TLS is disabled in a Listener config stanza.")
|
||||
continue
|
||||
}
|
||||
if ln.Config.TLSDisableClientCerts {
|
||||
diagnose.Warn(ctx, "TLS for a listener is turned on without requiring client certs.")
|
||||
}
|
||||
|
||||
// Check ciphersuite and load ca/cert/key files
|
||||
// TODO: TLSConfig returns a reloadFunc and a TLSConfig. We can use this to
|
||||
// perform an active probe.
|
||||
_, _, err := listenerutil.TLSConfig(ln.Config, make(map[string]string), c.UI)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sanitizedListeners = append(sanitizedListeners, listenerutil.Listener{
|
||||
Listener: ln.Listener,
|
||||
Config: ln.Config,
|
||||
})
|
||||
}
|
||||
return diagnose.ListenerChecks(sanitizedListeners)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer c.cleanupGuard.Do(listenerCloseFunc)
|
||||
|
||||
sanitizedListeners := make([]listenerutil.Listener, 0, len(config.Listeners))
|
||||
for _, ln := range lns {
|
||||
if ln.Config.TLSDisable {
|
||||
warnings = append(warnings, "WARNING! TLS is disabled in a Listener config stanza.")
|
||||
continue
|
||||
}
|
||||
if ln.Config.TLSDisableClientCerts {
|
||||
warnings = append(warnings, "WARNING! TLS for a listener is turned on without requiring client certs.")
|
||||
}
|
||||
|
||||
// Check ciphersuite and load ca/cert/key files
|
||||
// TODO: TLSConfig returns a reloadFunc and a TLSConfig. We can use this to
|
||||
// perform an active probe.
|
||||
_, _, err := listenerutil.TLSConfig(ln.Config, make(map[string]string), c.UI)
|
||||
if err != nil {
|
||||
c.outputErrorsAndWarnings(fmt.Sprintf("Error creating TLS Configuration out of config file: %s", err.Error()), phase, warnings)
|
||||
return 1
|
||||
}
|
||||
|
||||
sanitizedListeners = append(sanitizedListeners, listenerutil.Listener{
|
||||
Listener: ln.Listener,
|
||||
Config: ln.Config,
|
||||
})
|
||||
}
|
||||
err = diagnose.ListenerChecks(sanitizedListeners)
|
||||
if err != nil {
|
||||
c.outputErrorsAndWarnings(fmt.Sprintf("Diagnose caught configuration errors: %s", err.Error()), phase, warnings)
|
||||
return 1
|
||||
}
|
||||
|
||||
c.UI.Output(same_line + status_ok + phase)
|
||||
|
||||
// Errors in these items could stop Vault from starting but are not yet covered:
|
||||
// TODO: logging configuration
|
||||
// TODO: SetupTelemetry
|
||||
// TODO: check for storage backend
|
||||
|
||||
phase = "Access storage"
|
||||
warnings = nil
|
||||
if err := diagnose.Test(ctx, "storage", func(ctx context.Context) error {
|
||||
|
||||
_, err = server.setupStorage(config)
|
||||
if err != nil {
|
||||
c.outputErrorsAndWarnings(fmt.Sprintf(err.Error()), phase, warnings)
|
||||
return 1
|
||||
}
|
||||
|
||||
if config.Storage != nil && config.Storage.Type == storageTypeConsul {
|
||||
err = physconsul.SetupSecureTLS(api.DefaultConfig(), config.Storage.Config, server.logger, true)
|
||||
_, err = server.setupStorage(config)
|
||||
if err != nil {
|
||||
c.outputErrorsAndWarnings(fmt.Sprintf(err.Error()), phase, warnings)
|
||||
return 1
|
||||
return err
|
||||
}
|
||||
|
||||
if config.Storage != nil && config.Storage.Type == storageTypeConsul {
|
||||
err = physconsul.SetupSecureTLS(api.DefaultConfig(), config.Storage.Config, server.logger, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if config.HAStorage != nil && config.HAStorage.Type == storageTypeConsul {
|
||||
err = physconsul.SetupSecureTLS(api.DefaultConfig(), config.HAStorage.Config, server.logger, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if config.HAStorage != nil && config.HAStorage.Type == storageTypeConsul {
|
||||
err = physconsul.SetupSecureTLS(api.DefaultConfig(), config.HAStorage.Config, server.logger, true)
|
||||
if err != nil {
|
||||
c.outputErrorsAndWarnings(fmt.Sprintf(err.Error()), phase, warnings)
|
||||
return 1
|
||||
return diagnose.Test(ctx, "service-discovery", func(ctx context.Context) error {
|
||||
// Initialize the Service Discovery, if there is one
|
||||
if config.ServiceRegistration != nil && config.ServiceRegistration.Type == "consul" {
|
||||
// SetupSecureTLS for service discovery uses the same cert and key to set up physical
|
||||
// storage. See the consul package in physical for details.
|
||||
err = srconsul.SetupSecureTLS(api.DefaultConfig(), config.ServiceRegistration.Config, server.logger, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.UI.Output(same_line + status_ok + phase)
|
||||
|
||||
// Initialize the Service Discovery, if there is one
|
||||
phase = "Service discovery"
|
||||
if config.ServiceRegistration != nil && config.ServiceRegistration.Type == "consul" {
|
||||
// SetupSecureTLS for service discovery uses the same cert and key to set up physical
|
||||
// storage. See the consul package in physical for details.
|
||||
err = srconsul.SetupSecureTLS(api.DefaultConfig(), config.ServiceRegistration.Config, server.logger, true)
|
||||
if err != nil {
|
||||
c.outputErrorsAndWarnings(fmt.Sprintf(err.Error()), phase, warnings)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
c.UI.Output(same_line + status_ok + phase)
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *OperatorDiagnoseCommand) outputErrorsAndWarnings(err, phase string, warnings []string) {
|
||||
|
||||
c.UI.Output(same_line + status_failed + phase)
|
||||
|
||||
if warnings != nil && len(warnings) > 0 {
|
||||
for _, warning := range warnings {
|
||||
c.UI.Warn(warning)
|
||||
}
|
||||
}
|
||||
c.UI.Error(err)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,17 +3,21 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/vault/diagnose"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testOperatorDiagnoseCommand(tb testing.TB) (*cli.MockUi, *OperatorDiagnoseCommand) {
|
||||
func testOperatorDiagnoseCommand(tb testing.TB) *OperatorDiagnoseCommand {
|
||||
tb.Helper()
|
||||
|
||||
ui := cli.NewMockUi()
|
||||
return ui, &OperatorDiagnoseCommand{
|
||||
return &OperatorDiagnoseCommand{
|
||||
diagnose: diagnose.New(),
|
||||
BaseCommand: &BaseCommand{
|
||||
UI: ui,
|
||||
},
|
||||
@@ -23,58 +27,158 @@ func testOperatorDiagnoseCommand(tb testing.TB) (*cli.MockUi, *OperatorDiagnoseC
|
||||
func TestOperatorDiagnoseCommand_Run(t *testing.T) {
|
||||
t.Parallel()
|
||||
cases := []struct {
|
||||
name string
|
||||
args []string
|
||||
outFragments []string
|
||||
code int
|
||||
name string
|
||||
args []string
|
||||
expected []*diagnose.Result
|
||||
}{
|
||||
{
|
||||
"diagnose_ok",
|
||||
[]string{
|
||||
"-config", "./server/test-fixtures/config_diagnose_ok.hcl",
|
||||
},
|
||||
[]string{"Parse configuration\n\x1b[F\x1b[32m[ ok ]\x1b[0m Check Listeners\n\x1b[F\x1b[32m[ ok ]\x1b[0m Access storage\n\x1b[F\x1b[32m[ ok ]\x1b[0m Service discovery\n"},
|
||||
0,
|
||||
[]*diagnose.Result{
|
||||
{
|
||||
Name: "parse-config",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "init-listeners",
|
||||
Status: diagnose.WarningStatus,
|
||||
Warnings: []string{
|
||||
"TLS is disabled in a Listener config stanza.",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "storage",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "service-discovery",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"diagnose_invalid_storage",
|
||||
[]string{
|
||||
"-config", "./server/test-fixtures/nostore_config.hcl",
|
||||
},
|
||||
[]string{"Parse configuration\n\x1b[F\x1b[32m[ ok ]\x1b[0m Check Listeners\n\x1b[F\x1b[31m[failed]\x1b[0m Access storage\nA storage backend must be specified"},
|
||||
1,
|
||||
[]*diagnose.Result{
|
||||
{
|
||||
Name: "parse-config",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "init-listeners",
|
||||
Status: diagnose.WarningStatus,
|
||||
Warnings: []string{
|
||||
"TLS is disabled in a Listener config stanza.",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "storage",
|
||||
Status: diagnose.ErrorStatus,
|
||||
Message: "A storage backend must be specified",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"diagnose_listener_config_ok",
|
||||
[]string{
|
||||
"-config", "./server/test-fixtures/tls_config_ok.hcl",
|
||||
},
|
||||
[]string{"Parse configuration\n\x1b[F\x1b[32m[ ok ]\x1b[0m Check Listeners\n\x1b[F\x1b[32m[ ok ]\x1b[0m Access storage\n\x1b[F\x1b[32m[ ok ]\x1b[0m Service discovery"},
|
||||
0,
|
||||
[]*diagnose.Result{
|
||||
{
|
||||
Name: "parse-config",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "init-listeners",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "storage",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "service-discovery",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"diagnose_invalid_https_storage",
|
||||
[]string{
|
||||
"-config", "./server/test-fixtures/config_bad_https_storage.hcl",
|
||||
},
|
||||
[]string{"Access storage\nfailed to verify certificate: x509: certificate has expired or is not yet valid:"},
|
||||
1,
|
||||
[]*diagnose.Result{
|
||||
{
|
||||
Name: "parse-config",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "init-listeners",
|
||||
Status: diagnose.WarningStatus,
|
||||
Warnings: []string{
|
||||
"TLS is disabled in a Listener config stanza.",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "storage",
|
||||
Status: diagnose.ErrorStatus,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"diagnose_invalid_https_hastorage",
|
||||
[]string{
|
||||
"-config", "./server/test-fixtures/config_diagnose_hastorage_bad_https.hcl",
|
||||
},
|
||||
[]string{"Access storage\nfailed to verify certificate: x509: certificate has expired or is not yet valid:"},
|
||||
1,
|
||||
[]*diagnose.Result{
|
||||
{
|
||||
Name: "parse-config",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "init-listeners",
|
||||
Status: diagnose.WarningStatus,
|
||||
Warnings: []string{
|
||||
"TLS is disabled in a Listener config stanza.",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "storage",
|
||||
Status: diagnose.ErrorStatus,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"diagnose_invalid_https_sr",
|
||||
[]string{
|
||||
"-config", "./server/test-fixtures/diagnose_bad_https_consul_sr.hcl",
|
||||
},
|
||||
[]string{"Service discovery\nfailed to verify certificate: x509: certificate has expired or is not yet valid:"},
|
||||
1,
|
||||
[]*diagnose.Result{
|
||||
{
|
||||
Name: "parse-config",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "init-listeners",
|
||||
Status: diagnose.WarningStatus,
|
||||
Warnings: []string{
|
||||
"TLS is disabled in a Listener config stanza.",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "storage",
|
||||
Status: diagnose.OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "service-discovery",
|
||||
Status: diagnose.ErrorStatus,
|
||||
Message: "failed to verify certificate: x509: certificate has expired or is not yet valid:",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -86,26 +190,46 @@ func TestOperatorDiagnoseCommand_Run(t *testing.T) {
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client, closer := testVaultServer(t)
|
||||
defer closer()
|
||||
|
||||
ui, cmd := testOperatorDiagnoseCommand(t)
|
||||
cmd := testOperatorDiagnoseCommand(t)
|
||||
cmd.client = client
|
||||
|
||||
code := cmd.Run(tc.args)
|
||||
if code != tc.code {
|
||||
t.Errorf("%s: expected %d to be %d", tc.name, code, tc.code)
|
||||
}
|
||||
cmd.Run(tc.args)
|
||||
result := cmd.diagnose.Finalize(context.Background())
|
||||
|
||||
combined := ui.OutputWriter.String() + ui.ErrorWriter.String()
|
||||
|
||||
for _, outputFragment := range tc.outFragments {
|
||||
if !strings.Contains(combined, outputFragment) {
|
||||
t.Errorf("%s: expected %q to contain %q", tc.name, combined, outputFragment)
|
||||
for i, exp := range tc.expected {
|
||||
act := result.Children[i]
|
||||
if err := compareResult(t, exp, act); err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func compareResult(t *testing.T, exp *diagnose.Result, act *diagnose.Result) error {
|
||||
if exp.Name != act.Name {
|
||||
return fmt.Errorf("names mismatch: %s vs %s", exp.Name, act.Name)
|
||||
}
|
||||
if exp.Status != act.Status {
|
||||
return fmt.Errorf("section %s, status mismatch: %s vs %s", exp.Name, exp.Status, act.Status)
|
||||
}
|
||||
if exp.Message != "" && exp.Message != act.Message && !strings.Contains(act.Message, exp.Message) {
|
||||
return fmt.Errorf("section %s, message not found: %s in %s", exp.Name, exp.Message, act.Message)
|
||||
}
|
||||
if len(exp.Warnings) != len(act.Warnings) {
|
||||
return fmt.Errorf("section %s, warning count mismatch: %d vs %d", exp.Name, len(exp.Warnings), len(act.Warnings))
|
||||
}
|
||||
for j := range exp.Warnings {
|
||||
if !strings.Contains(act.Warnings[j], exp.Warnings[j]) {
|
||||
return fmt.Errorf("section %s, warning message not found: %s in %s", exp.Name, exp.Warnings[j], act.Warnings[j])
|
||||
}
|
||||
}
|
||||
if len(exp.Children) != len(act.Children) {
|
||||
return fmt.Errorf("section %s, child count mismatch: %d vs %d", exp.Name, len(exp.Children), len(act.Children))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1980,7 +1980,7 @@ CLUSTER_SYNTHESIS_COMPLETE:
|
||||
// Stop the listeners so that we don't process further client requests.
|
||||
c.cleanupGuard.Do(listenerCloseFunc)
|
||||
|
||||
// Shutdown will wait until after Vault is sealed, which means the
|
||||
// Finalize will wait until after Vault is sealed, which means the
|
||||
// request forwarding listeners will also be closed (and also
|
||||
// waited for).
|
||||
if err := core.Shutdown(); err != nil {
|
||||
@@ -2304,7 +2304,7 @@ func (c *ServerCommand) enableThreeNodeDevCluster(base *vault.CoreConfig, info m
|
||||
// Stop the listeners so that we don't process further client requests.
|
||||
c.cleanupGuard.Do(testCluster.Cleanup)
|
||||
|
||||
// Shutdown will wait until after Vault is sealed, which means the
|
||||
// Finalize will wait until after Vault is sealed, which means the
|
||||
// request forwarding listeners will also be closed (and also
|
||||
// waited for).
|
||||
for _, core := range testCluster.Cores {
|
||||
|
||||
5
go.mod
5
go.mod
@@ -147,7 +147,7 @@ require (
|
||||
github.com/sasha-s/go-deadlock v0.2.0
|
||||
github.com/sethvargo/go-limiter v0.3.0
|
||||
github.com/shirou/gopsutil v3.21.1+incompatible
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tidwall/pretty v1.0.1 // indirect
|
||||
github.com/ulikunitz/xz v0.5.7 // indirect
|
||||
github.com/xdg/stringprep v1.0.0 // indirect
|
||||
@@ -156,6 +156,9 @@ require (
|
||||
go.etcd.io/bbolt v1.3.5
|
||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20200425165423-262c93980547
|
||||
go.mongodb.org/mongo-driver v1.4.6
|
||||
go.opentelemetry.io/otel v0.20.0
|
||||
go.opentelemetry.io/otel/sdk v0.20.0
|
||||
go.opentelemetry.io/otel/trace v0.20.0
|
||||
go.uber.org/atomic v1.6.0
|
||||
go.uber.org/goleak v1.1.10
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
|
||||
|
||||
13
go.sum
13
go.sum
@@ -489,6 +489,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-metrics-stackdriver v0.2.0 h1:rbs2sxHAPn2OtUj9JdR/Gij1YKGl0BTVD0augB+HEjE=
|
||||
@@ -1163,6 +1165,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/svanharmelen/jsonapi v0.0.0-20180618144545-0c0828c3f16d h1:Z4EH+5EffvBEhh37F0C0DnpklTMh00JOkjW5zK3ofBI=
|
||||
github.com/svanharmelen/jsonapi v0.0.0-20180618144545-0c0828c3f16d/go.mod h1:BSTlc8jOjh0niykqEGVXOLXdi9o0r0kR8tCYiMvjFgw=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4=
|
||||
@@ -1227,6 +1231,15 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g=
|
||||
go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
|
||||
go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8=
|
||||
go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
|
||||
go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
|
||||
go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8=
|
||||
go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
|
||||
go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw=
|
||||
go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
|
||||
@@ -349,7 +349,7 @@ func TestRaft_Snapshot_Restart(t *testing.T) {
|
||||
t.Fatal(peers)
|
||||
}
|
||||
|
||||
// Shutdown raft1
|
||||
// Finalize raft1
|
||||
if err := raft1.TeardownCluster(nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -213,7 +213,6 @@ func SetupSecureTLS(consulConf *api.Config, conf map[string]string, logger log.L
|
||||
}
|
||||
|
||||
if consulConf.Scheme == "https" {
|
||||
|
||||
if isDiagnose {
|
||||
certPath, okCert := conf["tls_cert_file"]
|
||||
keyPath, okKey := conf["tls_key_file"]
|
||||
|
||||
@@ -245,7 +245,7 @@ func TestCore_Shutdown(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// verify the channel returned by ShutdownDone is closed after Shutdown
|
||||
// verify the channel returned by ShutdownDone is closed after Finalize
|
||||
func TestCore_ShutdownDone(t *testing.T) {
|
||||
c, _, _ := TestCoreUnsealed(t)
|
||||
doneCh := c.ShutdownDone()
|
||||
|
||||
148
vault/diagnose/helpers.go
Normal file
148
vault/diagnose/helpers.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package diagnose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
const (
|
||||
warningEventName = "warning"
|
||||
actionKey = "actionKey"
|
||||
spotCheckOkEventName = "spot-check-ok"
|
||||
spotCheckWarnEventName = "spot-check-warn"
|
||||
spotCheckErrorEventName = "spot-check-error"
|
||||
errorMessageKey = attribute.Key("error.message")
|
||||
nameKey = attribute.Key("name")
|
||||
messageKey = attribute.Key("message")
|
||||
)
|
||||
|
||||
var diagnoseSession = struct{}{}
|
||||
var noopTracer = trace.NewNoopTracerProvider().Tracer("vault-diagnose")
|
||||
|
||||
type Session struct {
|
||||
tc *TelemetryCollector
|
||||
tracer trace.Tracer
|
||||
tp *sdktrace.TracerProvider
|
||||
}
|
||||
|
||||
// New initializes a Diagnose tracing session. In particular this wires a TelemetryCollector, which
|
||||
// synchronously receives and tracks OpenTelemetry spans in order to provide a tree structure of results
|
||||
// when the outermost span ends.
|
||||
func New() *Session {
|
||||
tc := NewTelemetryCollector()
|
||||
//so, _ := stdout.NewExporter(stdout.WithPrettyPrint())
|
||||
tp := sdktrace.NewTracerProvider(
|
||||
sdktrace.WithSampler(sdktrace.AlwaysSample()),
|
||||
//sdktrace.WithSpanProcessor(sdktrace.NewSimpleSpanProcessor(so)),
|
||||
sdktrace.WithSpanProcessor(tc),
|
||||
)
|
||||
tracer := tp.Tracer("vault-diagnose")
|
||||
sess := &Session{
|
||||
tp: tp,
|
||||
tc: tc,
|
||||
tracer: tracer,
|
||||
}
|
||||
return sess
|
||||
}
|
||||
|
||||
// Context returns a new context with a defined diagnose session
|
||||
func Context(ctx context.Context, sess *Session) context.Context {
|
||||
return context.WithValue(ctx, diagnoseSession, sess)
|
||||
}
|
||||
|
||||
// Finalize ends the Diagnose session, returning the root of the result tree. This will be empty until
|
||||
// the outermost span ends.
|
||||
func (s *Session) Finalize(ctx context.Context) *Result {
|
||||
s.tp.ForceFlush(ctx)
|
||||
return s.tc.RootResult
|
||||
}
|
||||
|
||||
// StartSpan starts a "diagnose" span, which is really just an OpenTelemetry Tracing span.
|
||||
func StartSpan(ctx context.Context, spanName string, options ...trace.SpanOption) (context.Context, trace.Span) {
|
||||
sessionCtxVal := ctx.Value(diagnoseSession)
|
||||
if sessionCtxVal != nil {
|
||||
|
||||
session := sessionCtxVal.(*Session)
|
||||
return session.tracer.Start(ctx, spanName, options...)
|
||||
} else {
|
||||
return noopTracer.Start(ctx, spanName, options...)
|
||||
}
|
||||
}
|
||||
|
||||
// Fail records a failure in the current span
|
||||
func Fail(ctx context.Context, message string) {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
span.SetStatus(codes.Error, message)
|
||||
}
|
||||
|
||||
// Error records an error in the current span (but unlike Fail, doesn't set the overall span status to Error)
|
||||
func Error(ctx context.Context, err error, options ...trace.EventOption) error {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
span.RecordError(err, options...)
|
||||
return err
|
||||
}
|
||||
|
||||
// Warn records a warning on the current span
|
||||
func Warn(ctx context.Context, msg string) {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
span.AddEvent(warningEventName, trace.WithAttributes(messageKey.String(msg)))
|
||||
}
|
||||
|
||||
// SpotOk adds an Ok result without adding a new Span. This should be used for instantaneous checks with no
|
||||
// possible sub-spans
|
||||
func SpotOk(ctx context.Context, checkName, message string) {
|
||||
addSpotCheckResult(ctx, spotCheckOkEventName, checkName, message)
|
||||
}
|
||||
|
||||
// SpotWarn adds a Warning result without adding a new Span. This should be used for instantaneous checks with no
|
||||
// possible sub-spans
|
||||
func SpotWarn(ctx context.Context, checkName, message string) {
|
||||
addSpotCheckResult(ctx, spotCheckWarnEventName, checkName, message)
|
||||
}
|
||||
|
||||
// SpotError adds an Error result without adding a new Span. This should be used for instantaneous checks with no
|
||||
// possible sub-spans
|
||||
func SpotError(ctx context.Context, checkName string, err error) error {
|
||||
var message string
|
||||
if err != nil {
|
||||
message = err.Error()
|
||||
}
|
||||
addSpotCheckResult(ctx, spotCheckErrorEventName, checkName, message)
|
||||
return err
|
||||
}
|
||||
|
||||
func addSpotCheckResult(ctx context.Context, eventName, checkName, message string) {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
attrs := []trace.EventOption{trace.WithAttributes(nameKey.String(checkName))}
|
||||
if message != "" {
|
||||
attrs = append(attrs, trace.WithAttributes(messageKey.String(message)))
|
||||
}
|
||||
span.AddEvent(eventName, attrs...)
|
||||
}
|
||||
|
||||
func SpotCheck(ctx context.Context, checkName string, f func() error) error {
|
||||
err := f()
|
||||
if err != nil {
|
||||
SpotError(ctx, checkName, err)
|
||||
return err
|
||||
} else {
|
||||
SpotOk(ctx, checkName, "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Test creates a new named span, and executes the provided function within it. If the function returns an error,
|
||||
// the span is considered to have failed.
|
||||
func Test(ctx context.Context, spanName string, function func(context.Context) error, options ...trace.SpanOption) error {
|
||||
ctx, span := StartSpan(ctx, spanName, options...)
|
||||
defer span.End()
|
||||
|
||||
err := function(ctx)
|
||||
if err != nil {
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
}
|
||||
return err
|
||||
}
|
||||
91
vault/diagnose/helpers_test.go
Normal file
91
vault/diagnose/helpers_test.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package diagnose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/go-test/deep"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDiagnoseOtelResults(t *testing.T) {
|
||||
expected := &Result{
|
||||
Name: "make-coffee",
|
||||
Status: WarningStatus,
|
||||
Warnings: []string{
|
||||
"coffee getting low",
|
||||
},
|
||||
Children: []*Result{
|
||||
{
|
||||
Name: "warm-milk",
|
||||
Status: OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "brew-coffee",
|
||||
Status: OkStatus,
|
||||
},
|
||||
{
|
||||
Name: "pick-scone",
|
||||
Status: ErrorStatus,
|
||||
Message: "no scones",
|
||||
},
|
||||
},
|
||||
}
|
||||
sess := New()
|
||||
ctx := Context(context.Background(), sess)
|
||||
|
||||
func() {
|
||||
ctx, span := StartSpan(ctx, "make-coffee")
|
||||
defer span.End()
|
||||
|
||||
makeCoffee(ctx)
|
||||
}()
|
||||
|
||||
results := sess.Finalize(ctx)
|
||||
results.ZeroTimes()
|
||||
if !reflect.DeepEqual(results, expected) {
|
||||
t.Fatalf("results mismatch: %s", strings.Join(deep.Equal(results, expected), "\n"))
|
||||
}
|
||||
results.Write(os.Stdout)
|
||||
}
|
||||
|
||||
const coffeeLeft = 3
|
||||
|
||||
func makeCoffee(ctx context.Context) error {
|
||||
if coffeeLeft < 5 {
|
||||
Warn(ctx, "coffee getting low")
|
||||
}
|
||||
|
||||
err := Test(ctx, "warm-milk", warmMilk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = brewCoffee(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
SpotCheck(ctx, "pick-scone", pickScone)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func warmMilk(ctx context.Context) error {
|
||||
// Always succeeds
|
||||
return nil
|
||||
}
|
||||
|
||||
func brewCoffee(ctx context.Context) error {
|
||||
ctx, span := StartSpan(ctx, "brew-coffee")
|
||||
defer span.End()
|
||||
|
||||
//Brewing happens here, successfully
|
||||
return nil
|
||||
}
|
||||
|
||||
func pickScone() error {
|
||||
return errors.New("no scones")
|
||||
}
|
||||
276
vault/diagnose/output.go
Normal file
276
vault/diagnose/output.go
Normal file
@@ -0,0 +1,276 @@
|
||||
package diagnose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
const (
|
||||
status_unknown = "[ ] "
|
||||
status_ok = "\u001b[32m[ ok ]\u001b[0m "
|
||||
status_failed = "\u001b[31m[failed]\u001b[0m "
|
||||
status_warn = "\u001b[33m[ warn ]\u001b[0m "
|
||||
same_line = "\u001b[F"
|
||||
ErrorStatus = "error"
|
||||
WarningStatus = "warn"
|
||||
OkStatus = "ok"
|
||||
)
|
||||
|
||||
var errUnimplemented = errors.New("unimplemented")
|
||||
|
||||
type Result struct {
|
||||
Time time.Time
|
||||
Name string
|
||||
Warnings []string
|
||||
Status string
|
||||
Message string
|
||||
Children []*Result
|
||||
}
|
||||
|
||||
func (r *Result) sortChildren() {
|
||||
if len(r.Children) > 0 {
|
||||
sort.SliceStable(r.Children, func(i, j int) bool {
|
||||
return r.Children[i].Time.Before(r.Children[j].Time)
|
||||
})
|
||||
for _, c := range r.Children {
|
||||
c.sortChildren()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Result) ZeroTimes() {
|
||||
var zero time.Time
|
||||
r.Time = zero
|
||||
for _, c := range r.Children {
|
||||
c.ZeroTimes()
|
||||
}
|
||||
}
|
||||
|
||||
// TelemetryCollector is an otel SpanProcessor that gathers spans and once the outermost
|
||||
// span ends, walks the otel traces in order to produce a top-down tree of Diagnose results.
|
||||
type TelemetryCollector struct {
|
||||
spans map[trace.SpanID]sdktrace.ReadOnlySpan
|
||||
rootSpan sdktrace.ReadOnlySpan
|
||||
results map[trace.SpanID]*Result
|
||||
RootResult *Result
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewTelemetryCollector() *TelemetryCollector {
|
||||
return &TelemetryCollector{
|
||||
spans: make(map[trace.SpanID]sdktrace.ReadOnlySpan),
|
||||
results: make(map[trace.SpanID]*Result),
|
||||
}
|
||||
}
|
||||
|
||||
// OnStart tracks spans by id for later retrieval
|
||||
func (t *TelemetryCollector) OnStart(_ context.Context, s sdktrace.ReadWriteSpan) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.spans[s.SpanContext().SpanID()] = s
|
||||
}
|
||||
|
||||
func (t *TelemetryCollector) OnEnd(e sdktrace.ReadOnlySpan) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if !e.Parent().HasSpanID() {
|
||||
// First walk the span structs to construct the top down tree results we want
|
||||
for _, s := range t.spans {
|
||||
r := t.getOrBuildResult(s.SpanContext().SpanID())
|
||||
if r != nil {
|
||||
if s.Parent().HasSpanID() {
|
||||
p := t.getOrBuildResult(s.Parent().SpanID())
|
||||
if p != nil {
|
||||
p.Children = append(p.Children, r)
|
||||
}
|
||||
} else {
|
||||
t.RootResult = r
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then walk the results sorting children by time
|
||||
t.RootResult.sortChildren()
|
||||
}
|
||||
}
|
||||
|
||||
// required to implement SpanProcessor, but noops for our purposes
|
||||
func (t *TelemetryCollector) Shutdown(_ context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// required to implement SpanProcessor, but noops for our purposes
|
||||
func (t *TelemetryCollector) ForceFlush(_ context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TelemetryCollector) getOrBuildResult(id trace.SpanID) *Result {
|
||||
s := t.spans[id]
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
r, ok := t.results[id]
|
||||
if !ok {
|
||||
r = &Result{
|
||||
Name: s.Name(),
|
||||
Message: s.StatusMessage(),
|
||||
Time: s.StartTime(),
|
||||
}
|
||||
for _, e := range s.Events() {
|
||||
switch e.Name {
|
||||
case warningEventName:
|
||||
for _, a := range e.Attributes {
|
||||
if a.Key == messageKey {
|
||||
r.Warnings = append(r.Warnings, a.Value.AsString())
|
||||
}
|
||||
}
|
||||
case ErrorStatus:
|
||||
var message string
|
||||
var action string
|
||||
for _, a := range e.Attributes {
|
||||
switch a.Key {
|
||||
case actionKey:
|
||||
action = a.Value.AsString()
|
||||
case errorMessageKey:
|
||||
message = a.Value.AsString()
|
||||
}
|
||||
}
|
||||
if message != "" && action != "" {
|
||||
r.Children = append(r.Children, &Result{
|
||||
Name: action,
|
||||
Status: ErrorStatus,
|
||||
Message: message,
|
||||
})
|
||||
|
||||
}
|
||||
case spotCheckOkEventName:
|
||||
var checkName string
|
||||
var message string
|
||||
for _, a := range e.Attributes {
|
||||
switch a.Key {
|
||||
case nameKey:
|
||||
checkName = a.Value.AsString()
|
||||
case messageKey:
|
||||
message = a.Value.AsString()
|
||||
}
|
||||
}
|
||||
if checkName != "" {
|
||||
r.Children = append(r.Children,
|
||||
&Result{
|
||||
Name: checkName,
|
||||
Status: OkStatus,
|
||||
Message: message,
|
||||
Time: e.Time,
|
||||
})
|
||||
}
|
||||
case spotCheckWarnEventName:
|
||||
var checkName string
|
||||
var message string
|
||||
for _, a := range e.Attributes {
|
||||
switch a.Key {
|
||||
case nameKey:
|
||||
checkName = a.Value.AsString()
|
||||
case messageKey:
|
||||
message = a.Value.AsString()
|
||||
}
|
||||
}
|
||||
if checkName != "" {
|
||||
r.Children = append(r.Children,
|
||||
&Result{
|
||||
Name: checkName,
|
||||
Status: WarningStatus,
|
||||
Message: message,
|
||||
Time: e.Time,
|
||||
})
|
||||
}
|
||||
case spotCheckErrorEventName:
|
||||
var checkName string
|
||||
var message string
|
||||
for _, a := range e.Attributes {
|
||||
switch a.Key {
|
||||
case nameKey:
|
||||
checkName = a.Value.AsString()
|
||||
case messageKey:
|
||||
message = a.Value.AsString()
|
||||
}
|
||||
}
|
||||
if checkName != "" {
|
||||
r.Children = append(r.Children,
|
||||
&Result{
|
||||
Name: checkName,
|
||||
Status: ErrorStatus,
|
||||
Message: message,
|
||||
Time: e.Time,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
switch s.StatusCode() {
|
||||
case codes.Unset:
|
||||
if len(r.Warnings) > 0 {
|
||||
r.Status = WarningStatus
|
||||
} else {
|
||||
r.Status = OkStatus
|
||||
}
|
||||
case codes.Ok:
|
||||
r.Status = OkStatus
|
||||
case codes.Error:
|
||||
r.Status = ErrorStatus
|
||||
}
|
||||
t.results[id] = r
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Write outputs a human readable version of the results tree
|
||||
func (r *Result) Write(writer io.Writer) error {
|
||||
var sb strings.Builder
|
||||
r.write(&sb, 0)
|
||||
_, err := writer.Write([]byte(sb.String()))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Result) write(sb *strings.Builder, depth int) {
|
||||
if r.Status != WarningStatus || (len(r.Warnings) == 0 && r.Message != "") {
|
||||
for i := 0; i < depth; i++ {
|
||||
sb.WriteRune('\t')
|
||||
}
|
||||
switch r.Status {
|
||||
case OkStatus:
|
||||
sb.WriteString(status_ok)
|
||||
case WarningStatus:
|
||||
sb.WriteString(status_warn)
|
||||
case ErrorStatus:
|
||||
sb.WriteString(status_failed)
|
||||
}
|
||||
sb.WriteString(r.Name)
|
||||
|
||||
if r.Message != "" || len(r.Warnings) > 0 {
|
||||
sb.WriteString(": ")
|
||||
}
|
||||
sb.WriteString(r.Message)
|
||||
}
|
||||
for _, w := range r.Warnings {
|
||||
sb.WriteRune('\n')
|
||||
for i := 0; i < depth; i++ {
|
||||
sb.WriteRune('\t')
|
||||
}
|
||||
sb.WriteString(status_warn)
|
||||
sb.WriteString(r.Name)
|
||||
sb.WriteString(": ")
|
||||
sb.WriteString(w)
|
||||
}
|
||||
sb.WriteRune('\n')
|
||||
for _, c := range r.Children {
|
||||
c.write(sb, depth+1)
|
||||
}
|
||||
}
|
||||
@@ -1688,7 +1688,7 @@ func (cluster *TestCluster) StopCore(t testing.T, idx int) {
|
||||
tcc := cluster.Cores[idx]
|
||||
tcc.Logger().Info("stopping core", "core", idx)
|
||||
|
||||
// Stop listeners and call Shutdown()
|
||||
// Stop listeners and call Finalize()
|
||||
if err := tcc.stop(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
4
vendor/github.com/google/go-cmp/cmp/report_compare.go
generated
vendored
4
vendor/github.com/google/go-cmp/cmp/report_compare.go
generated
vendored
@@ -79,7 +79,7 @@ func (opts formatOptions) verbosity() uint {
|
||||
}
|
||||
}
|
||||
|
||||
const maxVerbosityPreset = 3
|
||||
const maxVerbosityPreset = 6
|
||||
|
||||
// verbosityPreset modifies the verbosity settings given an index
|
||||
// between 0 and maxVerbosityPreset, inclusive.
|
||||
@@ -100,7 +100,7 @@ func verbosityPreset(opts formatOptions, i int) formatOptions {
|
||||
func (opts formatOptions) FormatDiff(v *valueNode, ptrs *pointerReferences) (out textNode) {
|
||||
if opts.DiffMode == diffIdentical {
|
||||
opts = opts.WithVerbosity(1)
|
||||
} else {
|
||||
} else if opts.verbosity() < 3 {
|
||||
opts = opts.WithVerbosity(3)
|
||||
}
|
||||
|
||||
|
||||
25
vendor/github.com/google/go-cmp/cmp/report_slices.go
generated
vendored
25
vendor/github.com/google/go-cmp/cmp/report_slices.go
generated
vendored
@@ -26,8 +26,6 @@ func (opts formatOptions) CanFormatDiffSlice(v *valueNode) bool {
|
||||
return false // No differences detected
|
||||
case !v.ValueX.IsValid() || !v.ValueY.IsValid():
|
||||
return false // Both values must be valid
|
||||
case v.Type.Kind() == reflect.Slice && (v.ValueX.Len() == 0 || v.ValueY.Len() == 0):
|
||||
return false // Both slice values have to be non-empty
|
||||
case v.NumIgnored > 0:
|
||||
return false // Some ignore option was used
|
||||
case v.NumTransformed > 0:
|
||||
@@ -45,7 +43,16 @@ func (opts formatOptions) CanFormatDiffSlice(v *valueNode) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
switch t := v.Type; t.Kind() {
|
||||
// Check whether this is an interface with the same concrete types.
|
||||
t := v.Type
|
||||
vx, vy := v.ValueX, v.ValueY
|
||||
if t.Kind() == reflect.Interface && !vx.IsNil() && !vy.IsNil() && vx.Elem().Type() == vy.Elem().Type() {
|
||||
vx, vy = vx.Elem(), vy.Elem()
|
||||
t = vx.Type()
|
||||
}
|
||||
|
||||
// Check whether we provide specialized diffing for this type.
|
||||
switch t.Kind() {
|
||||
case reflect.String:
|
||||
case reflect.Array, reflect.Slice:
|
||||
// Only slices of primitive types have specialized handling.
|
||||
@@ -57,6 +64,11 @@ func (opts formatOptions) CanFormatDiffSlice(v *valueNode) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Both slice values have to be non-empty.
|
||||
if t.Kind() == reflect.Slice && (vx.Len() == 0 || vy.Len() == 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
// If a sufficient number of elements already differ,
|
||||
// use specialized formatting even if length requirement is not met.
|
||||
if v.NumDiff > v.NumSame {
|
||||
@@ -68,7 +80,7 @@ func (opts formatOptions) CanFormatDiffSlice(v *valueNode) bool {
|
||||
|
||||
// Use specialized string diffing for longer slices or strings.
|
||||
const minLength = 64
|
||||
return v.ValueX.Len() >= minLength && v.ValueY.Len() >= minLength
|
||||
return vx.Len() >= minLength && vy.Len() >= minLength
|
||||
}
|
||||
|
||||
// FormatDiffSlice prints a diff for the slices (or strings) represented by v.
|
||||
@@ -77,6 +89,11 @@ func (opts formatOptions) CanFormatDiffSlice(v *valueNode) bool {
|
||||
func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode {
|
||||
assert(opts.DiffMode == diffUnknown)
|
||||
t, vx, vy := v.Type, v.ValueX, v.ValueY
|
||||
if t.Kind() == reflect.Interface {
|
||||
vx, vy = vx.Elem(), vy.Elem()
|
||||
t = vx.Type()
|
||||
opts = opts.WithTypeMode(emitType)
|
||||
}
|
||||
|
||||
// Auto-detect the type of the data.
|
||||
var isLinedText, isText, isBinary bool
|
||||
|
||||
172
vendor/github.com/stretchr/testify/assert/assertion_compare.go
generated
vendored
172
vendor/github.com/stretchr/testify/assert/assertion_compare.go
generated
vendored
@@ -13,12 +13,42 @@ const (
|
||||
compareGreater
|
||||
)
|
||||
|
||||
var (
|
||||
intType = reflect.TypeOf(int(1))
|
||||
int8Type = reflect.TypeOf(int8(1))
|
||||
int16Type = reflect.TypeOf(int16(1))
|
||||
int32Type = reflect.TypeOf(int32(1))
|
||||
int64Type = reflect.TypeOf(int64(1))
|
||||
|
||||
uintType = reflect.TypeOf(uint(1))
|
||||
uint8Type = reflect.TypeOf(uint8(1))
|
||||
uint16Type = reflect.TypeOf(uint16(1))
|
||||
uint32Type = reflect.TypeOf(uint32(1))
|
||||
uint64Type = reflect.TypeOf(uint64(1))
|
||||
|
||||
float32Type = reflect.TypeOf(float32(1))
|
||||
float64Type = reflect.TypeOf(float64(1))
|
||||
|
||||
stringType = reflect.TypeOf("")
|
||||
)
|
||||
|
||||
func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
obj1Value := reflect.ValueOf(obj1)
|
||||
obj2Value := reflect.ValueOf(obj2)
|
||||
|
||||
// throughout this switch we try and avoid calling .Convert() if possible,
|
||||
// as this has a pretty big performance impact
|
||||
switch kind {
|
||||
case reflect.Int:
|
||||
{
|
||||
intobj1 := obj1.(int)
|
||||
intobj2 := obj2.(int)
|
||||
intobj1, ok := obj1.(int)
|
||||
if !ok {
|
||||
intobj1 = obj1Value.Convert(intType).Interface().(int)
|
||||
}
|
||||
intobj2, ok := obj2.(int)
|
||||
if !ok {
|
||||
intobj2 = obj2Value.Convert(intType).Interface().(int)
|
||||
}
|
||||
if intobj1 > intobj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -31,8 +61,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Int8:
|
||||
{
|
||||
int8obj1 := obj1.(int8)
|
||||
int8obj2 := obj2.(int8)
|
||||
int8obj1, ok := obj1.(int8)
|
||||
if !ok {
|
||||
int8obj1 = obj1Value.Convert(int8Type).Interface().(int8)
|
||||
}
|
||||
int8obj2, ok := obj2.(int8)
|
||||
if !ok {
|
||||
int8obj2 = obj2Value.Convert(int8Type).Interface().(int8)
|
||||
}
|
||||
if int8obj1 > int8obj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -45,8 +81,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Int16:
|
||||
{
|
||||
int16obj1 := obj1.(int16)
|
||||
int16obj2 := obj2.(int16)
|
||||
int16obj1, ok := obj1.(int16)
|
||||
if !ok {
|
||||
int16obj1 = obj1Value.Convert(int16Type).Interface().(int16)
|
||||
}
|
||||
int16obj2, ok := obj2.(int16)
|
||||
if !ok {
|
||||
int16obj2 = obj2Value.Convert(int16Type).Interface().(int16)
|
||||
}
|
||||
if int16obj1 > int16obj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -59,8 +101,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Int32:
|
||||
{
|
||||
int32obj1 := obj1.(int32)
|
||||
int32obj2 := obj2.(int32)
|
||||
int32obj1, ok := obj1.(int32)
|
||||
if !ok {
|
||||
int32obj1 = obj1Value.Convert(int32Type).Interface().(int32)
|
||||
}
|
||||
int32obj2, ok := obj2.(int32)
|
||||
if !ok {
|
||||
int32obj2 = obj2Value.Convert(int32Type).Interface().(int32)
|
||||
}
|
||||
if int32obj1 > int32obj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -73,8 +121,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Int64:
|
||||
{
|
||||
int64obj1 := obj1.(int64)
|
||||
int64obj2 := obj2.(int64)
|
||||
int64obj1, ok := obj1.(int64)
|
||||
if !ok {
|
||||
int64obj1 = obj1Value.Convert(int64Type).Interface().(int64)
|
||||
}
|
||||
int64obj2, ok := obj2.(int64)
|
||||
if !ok {
|
||||
int64obj2 = obj2Value.Convert(int64Type).Interface().(int64)
|
||||
}
|
||||
if int64obj1 > int64obj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -87,8 +141,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Uint:
|
||||
{
|
||||
uintobj1 := obj1.(uint)
|
||||
uintobj2 := obj2.(uint)
|
||||
uintobj1, ok := obj1.(uint)
|
||||
if !ok {
|
||||
uintobj1 = obj1Value.Convert(uintType).Interface().(uint)
|
||||
}
|
||||
uintobj2, ok := obj2.(uint)
|
||||
if !ok {
|
||||
uintobj2 = obj2Value.Convert(uintType).Interface().(uint)
|
||||
}
|
||||
if uintobj1 > uintobj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -101,8 +161,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Uint8:
|
||||
{
|
||||
uint8obj1 := obj1.(uint8)
|
||||
uint8obj2 := obj2.(uint8)
|
||||
uint8obj1, ok := obj1.(uint8)
|
||||
if !ok {
|
||||
uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8)
|
||||
}
|
||||
uint8obj2, ok := obj2.(uint8)
|
||||
if !ok {
|
||||
uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8)
|
||||
}
|
||||
if uint8obj1 > uint8obj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -115,8 +181,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Uint16:
|
||||
{
|
||||
uint16obj1 := obj1.(uint16)
|
||||
uint16obj2 := obj2.(uint16)
|
||||
uint16obj1, ok := obj1.(uint16)
|
||||
if !ok {
|
||||
uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16)
|
||||
}
|
||||
uint16obj2, ok := obj2.(uint16)
|
||||
if !ok {
|
||||
uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16)
|
||||
}
|
||||
if uint16obj1 > uint16obj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -129,8 +201,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Uint32:
|
||||
{
|
||||
uint32obj1 := obj1.(uint32)
|
||||
uint32obj2 := obj2.(uint32)
|
||||
uint32obj1, ok := obj1.(uint32)
|
||||
if !ok {
|
||||
uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32)
|
||||
}
|
||||
uint32obj2, ok := obj2.(uint32)
|
||||
if !ok {
|
||||
uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32)
|
||||
}
|
||||
if uint32obj1 > uint32obj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -143,8 +221,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Uint64:
|
||||
{
|
||||
uint64obj1 := obj1.(uint64)
|
||||
uint64obj2 := obj2.(uint64)
|
||||
uint64obj1, ok := obj1.(uint64)
|
||||
if !ok {
|
||||
uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64)
|
||||
}
|
||||
uint64obj2, ok := obj2.(uint64)
|
||||
if !ok {
|
||||
uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64)
|
||||
}
|
||||
if uint64obj1 > uint64obj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -157,8 +241,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Float32:
|
||||
{
|
||||
float32obj1 := obj1.(float32)
|
||||
float32obj2 := obj2.(float32)
|
||||
float32obj1, ok := obj1.(float32)
|
||||
if !ok {
|
||||
float32obj1 = obj1Value.Convert(float32Type).Interface().(float32)
|
||||
}
|
||||
float32obj2, ok := obj2.(float32)
|
||||
if !ok {
|
||||
float32obj2 = obj2Value.Convert(float32Type).Interface().(float32)
|
||||
}
|
||||
if float32obj1 > float32obj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -171,8 +261,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.Float64:
|
||||
{
|
||||
float64obj1 := obj1.(float64)
|
||||
float64obj2 := obj2.(float64)
|
||||
float64obj1, ok := obj1.(float64)
|
||||
if !ok {
|
||||
float64obj1 = obj1Value.Convert(float64Type).Interface().(float64)
|
||||
}
|
||||
float64obj2, ok := obj2.(float64)
|
||||
if !ok {
|
||||
float64obj2 = obj2Value.Convert(float64Type).Interface().(float64)
|
||||
}
|
||||
if float64obj1 > float64obj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -185,8 +281,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||
}
|
||||
case reflect.String:
|
||||
{
|
||||
stringobj1 := obj1.(string)
|
||||
stringobj2 := obj2.(string)
|
||||
stringobj1, ok := obj1.(string)
|
||||
if !ok {
|
||||
stringobj1 = obj1Value.Convert(stringType).Interface().(string)
|
||||
}
|
||||
stringobj2, ok := obj2.(string)
|
||||
if !ok {
|
||||
stringobj2 = obj2Value.Convert(stringType).Interface().(string)
|
||||
}
|
||||
if stringobj1 > stringobj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
@@ -240,6 +342,24 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter
|
||||
return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs)
|
||||
}
|
||||
|
||||
// Positive asserts that the specified element is positive
|
||||
//
|
||||
// assert.Positive(t, 1)
|
||||
// assert.Positive(t, 1.23)
|
||||
func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
||||
zero := reflect.Zero(reflect.TypeOf(e))
|
||||
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs)
|
||||
}
|
||||
|
||||
// Negative asserts that the specified element is negative
|
||||
//
|
||||
// assert.Negative(t, -1)
|
||||
// assert.Negative(t, -1.23)
|
||||
func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
||||
zero := reflect.Zero(reflect.TypeOf(e))
|
||||
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs)
|
||||
}
|
||||
|
||||
func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
||||
97
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
97
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
@@ -114,6 +114,24 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||
return Error(t, err, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
|
||||
// This is a wrapper for errors.As.
|
||||
func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// ErrorIsf asserts that at least one of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Eventuallyf asserts that given condition will be met in waitFor time,
|
||||
// periodically checking target function each tick.
|
||||
//
|
||||
@@ -321,6 +339,54 @@ func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsil
|
||||
return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// IsDecreasingf asserts that the collection is decreasing
|
||||
//
|
||||
// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
|
||||
// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
|
||||
// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
|
||||
func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsDecreasing(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// IsIncreasingf asserts that the collection is increasing
|
||||
//
|
||||
// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
|
||||
// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
|
||||
// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
|
||||
func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsIncreasing(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// IsNonDecreasingf asserts that the collection is not decreasing
|
||||
//
|
||||
// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
|
||||
// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
|
||||
// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
|
||||
func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsNonDecreasing(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// IsNonIncreasingf asserts that the collection is not increasing
|
||||
//
|
||||
// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
|
||||
// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
|
||||
// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
|
||||
func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// IsTypef asserts that the specified objects are of the same type.
|
||||
func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
@@ -375,6 +441,17 @@ func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args .
|
||||
return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Negativef asserts that the specified element is negative
|
||||
//
|
||||
// assert.Negativef(t, -1, "error message %s", "formatted")
|
||||
// assert.Negativef(t, -1.23, "error message %s", "formatted")
|
||||
func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Negative(t, e, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Neverf asserts that the given condition doesn't satisfy in waitFor time,
|
||||
// periodically checking the target function each tick.
|
||||
//
|
||||
@@ -476,6 +553,15 @@ func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg s
|
||||
return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotErrorIsf asserts that at none of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotNilf asserts that the specified object is not nil.
|
||||
//
|
||||
// assert.NotNilf(t, err, "error message %s", "formatted")
|
||||
@@ -572,6 +658,17 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str
|
||||
return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Positivef asserts that the specified element is positive
|
||||
//
|
||||
// assert.Positivef(t, 1, "error message %s", "formatted")
|
||||
// assert.Positivef(t, 1.23, "error message %s", "formatted")
|
||||
func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Positive(t, e, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Regexpf asserts that a specified regexp matches a string.
|
||||
//
|
||||
// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
|
||||
|
||||
194
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
194
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
@@ -204,6 +204,42 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
|
||||
return Error(a.t, err, msgAndArgs...)
|
||||
}
|
||||
|
||||
// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
|
||||
// This is a wrapper for errors.As.
|
||||
func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ErrorAs(a.t, err, target, msgAndArgs...)
|
||||
}
|
||||
|
||||
// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
|
||||
// This is a wrapper for errors.As.
|
||||
func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ErrorAsf(a.t, err, target, msg, args...)
|
||||
}
|
||||
|
||||
// ErrorIs asserts that at least one of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ErrorIs(a.t, err, target, msgAndArgs...)
|
||||
}
|
||||
|
||||
// ErrorIsf asserts that at least one of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ErrorIsf(a.t, err, target, msg, args...)
|
||||
}
|
||||
|
||||
// Errorf asserts that a function returned an error (i.e. not `nil`).
|
||||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
@@ -631,6 +667,102 @@ func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilo
|
||||
return InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
|
||||
}
|
||||
|
||||
// IsDecreasing asserts that the collection is decreasing
|
||||
//
|
||||
// a.IsDecreasing([]int{2, 1, 0})
|
||||
// a.IsDecreasing([]float{2, 1})
|
||||
// a.IsDecreasing([]string{"b", "a"})
|
||||
func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsDecreasing(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsDecreasingf asserts that the collection is decreasing
|
||||
//
|
||||
// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted")
|
||||
// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted")
|
||||
// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted")
|
||||
func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsDecreasingf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
// IsIncreasing asserts that the collection is increasing
|
||||
//
|
||||
// a.IsIncreasing([]int{1, 2, 3})
|
||||
// a.IsIncreasing([]float{1, 2})
|
||||
// a.IsIncreasing([]string{"a", "b"})
|
||||
func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsIncreasing(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsIncreasingf asserts that the collection is increasing
|
||||
//
|
||||
// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted")
|
||||
// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted")
|
||||
// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted")
|
||||
func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsIncreasingf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
// IsNonDecreasing asserts that the collection is not decreasing
|
||||
//
|
||||
// a.IsNonDecreasing([]int{1, 1, 2})
|
||||
// a.IsNonDecreasing([]float{1, 2})
|
||||
// a.IsNonDecreasing([]string{"a", "b"})
|
||||
func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsNonDecreasing(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsNonDecreasingf asserts that the collection is not decreasing
|
||||
//
|
||||
// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted")
|
||||
// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted")
|
||||
// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted")
|
||||
func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsNonDecreasingf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
// IsNonIncreasing asserts that the collection is not increasing
|
||||
//
|
||||
// a.IsNonIncreasing([]int{2, 1, 1})
|
||||
// a.IsNonIncreasing([]float{2, 1})
|
||||
// a.IsNonIncreasing([]string{"b", "a"})
|
||||
func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsNonIncreasing(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsNonIncreasingf asserts that the collection is not increasing
|
||||
//
|
||||
// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted")
|
||||
// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted")
|
||||
// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted")
|
||||
func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsNonIncreasingf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
// IsType asserts that the specified objects are of the same type.
|
||||
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
@@ -739,6 +871,28 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i
|
||||
return Lessf(a.t, e1, e2, msg, args...)
|
||||
}
|
||||
|
||||
// Negative asserts that the specified element is negative
|
||||
//
|
||||
// a.Negative(-1)
|
||||
// a.Negative(-1.23)
|
||||
func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Negative(a.t, e, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Negativef asserts that the specified element is negative
|
||||
//
|
||||
// a.Negativef(-1, "error message %s", "formatted")
|
||||
// a.Negativef(-1.23, "error message %s", "formatted")
|
||||
func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Negativef(a.t, e, msg, args...)
|
||||
}
|
||||
|
||||
// Never asserts that the given condition doesn't satisfy in waitFor time,
|
||||
// periodically checking the target function each tick.
|
||||
//
|
||||
@@ -941,6 +1095,24 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str
|
||||
return NotEqualf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// NotErrorIs asserts that at none of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotErrorIs(a.t, err, target, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotErrorIsf asserts that at none of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotErrorIsf(a.t, err, target, msg, args...)
|
||||
}
|
||||
|
||||
// NotNil asserts that the specified object is not nil.
|
||||
//
|
||||
// a.NotNil(err)
|
||||
@@ -1133,6 +1305,28 @@ func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) b
|
||||
return Panicsf(a.t, f, msg, args...)
|
||||
}
|
||||
|
||||
// Positive asserts that the specified element is positive
|
||||
//
|
||||
// a.Positive(1)
|
||||
// a.Positive(1.23)
|
||||
func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Positive(a.t, e, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Positivef asserts that the specified element is positive
|
||||
//
|
||||
// a.Positivef(1, "error message %s", "formatted")
|
||||
// a.Positivef(1.23, "error message %s", "formatted")
|
||||
func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Positivef(a.t, e, msg, args...)
|
||||
}
|
||||
|
||||
// Regexp asserts that a specified regexp matches a string.
|
||||
//
|
||||
// a.Regexp(regexp.MustCompile("start"), "it's starting")
|
||||
|
||||
81
vendor/github.com/stretchr/testify/assert/assertion_order.go
generated
vendored
Normal file
81
vendor/github.com/stretchr/testify/assert/assertion_order.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
package assert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// isOrdered checks that collection contains orderable elements.
|
||||
func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
|
||||
objKind := reflect.TypeOf(object).Kind()
|
||||
if objKind != reflect.Slice && objKind != reflect.Array {
|
||||
return false
|
||||
}
|
||||
|
||||
objValue := reflect.ValueOf(object)
|
||||
objLen := objValue.Len()
|
||||
|
||||
if objLen <= 1 {
|
||||
return true
|
||||
}
|
||||
|
||||
value := objValue.Index(0)
|
||||
valueInterface := value.Interface()
|
||||
firstValueKind := value.Kind()
|
||||
|
||||
for i := 1; i < objLen; i++ {
|
||||
prevValue := value
|
||||
prevValueInterface := valueInterface
|
||||
|
||||
value = objValue.Index(i)
|
||||
valueInterface = value.Interface()
|
||||
|
||||
compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind)
|
||||
|
||||
if !isComparable {
|
||||
return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...)
|
||||
}
|
||||
|
||||
if !containsValue(allowedComparesResults, compareResult) {
|
||||
return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IsIncreasing asserts that the collection is increasing
|
||||
//
|
||||
// assert.IsIncreasing(t, []int{1, 2, 3})
|
||||
// assert.IsIncreasing(t, []float{1, 2})
|
||||
// assert.IsIncreasing(t, []string{"a", "b"})
|
||||
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs)
|
||||
}
|
||||
|
||||
// IsNonIncreasing asserts that the collection is not increasing
|
||||
//
|
||||
// assert.IsNonIncreasing(t, []int{2, 1, 1})
|
||||
// assert.IsNonIncreasing(t, []float{2, 1})
|
||||
// assert.IsNonIncreasing(t, []string{"b", "a"})
|
||||
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs)
|
||||
}
|
||||
|
||||
// IsDecreasing asserts that the collection is decreasing
|
||||
//
|
||||
// assert.IsDecreasing(t, []int{2, 1, 0})
|
||||
// assert.IsDecreasing(t, []float{2, 1})
|
||||
// assert.IsDecreasing(t, []string{"b", "a"})
|
||||
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs)
|
||||
}
|
||||
|
||||
// IsNonDecreasing asserts that the collection is not decreasing
|
||||
//
|
||||
// assert.IsNonDecreasing(t, []int{1, 1, 2})
|
||||
// assert.IsNonDecreasing(t, []float{1, 2})
|
||||
// assert.IsNonDecreasing(t, []string{"a", "b"})
|
||||
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs)
|
||||
}
|
||||
83
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
83
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
@@ -172,8 +172,8 @@ func isTest(name, prefix string) bool {
|
||||
if len(name) == len(prefix) { // "Test" is ok
|
||||
return true
|
||||
}
|
||||
rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
|
||||
return !unicode.IsLower(rune)
|
||||
r, _ := utf8.DecodeRuneInString(name[len(prefix):])
|
||||
return !unicode.IsLower(r)
|
||||
}
|
||||
|
||||
func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
|
||||
@@ -1622,6 +1622,7 @@ var spewConfig = spew.ConfigState{
|
||||
DisableCapacities: true,
|
||||
SortKeys: true,
|
||||
DisableMethods: true,
|
||||
MaxDepth: 10,
|
||||
}
|
||||
|
||||
type tHelper interface {
|
||||
@@ -1693,3 +1694,81 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorIs asserts that at least one of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if errors.Is(err, target) {
|
||||
return true
|
||||
}
|
||||
|
||||
var expectedText string
|
||||
if target != nil {
|
||||
expectedText = target.Error()
|
||||
}
|
||||
|
||||
chain := buildErrorChainString(err)
|
||||
|
||||
return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+
|
||||
"expected: %q\n"+
|
||||
"in chain: %s", expectedText, chain,
|
||||
), msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotErrorIs asserts that at none of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if !errors.Is(err, target) {
|
||||
return true
|
||||
}
|
||||
|
||||
var expectedText string
|
||||
if target != nil {
|
||||
expectedText = target.Error()
|
||||
}
|
||||
|
||||
chain := buildErrorChainString(err)
|
||||
|
||||
return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
|
||||
"found: %q\n"+
|
||||
"in chain: %s", expectedText, chain,
|
||||
), msgAndArgs...)
|
||||
}
|
||||
|
||||
// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
|
||||
// This is a wrapper for errors.As.
|
||||
func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if errors.As(err, target) {
|
||||
return true
|
||||
}
|
||||
|
||||
chain := buildErrorChainString(err)
|
||||
|
||||
return Fail(t, fmt.Sprintf("Should be in error chain:\n"+
|
||||
"expected: %q\n"+
|
||||
"in chain: %s", target, chain,
|
||||
), msgAndArgs...)
|
||||
}
|
||||
|
||||
func buildErrorChainString(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
e := errors.Unwrap(err)
|
||||
chain := fmt.Sprintf("%q", err.Error())
|
||||
for e != nil {
|
||||
chain += fmt.Sprintf("\n\t%q", e.Error())
|
||||
e = errors.Unwrap(e)
|
||||
}
|
||||
return chain
|
||||
}
|
||||
|
||||
45
vendor/github.com/stretchr/testify/mock/mock.go
generated
vendored
45
vendor/github.com/stretchr/testify/mock/mock.go
generated
vendored
@@ -297,25 +297,52 @@ func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *
|
||||
return -1, expectedCall
|
||||
}
|
||||
|
||||
type matchCandidate struct {
|
||||
call *Call
|
||||
mismatch string
|
||||
diffCount int
|
||||
}
|
||||
|
||||
func (c matchCandidate) isBetterMatchThan(other matchCandidate) bool {
|
||||
if c.call == nil {
|
||||
return false
|
||||
}
|
||||
if other.call == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if c.diffCount > other.diffCount {
|
||||
return false
|
||||
}
|
||||
if c.diffCount < other.diffCount {
|
||||
return true
|
||||
}
|
||||
|
||||
if c.call.Repeatability > 0 && other.call.Repeatability <= 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call, string) {
|
||||
var diffCount int
|
||||
var closestCall *Call
|
||||
var err string
|
||||
var bestMatch matchCandidate
|
||||
|
||||
for _, call := range m.expectedCalls() {
|
||||
if call.Method == method {
|
||||
|
||||
errInfo, tempDiffCount := call.Arguments.Diff(arguments)
|
||||
if tempDiffCount < diffCount || diffCount == 0 {
|
||||
diffCount = tempDiffCount
|
||||
closestCall = call
|
||||
err = errInfo
|
||||
tempCandidate := matchCandidate{
|
||||
call: call,
|
||||
mismatch: errInfo,
|
||||
diffCount: tempDiffCount,
|
||||
}
|
||||
if tempCandidate.isBetterMatchThan(bestMatch) {
|
||||
bestMatch = tempCandidate
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return closestCall, err
|
||||
return bestMatch.call, bestMatch.mismatch
|
||||
}
|
||||
|
||||
func callString(method string, arguments Arguments, includeArgumentValues bool) string {
|
||||
|
||||
248
vendor/github.com/stretchr/testify/require/require.go
generated
vendored
248
vendor/github.com/stretchr/testify/require/require.go
generated
vendored
@@ -256,6 +256,54 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
|
||||
// This is a wrapper for errors.As.
|
||||
func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.ErrorAs(t, err, target, msgAndArgs...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
|
||||
// This is a wrapper for errors.As.
|
||||
func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.ErrorAsf(t, err, target, msg, args...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// ErrorIs asserts that at least one of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.ErrorIs(t, err, target, msgAndArgs...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// ErrorIsf asserts that at least one of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.ErrorIsf(t, err, target, msg, args...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Errorf asserts that a function returned an error (i.e. not `nil`).
|
||||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
@@ -806,6 +854,126 @@ func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon fl
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// IsDecreasing asserts that the collection is decreasing
|
||||
//
|
||||
// assert.IsDecreasing(t, []int{2, 1, 0})
|
||||
// assert.IsDecreasing(t, []float{2, 1})
|
||||
// assert.IsDecreasing(t, []string{"b", "a"})
|
||||
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.IsDecreasing(t, object, msgAndArgs...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// IsDecreasingf asserts that the collection is decreasing
|
||||
//
|
||||
// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
|
||||
// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
|
||||
// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
|
||||
func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.IsDecreasingf(t, object, msg, args...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// IsIncreasing asserts that the collection is increasing
|
||||
//
|
||||
// assert.IsIncreasing(t, []int{1, 2, 3})
|
||||
// assert.IsIncreasing(t, []float{1, 2})
|
||||
// assert.IsIncreasing(t, []string{"a", "b"})
|
||||
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.IsIncreasing(t, object, msgAndArgs...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// IsIncreasingf asserts that the collection is increasing
|
||||
//
|
||||
// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
|
||||
// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
|
||||
// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
|
||||
func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.IsIncreasingf(t, object, msg, args...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// IsNonDecreasing asserts that the collection is not decreasing
|
||||
//
|
||||
// assert.IsNonDecreasing(t, []int{1, 1, 2})
|
||||
// assert.IsNonDecreasing(t, []float{1, 2})
|
||||
// assert.IsNonDecreasing(t, []string{"a", "b"})
|
||||
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.IsNonDecreasing(t, object, msgAndArgs...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// IsNonDecreasingf asserts that the collection is not decreasing
|
||||
//
|
||||
// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
|
||||
// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
|
||||
// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
|
||||
func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.IsNonDecreasingf(t, object, msg, args...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// IsNonIncreasing asserts that the collection is not increasing
|
||||
//
|
||||
// assert.IsNonIncreasing(t, []int{2, 1, 1})
|
||||
// assert.IsNonIncreasing(t, []float{2, 1})
|
||||
// assert.IsNonIncreasing(t, []string{"b", "a"})
|
||||
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.IsNonIncreasing(t, object, msgAndArgs...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// IsNonIncreasingf asserts that the collection is not increasing
|
||||
//
|
||||
// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
|
||||
// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
|
||||
// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
|
||||
func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.IsNonIncreasingf(t, object, msg, args...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// IsType asserts that the specified objects are of the same type.
|
||||
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
@@ -944,6 +1112,34 @@ func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...inter
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Negative asserts that the specified element is negative
|
||||
//
|
||||
// assert.Negative(t, -1)
|
||||
// assert.Negative(t, -1.23)
|
||||
func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.Negative(t, e, msgAndArgs...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Negativef asserts that the specified element is negative
|
||||
//
|
||||
// assert.Negativef(t, -1, "error message %s", "formatted")
|
||||
// assert.Negativef(t, -1.23, "error message %s", "formatted")
|
||||
func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.Negativef(t, e, msg, args...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Never asserts that the given condition doesn't satisfy in waitFor time,
|
||||
// periodically checking the target function each tick.
|
||||
//
|
||||
@@ -1200,6 +1396,30 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string,
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// NotErrorIs asserts that at none of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.NotErrorIs(t, err, target, msgAndArgs...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// NotErrorIsf asserts that at none of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.NotErrorIsf(t, err, target, msg, args...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// NotNil asserts that the specified object is not nil.
|
||||
//
|
||||
// assert.NotNil(t, err)
|
||||
@@ -1446,6 +1666,34 @@ func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Positive asserts that the specified element is positive
|
||||
//
|
||||
// assert.Positive(t, 1)
|
||||
// assert.Positive(t, 1.23)
|
||||
func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.Positive(t, e, msgAndArgs...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Positivef asserts that the specified element is positive
|
||||
//
|
||||
// assert.Positivef(t, 1, "error message %s", "formatted")
|
||||
// assert.Positivef(t, 1.23, "error message %s", "formatted")
|
||||
func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.Positivef(t, e, msg, args...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Regexp asserts that a specified regexp matches a string.
|
||||
//
|
||||
// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
|
||||
|
||||
194
vendor/github.com/stretchr/testify/require/require_forward.go
generated
vendored
194
vendor/github.com/stretchr/testify/require/require_forward.go
generated
vendored
@@ -205,6 +205,42 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) {
|
||||
Error(a.t, err, msgAndArgs...)
|
||||
}
|
||||
|
||||
// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
|
||||
// This is a wrapper for errors.As.
|
||||
func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
ErrorAs(a.t, err, target, msgAndArgs...)
|
||||
}
|
||||
|
||||
// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
|
||||
// This is a wrapper for errors.As.
|
||||
func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
ErrorAsf(a.t, err, target, msg, args...)
|
||||
}
|
||||
|
||||
// ErrorIs asserts that at least one of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
ErrorIs(a.t, err, target, msgAndArgs...)
|
||||
}
|
||||
|
||||
// ErrorIsf asserts that at least one of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
ErrorIsf(a.t, err, target, msg, args...)
|
||||
}
|
||||
|
||||
// Errorf asserts that a function returned an error (i.e. not `nil`).
|
||||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
@@ -632,6 +668,102 @@ func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilo
|
||||
InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
|
||||
}
|
||||
|
||||
// IsDecreasing asserts that the collection is decreasing
|
||||
//
|
||||
// a.IsDecreasing([]int{2, 1, 0})
|
||||
// a.IsDecreasing([]float{2, 1})
|
||||
// a.IsDecreasing([]string{"b", "a"})
|
||||
func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
IsDecreasing(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsDecreasingf asserts that the collection is decreasing
|
||||
//
|
||||
// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted")
|
||||
// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted")
|
||||
// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted")
|
||||
func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
IsDecreasingf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
// IsIncreasing asserts that the collection is increasing
|
||||
//
|
||||
// a.IsIncreasing([]int{1, 2, 3})
|
||||
// a.IsIncreasing([]float{1, 2})
|
||||
// a.IsIncreasing([]string{"a", "b"})
|
||||
func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
IsIncreasing(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsIncreasingf asserts that the collection is increasing
|
||||
//
|
||||
// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted")
|
||||
// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted")
|
||||
// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted")
|
||||
func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
IsIncreasingf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
// IsNonDecreasing asserts that the collection is not decreasing
|
||||
//
|
||||
// a.IsNonDecreasing([]int{1, 1, 2})
|
||||
// a.IsNonDecreasing([]float{1, 2})
|
||||
// a.IsNonDecreasing([]string{"a", "b"})
|
||||
func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
IsNonDecreasing(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsNonDecreasingf asserts that the collection is not decreasing
|
||||
//
|
||||
// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted")
|
||||
// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted")
|
||||
// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted")
|
||||
func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
IsNonDecreasingf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
// IsNonIncreasing asserts that the collection is not increasing
|
||||
//
|
||||
// a.IsNonIncreasing([]int{2, 1, 1})
|
||||
// a.IsNonIncreasing([]float{2, 1})
|
||||
// a.IsNonIncreasing([]string{"b", "a"})
|
||||
func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
IsNonIncreasing(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsNonIncreasingf asserts that the collection is not increasing
|
||||
//
|
||||
// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted")
|
||||
// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted")
|
||||
// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted")
|
||||
func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
IsNonIncreasingf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
// IsType asserts that the specified objects are of the same type.
|
||||
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
@@ -740,6 +872,28 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i
|
||||
Lessf(a.t, e1, e2, msg, args...)
|
||||
}
|
||||
|
||||
// Negative asserts that the specified element is negative
|
||||
//
|
||||
// a.Negative(-1)
|
||||
// a.Negative(-1.23)
|
||||
func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Negative(a.t, e, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Negativef asserts that the specified element is negative
|
||||
//
|
||||
// a.Negativef(-1, "error message %s", "formatted")
|
||||
// a.Negativef(-1.23, "error message %s", "formatted")
|
||||
func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Negativef(a.t, e, msg, args...)
|
||||
}
|
||||
|
||||
// Never asserts that the given condition doesn't satisfy in waitFor time,
|
||||
// periodically checking the target function each tick.
|
||||
//
|
||||
@@ -942,6 +1096,24 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str
|
||||
NotEqualf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// NotErrorIs asserts that at none of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotErrorIs(a.t, err, target, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotErrorIsf asserts that at none of the errors in err's chain matches target.
|
||||
// This is a wrapper for errors.Is.
|
||||
func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotErrorIsf(a.t, err, target, msg, args...)
|
||||
}
|
||||
|
||||
// NotNil asserts that the specified object is not nil.
|
||||
//
|
||||
// a.NotNil(err)
|
||||
@@ -1134,6 +1306,28 @@ func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interfa
|
||||
Panicsf(a.t, f, msg, args...)
|
||||
}
|
||||
|
||||
// Positive asserts that the specified element is positive
|
||||
//
|
||||
// a.Positive(1)
|
||||
// a.Positive(1.23)
|
||||
func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Positive(a.t, e, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Positivef asserts that the specified element is positive
|
||||
//
|
||||
// a.Positivef(1, "error message %s", "formatted")
|
||||
// a.Positivef(1.23, "error message %s", "formatted")
|
||||
func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Positivef(a.t, e, msg, args...)
|
||||
}
|
||||
|
||||
// Regexp asserts that a specified regexp matches a string.
|
||||
//
|
||||
// a.Regexp(regexp.MustCompile("start"), "it's starting")
|
||||
|
||||
19
vendor/go.opentelemetry.io/otel/.gitignore
generated
vendored
Normal file
19
vendor/go.opentelemetry.io/otel/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
.tools/
|
||||
.idea/
|
||||
.vscode/
|
||||
*.iml
|
||||
*.so
|
||||
coverage.*
|
||||
|
||||
gen/
|
||||
|
||||
/example/jaeger/jaeger
|
||||
/example/namedtracer/namedtracer
|
||||
/example/opencensus/opencensus
|
||||
/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
|
||||
- golint
|
||||
- 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:
|
||||
- golint
|
||||
# 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:
|
||||
- golint
|
||||
|
||||
linters-settings:
|
||||
misspell:
|
||||
locale: US
|
||||
ignore-words:
|
||||
- cancelled
|
||||
goimports:
|
||||
local-prefixes: go.opentelemetry.io
|
||||
1319
vendor/go.opentelemetry.io/otel/CHANGELOG.md
generated
vendored
Normal file
1319
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
|
||||
|
||||
CODEOWNERS @MrAlias @Aneurysm9
|
||||
380
vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
generated
vendored
Normal file
380
vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,380 @@
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
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.
|
||||
* 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:
|
||||
https://github.com/open-telemetry/opentelemetry-specification/issues/165
|
||||
|
||||
## 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 `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 `struct` must contain configuration options.
|
||||
|
||||
```go
|
||||
// config contains configuration options for a thing.
|
||||
type config struct {
|
||||
// options ...
|
||||
}
|
||||
```
|
||||
|
||||
In general the `config` `struct` 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 `config` are not shared across package boundaries.
|
||||
Meaning a `config` from one package should not be directly used by another.
|
||||
|
||||
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)
|
||||
}
|
||||
```
|
||||
|
||||
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}
|
||||
}
|
||||
```
|
||||
|
||||
#### Instantiation
|
||||
|
||||
Using this configuration pattern to configure instantiation with a `New*`
|
||||
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 {…}
|
||||
```
|
||||
|
||||
### Interface Type
|
||||
|
||||
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.
|
||||
|
||||
## 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
|
||||
|
||||
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.
|
||||
179
vendor/go.opentelemetry.io/otel/Makefile
generated
vendored
Normal file
179
vendor/go.opentelemetry.io/otel/Makefile
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
# 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)
|
||||
|
||||
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
|
||||
|
||||
STRINGER = $(TOOLS)/stringer
|
||||
$(TOOLS)/stringer: PACKAGE=golang.org/x/tools/cmd/stringer
|
||||
|
||||
$(TOOLS)/gojq: PACKAGE=github.com/itchyny/gojq/cmd/gojq
|
||||
|
||||
.PHONY: tools
|
||||
tools: $(CROSSLINK) $(GOLANGCI_LINT) $(MISSPELL) $(STRINGER) $(TOOLS)/gojq
|
||||
|
||||
|
||||
# Build
|
||||
|
||||
.PHONY: examples generate build
|
||||
examples:
|
||||
@set -e; for dir in $(EXAMPLES); do \
|
||||
echo "$(GO) build $${dir}/..."; \
|
||||
(cd "$${dir}" && \
|
||||
$(GO) build .); \
|
||||
done
|
||||
|
||||
generate: $(STRINGER)
|
||||
set -e; for dir in $(ALL_GO_MOD_DIRS); do \
|
||||
echo "$(GO) generate $${dir}/..."; \
|
||||
(cd "$${dir}" && \
|
||||
PATH="$(TOOLS):$${PATH}" $(GO) generate ./...); \
|
||||
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:
|
||||
@set -e; \
|
||||
printf "" > coverage.txt; \
|
||||
for dir in $(ALL_COVERAGE_MOD_DIRS); do \
|
||||
echo "$(GO) test -coverpkg=./... -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); \
|
||||
[ -f "$${dir}/coverage.out" ] && cat "$${dir}/coverage.out" >> coverage.txt; \
|
||||
done; \
|
||||
sed -i.bak -e '2,$$ { /^mode: /d; }' 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: 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/*' ! -path './exporters/otlp/internal/opentelemetry-proto/*') ; 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 "$$f" .github/dependabot.yml \
|
||||
|| echo "$$f"; \
|
||||
done; \
|
||||
); \
|
||||
if [ -n "$$result" ]; then \
|
||||
echo "missing go.mod dependabot check:"; echo "$$result"; \
|
||||
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
|
||||
92
vendor/go.opentelemetry.io/otel/README.md
generated
vendored
Normal file
92
vendor/go.opentelemetry.io/otel/README.md
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
# OpenTelemetry-Go
|
||||
|
||||
[](https://github.com/open-telemetry/opentelemetry-go/actions?query=workflow%3Aci+branch%3Amain)
|
||||
[](https://pkg.go.dev/go.opentelemetry.io/otel)
|
||||
[](https://goreportcard.com/report/go.opentelemetry.io/otel)
|
||||
[](https://cloud-native.slack.com/archives/C01NPAXACKT)
|
||||
|
||||
|
||||
The Go [OpenTelemetry](https://opentelemetry.io/) implementation.
|
||||
|
||||
## Project Status
|
||||
|
||||
**Warning**: this project 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.
|
||||
|
||||
Our progress towards a GA release candidate is tracked in [this project
|
||||
board](https://github.com/orgs/open-telemetry/projects/5). This release
|
||||
candidate will follow semantic versioning and will be released with a major
|
||||
version greater than zero.
|
||||
|
||||
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.15 | amd64 |
|
||||
| Ubuntu | 1.14 | amd64 |
|
||||
| Ubuntu | 1.15 | 386 |
|
||||
| Ubuntu | 1.14 | 386 |
|
||||
| MacOS | 1.15 | amd64 |
|
||||
| MacOS | 1.14 | amd64 |
|
||||
| Windows | 1.15 | amd64 |
|
||||
| Windows | 1.14 | amd64 |
|
||||
| Windows | 1.15 | 386 |
|
||||
| Windows | 1.14 | 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.
|
||||
|
||||
You can find officially supported exporters [here](./exporters/) and in the
|
||||
companion [contrib
|
||||
repository](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/exporters/metric).
|
||||
Additionally, there are many vendor specific or 3rd party exporters for
|
||||
OpenTelemetry. These exporters are broken down by
|
||||
[trace](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/export/trace?tab=importedby)
|
||||
and
|
||||
[metric](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/export/metric?tab=importedby)
|
||||
support.
|
||||
|
||||
## Contributing
|
||||
|
||||
See the [contributing documentation](CONTRIBUTING.md).
|
||||
81
vendor/go.opentelemetry.io/otel/RELEASING.md
generated
vendored
Normal file
81
vendor/go.opentelemetry.io/otel/RELEASING.md
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
# Release Process
|
||||
|
||||
## Pre-Release
|
||||
|
||||
Update go.mod for submodules to depend on the new release which will happen in the next step.
|
||||
|
||||
1. Run the pre-release script. It creates a branch `pre_release_<new tag>` that will contain all release changes.
|
||||
|
||||
```
|
||||
./pre_release.sh -t <new tag>
|
||||
```
|
||||
|
||||
2. Verify the changes.
|
||||
|
||||
```
|
||||
git diff main
|
||||
```
|
||||
|
||||
This should have changed the version for all modules to be `<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.
|
||||
|
||||
***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. Run the tag.sh script using the `<commit-hash>` of the commit on the main branch for the merged Pull Request.
|
||||
|
||||
```
|
||||
./tag.sh <new tag> <commit-hash>
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
## 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.
|
||||
217
vendor/go.opentelemetry.io/otel/VERSIONING.md
generated
vendored
Normal file
217
vendor/go.opentelemetry.io/otel/VERSIONING.md
generated
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
# 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).
|
||||
* 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-rc.1`
|
||||
* `otel/trace`: `v1.0.0-rc.1`
|
||||
* `otel/baggage`: `v1.0.0-rc.1`
|
||||
* `otel/sdk/trace`: `v1.0.0-rc.1`
|
||||
|
||||
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-rc.2`
|
||||
* `otel/trace`: `v1.0.0-rc.2`
|
||||
* `otel/baggage`: `v1.0.0-rc.2`
|
||||
* `otel/sdk/trace`: `v1.0.0-rc.2`
|
||||
|
||||
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-rc.1`
|
||||
* `otel/trace`: `v1.1.0-rc.1`
|
||||
* `otel/metric`: `v1.1.0-rc.1`
|
||||
* `otel/baggage`: `v1.1.0-rc.1`
|
||||
* `otel/sdk/trace`: `v1.1.0-rc.1`
|
||||
* `otel/sdk/metric`: `v1.1.0-rc.1`
|
||||
|
||||
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`
|
||||
20
vendor/go.opentelemetry.io/otel/attribute/doc.go
generated
vendored
Normal file
20
vendor/go.opentelemetry.io/otel/attribute/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 attribute provides key and value attributes.
|
||||
//
|
||||
// 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 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
|
||||
}
|
||||
102
vendor/go.opentelemetry.io/otel/attribute/key.go
generated
vendored
Normal file
102
vendor/go.opentelemetry.io/otel/attribute/key.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
// 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 key and a bool value at the same time, then
|
||||
// instead of calling Key(name).Bool(value) consider using a
|
||||
// convenience function provided by the api/key package -
|
||||
// key.Bool(name, value).
|
||||
func (k Key) Bool(v bool) KeyValue {
|
||||
return KeyValue{
|
||||
Key: k,
|
||||
Value: BoolValue(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Int64 creates a KeyValue instance with an INT64 Value.
|
||||
//
|
||||
// If creating both key and an int64 value at the same time, then
|
||||
// instead of calling Key(name).Int64(value) consider using a
|
||||
// convenience function provided by the api/key package -
|
||||
// key.Int64(name, value).
|
||||
func (k Key) Int64(v int64) KeyValue {
|
||||
return KeyValue{
|
||||
Key: k,
|
||||
Value: Int64Value(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Float64 creates a KeyValue instance with a FLOAT64 Value.
|
||||
//
|
||||
// If creating both key and a float64 value at the same time, then
|
||||
// instead of calling Key(name).Float64(value) consider using a
|
||||
// convenience function provided by the api/key package -
|
||||
// key.Float64(name, value).
|
||||
func (k Key) Float64(v float64) KeyValue {
|
||||
return KeyValue{
|
||||
Key: k,
|
||||
Value: Float64Value(v),
|
||||
}
|
||||
}
|
||||
|
||||
// String creates a KeyValue instance with a STRING Value.
|
||||
//
|
||||
// If creating both key and a string value at the same time, then
|
||||
// instead of calling Key(name).String(value) consider using a
|
||||
// convenience function provided by the api/key package -
|
||||
// key.String(name, value).
|
||||
func (k Key) String(v string) KeyValue {
|
||||
return KeyValue{
|
||||
Key: k,
|
||||
Value: StringValue(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Int creates a KeyValue instance with an INT64 Value.
|
||||
//
|
||||
// If creating both key and an int value at the same time, then
|
||||
// instead of calling Key(name).Int(value) consider using a
|
||||
// convenience function provided by the api/key package -
|
||||
// key.Int(name, value).
|
||||
func (k Key) Int(v int) KeyValue {
|
||||
return KeyValue{
|
||||
Key: k,
|
||||
Value: IntValue(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Defined returns true for non-empty keys.
|
||||
func (k Key) Defined() bool {
|
||||
return len(k) != 0
|
||||
}
|
||||
|
||||
// Array creates a KeyValue instance with a ARRAY Value.
|
||||
//
|
||||
// If creating both key and a array value at the same time, then
|
||||
// instead of calling Key(name).String(value) consider using a
|
||||
// convenience function provided by the api/key package -
|
||||
// key.Array(name, value).
|
||||
func (k Key) Array(v interface{}) KeyValue {
|
||||
return KeyValue{
|
||||
Key: k,
|
||||
Value: ArrayValue(v),
|
||||
}
|
||||
}
|
||||
108
vendor/go.opentelemetry.io/otel/attribute/kv.go
generated
vendored
Normal file
108
vendor/go.opentelemetry.io/otel/attribute/kv.go
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
// 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"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// 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 new key-value pair with a passed name and a bool
|
||||
// value.
|
||||
func Bool(k string, v bool) KeyValue {
|
||||
return Key(k).Bool(v)
|
||||
}
|
||||
|
||||
// Int64 creates a new key-value pair with a passed name and an int64
|
||||
// value.
|
||||
func Int64(k string, v int64) KeyValue {
|
||||
return Key(k).Int64(v)
|
||||
}
|
||||
|
||||
// Float64 creates a new key-value pair with a passed name and a float64
|
||||
// value.
|
||||
func Float64(k string, v float64) KeyValue {
|
||||
return Key(k).Float64(v)
|
||||
}
|
||||
|
||||
// String creates a new key-value pair with a passed name and a string
|
||||
// value.
|
||||
func String(k, v string) KeyValue {
|
||||
return Key(k).String(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())
|
||||
}
|
||||
|
||||
// Int creates a new key-value pair instance with a passed name and
|
||||
// either an int32 or an int64 value, depending on whether the int
|
||||
// type is 32 or 64 bits wide.
|
||||
func Int(k string, v int) KeyValue {
|
||||
return Key(k).Int(v)
|
||||
}
|
||||
|
||||
// Array creates a new key-value pair with a passed name and a array.
|
||||
// Only arrays of primitive type are supported.
|
||||
func Array(k string, v interface{}) KeyValue {
|
||||
return Key(k).Array(v)
|
||||
}
|
||||
|
||||
// Any creates a new key-value pair instance with a passed name and
|
||||
// automatic type inference. This is slower, and not type-safe.
|
||||
func Any(k string, value interface{}) KeyValue {
|
||||
if value == nil {
|
||||
return String(k, "<nil>")
|
||||
}
|
||||
|
||||
if stringer, ok := value.(fmt.Stringer); ok {
|
||||
return String(k, stringer.String())
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(value)
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
return Array(k, value)
|
||||
case reflect.Bool:
|
||||
return Bool(k, rv.Bool())
|
||||
case reflect.Int, reflect.Int8, reflect.Int16:
|
||||
return Int(k, int(rv.Int()))
|
||||
case reflect.Int64:
|
||||
return Int64(k, rv.Int())
|
||||
case reflect.Float64:
|
||||
return Float64(k, rv.Float())
|
||||
case reflect.String:
|
||||
return String(k, rv.String())
|
||||
}
|
||||
if b, err := json.Marshal(value); b != nil && err == nil {
|
||||
return String(k, string(b))
|
||||
}
|
||||
return String(k, fmt.Sprint(value))
|
||||
}
|
||||
471
vendor/go.opentelemetry.io/otel/attribute/set.go
generated
vendored
Normal file
471
vendor/go.opentelemetry.io/otel/attribute/set.go
generated
vendored
Normal file
@@ -0,0 +1,471 @@
|
||||
// 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"
|
||||
"sync"
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
lock sync.Mutex
|
||||
encoders [maxConcurrentEncoders]EncoderID
|
||||
encoded [maxConcurrentEncoders]string
|
||||
}
|
||||
|
||||
// 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{},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
const maxConcurrentEncoders = 3
|
||||
|
||||
// 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`. The result will be cached in this `*Set`.
|
||||
func (l *Set) Encoded(encoder Encoder) string {
|
||||
if l == nil || encoder == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
id := encoder.ID()
|
||||
if !id.Valid() {
|
||||
// Invalid IDs are not cached.
|
||||
return encoder.Encode(l.Iter())
|
||||
}
|
||||
|
||||
var lookup *string
|
||||
l.lock.Lock()
|
||||
for idx := 0; idx < maxConcurrentEncoders; idx++ {
|
||||
if l.encoders[idx] == id {
|
||||
lookup = &l.encoded[idx]
|
||||
break
|
||||
}
|
||||
}
|
||||
l.lock.Unlock()
|
||||
|
||||
if lookup != nil {
|
||||
return *lookup
|
||||
}
|
||||
|
||||
r := encoder.Encode(l.Iter())
|
||||
|
||||
l.lock.Lock()
|
||||
defer l.lock.Unlock()
|
||||
|
||||
for idx := 0; idx < maxConcurrentEncoders; idx++ {
|
||||
if l.encoders[idx] == id {
|
||||
return l.encoded[idx]
|
||||
}
|
||||
if !l.encoders[idx].Valid() {
|
||||
l.encoders[idx] = id
|
||||
l.encoded[idx] = r
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This is a performance cliff. Find a way for this to
|
||||
// generate a warning.
|
||||
return r
|
||||
}
|
||||
|
||||
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 //nolint
|
||||
}
|
||||
|
||||
// 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 //nolint
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
28
vendor/go.opentelemetry.io/otel/attribute/type_string.go
generated
vendored
Normal file
28
vendor/go.opentelemetry.io/otel/attribute/type_string.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// 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[ARRAY-5]
|
||||
}
|
||||
|
||||
const _Type_name = "INVALIDBOOLINT64FLOAT64STRINGARRAY"
|
||||
|
||||
var _Type_index = [...]uint8{0, 7, 11, 16, 23, 29, 34}
|
||||
|
||||
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]]
|
||||
}
|
||||
204
vendor/go.opentelemetry.io/otel/attribute/value.go
generated
vendored
Normal file
204
vendor/go.opentelemetry.io/otel/attribute/value.go
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
// 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"
|
||||
"reflect"
|
||||
"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
|
||||
// TODO Lazy value type?
|
||||
|
||||
array 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
|
||||
// ARRAY is an array Type Value used to store 1-dimensional slices or
|
||||
// arrays of bool, int, int32, int64, uint, uint32, uint64, float,
|
||||
// float32, float64, or string types.
|
||||
ARRAY
|
||||
)
|
||||
|
||||
// BoolValue creates a BOOL Value.
|
||||
func BoolValue(v bool) Value {
|
||||
return Value{
|
||||
vtype: BOOL,
|
||||
numeric: internal.BoolToRaw(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Int64Value creates an INT64 Value.
|
||||
func Int64Value(v int64) Value {
|
||||
return Value{
|
||||
vtype: INT64,
|
||||
numeric: internal.Int64ToRaw(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Float64Value creates a FLOAT64 Value.
|
||||
func Float64Value(v float64) Value {
|
||||
return Value{
|
||||
vtype: FLOAT64,
|
||||
numeric: internal.Float64ToRaw(v),
|
||||
}
|
||||
}
|
||||
|
||||
// StringValue creates a STRING Value.
|
||||
func StringValue(v string) Value {
|
||||
return Value{
|
||||
vtype: STRING,
|
||||
stringly: v,
|
||||
}
|
||||
}
|
||||
|
||||
// IntValue creates an INT64 Value.
|
||||
func IntValue(v int) Value {
|
||||
return Int64Value(int64(v))
|
||||
}
|
||||
|
||||
// ArrayValue creates an ARRAY value from an array or slice.
|
||||
// Only arrays or slices of bool, int, int64, float, float64, or string types are allowed.
|
||||
// Specifically, arrays and slices can not contain other arrays, slices, structs, or non-standard
|
||||
// types. If the passed value is not an array or slice of these types an
|
||||
// INVALID value is returned.
|
||||
func ArrayValue(v interface{}) Value {
|
||||
switch reflect.TypeOf(v).Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
// get array type regardless of dimensions
|
||||
typ := reflect.TypeOf(v).Elem()
|
||||
kind := typ.Kind()
|
||||
switch kind {
|
||||
case reflect.Bool, reflect.Int, reflect.Int64,
|
||||
reflect.Float64, reflect.String:
|
||||
val := reflect.ValueOf(v)
|
||||
length := val.Len()
|
||||
frozen := reflect.Indirect(reflect.New(reflect.ArrayOf(length, typ)))
|
||||
reflect.Copy(frozen, val)
|
||||
return Value{
|
||||
vtype: ARRAY,
|
||||
array: frozen.Interface(),
|
||||
}
|
||||
default:
|
||||
return Value{vtype: INVALID}
|
||||
}
|
||||
}
|
||||
return Value{vtype: INVALID}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// AsInt64 returns the int64 value. Make sure that the Value's type is
|
||||
// INT64.
|
||||
func (v Value) AsInt64() int64 {
|
||||
return internal.RawToInt64(v.numeric)
|
||||
}
|
||||
|
||||
// AsFloat64 returns the float64 value. Make sure that the Value's
|
||||
// type is FLOAT64.
|
||||
func (v Value) AsFloat64() float64 {
|
||||
return internal.RawToFloat64(v.numeric)
|
||||
}
|
||||
|
||||
// AsString returns the string value. Make sure that the Value's type
|
||||
// is STRING.
|
||||
func (v Value) AsString() string {
|
||||
return v.stringly
|
||||
}
|
||||
|
||||
// AsArray returns the array Value as an interface{}.
|
||||
func (v Value) AsArray() interface{} {
|
||||
return v.array
|
||||
}
|
||||
|
||||
type unknownValueType struct{}
|
||||
|
||||
// AsInterface returns Value's data as interface{}.
|
||||
func (v Value) AsInterface() interface{} {
|
||||
switch v.Type() {
|
||||
case ARRAY:
|
||||
return v.AsArray()
|
||||
case BOOL:
|
||||
return v.AsBool()
|
||||
case INT64:
|
||||
return v.AsInt64()
|
||||
case FLOAT64:
|
||||
return v.AsFloat64()
|
||||
case STRING:
|
||||
return v.stringly
|
||||
}
|
||||
return unknownValueType{}
|
||||
}
|
||||
|
||||
// Emit returns a string representation of Value's data.
|
||||
func (v Value) Emit() string {
|
||||
switch v.Type() {
|
||||
case ARRAY:
|
||||
return fmt.Sprint(v.array)
|
||||
case BOOL:
|
||||
return strconv.FormatBool(v.AsBool())
|
||||
case INT64:
|
||||
return strconv.FormatInt(v.AsInt64(), 10)
|
||||
case FLOAT64:
|
||||
return fmt.Sprint(v.AsFloat64())
|
||||
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)
|
||||
}
|
||||
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
|
||||
}
|
||||
25
vendor/go.opentelemetry.io/otel/codes/doc.go
generated
vendored
Normal file
25
vendor/go.opentelemetry.io/otel/codes/doc.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// 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.
|
||||
|
||||
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.
|
||||
|
||||
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"
|
||||
38
vendor/go.opentelemetry.io/otel/doc.go
generated
vendored
Normal file
38
vendor/go.opentelemetry.io/otel/doc.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 provides global access to the OpenTelemetry API. The subpackages of
|
||||
the otel package provide an implementation 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.
|
||||
|
||||
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"
|
||||
22
vendor/go.opentelemetry.io/otel/error_handler.go
generated
vendored
Normal file
22
vendor/go.opentelemetry.io/otel/error_handler.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// 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 {
|
||||
// Handle handles any error deemed irremediable by an OpenTelemetry
|
||||
// component.
|
||||
Handle(error)
|
||||
}
|
||||
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
|
||||
55
vendor/go.opentelemetry.io/otel/go.mod
generated
vendored
Normal file
55
vendor/go.opentelemetry.io/otel/go.mod
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
module go.opentelemetry.io/otel
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/google/go-cmp v0.5.5
|
||||
github.com/stretchr/testify v1.7.0
|
||||
go.opentelemetry.io/otel/metric v0.20.0
|
||||
go.opentelemetry.io/otel/oteltest v0.20.0
|
||||
go.opentelemetry.io/otel/trace v0.20.0
|
||||
)
|
||||
|
||||
replace go.opentelemetry.io/otel => ./
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opencensus => ./bridge/opencensus
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opentracing => ./bridge/opentracing
|
||||
|
||||
replace go.opentelemetry.io/otel/example/jaeger => ./example/jaeger
|
||||
|
||||
replace go.opentelemetry.io/otel/example/namedtracer => ./example/namedtracer
|
||||
|
||||
replace go.opentelemetry.io/otel/example/opencensus => ./example/opencensus
|
||||
|
||||
replace go.opentelemetry.io/otel/example/otel-collector => ./example/otel-collector
|
||||
|
||||
replace go.opentelemetry.io/otel/example/prom-collector => ./example/prom-collector
|
||||
|
||||
replace go.opentelemetry.io/otel/example/prometheus => ./example/prometheus
|
||||
|
||||
replace go.opentelemetry.io/otel/example/zipkin => ./example/zipkin
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/metric/prometheus => ./exporters/metric/prometheus
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/otlp => ./exporters/otlp
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/stdout => ./exporters/stdout
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/trace/jaeger => ./exporters/trace/jaeger
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/trace/zipkin => ./exporters/trace/zipkin
|
||||
|
||||
replace go.opentelemetry.io/otel/internal/tools => ./internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ./sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ./metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ./oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ./sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ./sdk/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/trace => ./trace
|
||||
15
vendor/go.opentelemetry.io/otel/go.sum
generated
vendored
Normal file
15
vendor/go.opentelemetry.io/otel/go.sum
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
89
vendor/go.opentelemetry.io/otel/handler.go
generated
vendored
Normal file
89
vendor/go.opentelemetry.io/otel/handler.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// 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 = &loggingErrorHandler{
|
||||
l: log.New(os.Stderr, "", log.LstdFlags),
|
||||
}
|
||||
|
||||
// delegateErrorHandlerOnce ensures that a user provided ErrorHandler is
|
||||
// only ever registered once.
|
||||
delegateErrorHandlerOnce sync.Once
|
||||
|
||||
// Comiple time check that loggingErrorHandler implements ErrorHandler.
|
||||
_ ErrorHandler = (*loggingErrorHandler)(nil)
|
||||
)
|
||||
|
||||
// loggingErrorHandler logs all errors to STDERR.
|
||||
type loggingErrorHandler struct {
|
||||
delegate atomic.Value
|
||||
|
||||
l *log.Logger
|
||||
}
|
||||
|
||||
// setDelegate sets the ErrorHandler delegate if one is not already set.
|
||||
func (h *loggingErrorHandler) setDelegate(d ErrorHandler) {
|
||||
if h.delegate.Load() != nil {
|
||||
// Delegate already registered
|
||||
return
|
||||
}
|
||||
h.delegate.Store(d)
|
||||
}
|
||||
|
||||
// Handle implements ErrorHandler.
|
||||
func (h *loggingErrorHandler) 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. If no ErrorHandler
|
||||
// instance has been set (`SetErrorHandler`), the default ErrorHandler which
|
||||
// logs errors to STDERR is returned.
|
||||
func GetErrorHandler() ErrorHandler {
|
||||
return globalErrorHandler
|
||||
}
|
||||
|
||||
// SetErrorHandler sets the global ErrorHandler to be h.
|
||||
func SetErrorHandler(h ErrorHandler) {
|
||||
delegateErrorHandlerOnce.Do(func() {
|
||||
current := GetErrorHandler()
|
||||
if current == h {
|
||||
return
|
||||
}
|
||||
if internalHandler, ok := current.(*loggingErrorHandler); ok {
|
||||
internalHandler.setDelegate(h)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Handle is a convience function for ErrorHandler().Handle(err)
|
||||
func Handle(err error) {
|
||||
GetErrorHandler().Handle(err)
|
||||
}
|
||||
338
vendor/go.opentelemetry.io/otel/internal/baggage/baggage.go
generated
vendored
Normal file
338
vendor/go.opentelemetry.io/otel/internal/baggage/baggage.go
generated
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
// 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 types and functions to manage W3C Baggage.
|
||||
package baggage
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
type rawMap map[attribute.Key]attribute.Value
|
||||
type keySet map[attribute.Key]struct{}
|
||||
|
||||
// Map is an immutable storage for correlations.
|
||||
type Map struct {
|
||||
m rawMap
|
||||
}
|
||||
|
||||
// MapUpdate contains information about correlation changes to be
|
||||
// made.
|
||||
type MapUpdate struct {
|
||||
// DropSingleK contains a single key to be dropped from
|
||||
// correlations. Use this to avoid an overhead of a slice
|
||||
// allocation if there is only one key to drop.
|
||||
DropSingleK attribute.Key
|
||||
// DropMultiK contains all the keys to be dropped from
|
||||
// correlations.
|
||||
DropMultiK []attribute.Key
|
||||
|
||||
// SingleKV contains a single key-value pair to be added to
|
||||
// correlations. Use this to avoid an overhead of a slice
|
||||
// allocation if there is only one key-value pair to add.
|
||||
SingleKV attribute.KeyValue
|
||||
// MultiKV contains all the key-value pairs to be added to
|
||||
// correlations.
|
||||
MultiKV []attribute.KeyValue
|
||||
}
|
||||
|
||||
func newMap(raw rawMap) Map {
|
||||
return Map{
|
||||
m: raw,
|
||||
}
|
||||
}
|
||||
|
||||
// NewEmptyMap creates an empty correlations map.
|
||||
func NewEmptyMap() Map {
|
||||
return newMap(nil)
|
||||
}
|
||||
|
||||
// NewMap creates a map with the contents of the update applied. In
|
||||
// this function, having an update with DropSingleK or DropMultiK
|
||||
// makes no sense - those fields are effectively ignored.
|
||||
func NewMap(update MapUpdate) Map {
|
||||
return NewEmptyMap().Apply(update)
|
||||
}
|
||||
|
||||
// Apply creates a copy of the map with the contents of the update
|
||||
// applied. Apply will first drop the keys from DropSingleK and
|
||||
// DropMultiK, then add key-value pairs from SingleKV and MultiKV.
|
||||
func (m Map) Apply(update MapUpdate) Map {
|
||||
delSet, addSet := getModificationSets(update)
|
||||
mapSize := getNewMapSize(m.m, delSet, addSet)
|
||||
|
||||
r := make(rawMap, mapSize)
|
||||
for k, v := range m.m {
|
||||
// do not copy items we want to drop
|
||||
if _, ok := delSet[k]; ok {
|
||||
continue
|
||||
}
|
||||
// do not copy items we would overwrite
|
||||
if _, ok := addSet[k]; ok {
|
||||
continue
|
||||
}
|
||||
r[k] = v
|
||||
}
|
||||
if update.SingleKV.Key.Defined() {
|
||||
r[update.SingleKV.Key] = update.SingleKV.Value
|
||||
}
|
||||
for _, kv := range update.MultiKV {
|
||||
r[kv.Key] = kv.Value
|
||||
}
|
||||
if len(r) == 0 {
|
||||
r = nil
|
||||
}
|
||||
return newMap(r)
|
||||
}
|
||||
|
||||
func getModificationSets(update MapUpdate) (delSet, addSet keySet) {
|
||||
deletionsCount := len(update.DropMultiK)
|
||||
if update.DropSingleK.Defined() {
|
||||
deletionsCount++
|
||||
}
|
||||
if deletionsCount > 0 {
|
||||
delSet = make(map[attribute.Key]struct{}, deletionsCount)
|
||||
for _, k := range update.DropMultiK {
|
||||
delSet[k] = struct{}{}
|
||||
}
|
||||
if update.DropSingleK.Defined() {
|
||||
delSet[update.DropSingleK] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
additionsCount := len(update.MultiKV)
|
||||
if update.SingleKV.Key.Defined() {
|
||||
additionsCount++
|
||||
}
|
||||
if additionsCount > 0 {
|
||||
addSet = make(map[attribute.Key]struct{}, additionsCount)
|
||||
for _, k := range update.MultiKV {
|
||||
addSet[k.Key] = struct{}{}
|
||||
}
|
||||
if update.SingleKV.Key.Defined() {
|
||||
addSet[update.SingleKV.Key] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getNewMapSize(m rawMap, delSet, addSet keySet) int {
|
||||
mapSizeDiff := 0
|
||||
for k := range addSet {
|
||||
if _, ok := m[k]; !ok {
|
||||
mapSizeDiff++
|
||||
}
|
||||
}
|
||||
for k := range delSet {
|
||||
if _, ok := m[k]; ok {
|
||||
if _, inAddSet := addSet[k]; !inAddSet {
|
||||
mapSizeDiff--
|
||||
}
|
||||
}
|
||||
}
|
||||
return len(m) + mapSizeDiff
|
||||
}
|
||||
|
||||
// Value gets a value from correlations map and returns a boolean
|
||||
// value indicating whether the key exist in the map.
|
||||
func (m Map) Value(k attribute.Key) (attribute.Value, bool) {
|
||||
value, ok := m.m[k]
|
||||
return value, ok
|
||||
}
|
||||
|
||||
// HasValue returns a boolean value indicating whether the key exist
|
||||
// in the map.
|
||||
func (m Map) HasValue(k attribute.Key) bool {
|
||||
_, has := m.Value(k)
|
||||
return has
|
||||
}
|
||||
|
||||
// Len returns a length of the map.
|
||||
func (m Map) Len() int {
|
||||
return len(m.m)
|
||||
}
|
||||
|
||||
// Foreach calls a passed callback once on each key-value pair until
|
||||
// all the key-value pairs of the map were iterated or the callback
|
||||
// returns false, whichever happens first.
|
||||
func (m Map) Foreach(f func(attribute.KeyValue) bool) {
|
||||
for k, v := range m.m {
|
||||
if !f(attribute.KeyValue{
|
||||
Key: k,
|
||||
Value: v,
|
||||
}) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type correlationsType struct{}
|
||||
|
||||
// SetHookFunc describes a type of a callback that is called when
|
||||
// storing baggage in the context.
|
||||
type SetHookFunc func(context.Context) context.Context
|
||||
|
||||
// GetHookFunc describes a type of a callback that is called when
|
||||
// getting baggage from the context.
|
||||
type GetHookFunc func(context.Context, Map) Map
|
||||
|
||||
// value under this key is either of type Map or correlationsData
|
||||
var correlationsKey = &correlationsType{}
|
||||
|
||||
type correlationsData struct {
|
||||
m Map
|
||||
setHook SetHookFunc
|
||||
getHook GetHookFunc
|
||||
}
|
||||
|
||||
func (d correlationsData) isHookless() bool {
|
||||
return d.setHook == nil && d.getHook == nil
|
||||
}
|
||||
|
||||
type hookKind int
|
||||
|
||||
const (
|
||||
hookKindSet hookKind = iota
|
||||
hookKindGet
|
||||
)
|
||||
|
||||
func (d *correlationsData) overrideHook(kind hookKind, setHook SetHookFunc, getHook GetHookFunc) {
|
||||
switch kind {
|
||||
case hookKindSet:
|
||||
d.setHook = setHook
|
||||
case hookKindGet:
|
||||
d.getHook = getHook
|
||||
}
|
||||
}
|
||||
|
||||
// ContextWithSetHook installs a hook function that will be invoked
|
||||
// every time ContextWithMap is called. To avoid unnecessary callback
|
||||
// invocations (recursive or not), the callback can temporarily clear
|
||||
// the hooks from the context with the ContextWithNoHooks function.
|
||||
//
|
||||
// Note that NewContext also calls ContextWithMap, so the hook will be
|
||||
// invoked.
|
||||
//
|
||||
// Passing nil SetHookFunc creates a context with no set hook to call.
|
||||
//
|
||||
// This function should not be used by applications or libraries. It
|
||||
// is mostly for interoperation with other observability APIs.
|
||||
func ContextWithSetHook(ctx context.Context, hook SetHookFunc) context.Context {
|
||||
return contextWithHook(ctx, hookKindSet, hook, nil)
|
||||
}
|
||||
|
||||
// ContextWithGetHook installs a hook function that will be invoked
|
||||
// every time MapFromContext is called. To avoid unnecessary callback
|
||||
// invocations (recursive or not), the callback can temporarily clear
|
||||
// the hooks from the context with the ContextWithNoHooks function.
|
||||
//
|
||||
// Note that NewContext also calls MapFromContext, so the hook will be
|
||||
// invoked.
|
||||
//
|
||||
// Passing nil GetHookFunc creates a context with no get hook to call.
|
||||
//
|
||||
// This function should not be used by applications or libraries. It
|
||||
// is mostly for interoperation with other observability APIs.
|
||||
func ContextWithGetHook(ctx context.Context, hook GetHookFunc) context.Context {
|
||||
return contextWithHook(ctx, hookKindGet, nil, hook)
|
||||
}
|
||||
|
||||
func contextWithHook(ctx context.Context, kind hookKind, setHook SetHookFunc, getHook GetHookFunc) context.Context {
|
||||
switch v := ctx.Value(correlationsKey).(type) {
|
||||
case correlationsData:
|
||||
v.overrideHook(kind, setHook, getHook)
|
||||
if v.isHookless() {
|
||||
return context.WithValue(ctx, correlationsKey, v.m)
|
||||
}
|
||||
return context.WithValue(ctx, correlationsKey, v)
|
||||
case Map:
|
||||
return contextWithOneHookAndMap(ctx, kind, setHook, getHook, v)
|
||||
default:
|
||||
m := NewEmptyMap()
|
||||
return contextWithOneHookAndMap(ctx, kind, setHook, getHook, m)
|
||||
}
|
||||
}
|
||||
|
||||
func contextWithOneHookAndMap(ctx context.Context, kind hookKind, setHook SetHookFunc, getHook GetHookFunc, m Map) context.Context {
|
||||
d := correlationsData{m: m}
|
||||
d.overrideHook(kind, setHook, getHook)
|
||||
if d.isHookless() {
|
||||
return ctx
|
||||
}
|
||||
return context.WithValue(ctx, correlationsKey, d)
|
||||
}
|
||||
|
||||
// ContextWithNoHooks creates a context with all the hooks
|
||||
// disabled. Also returns old set and get hooks. This function can be
|
||||
// used to temporarily clear the context from hooks and then reinstate
|
||||
// them by calling ContextWithSetHook and ContextWithGetHook functions
|
||||
// passing the hooks returned by this function.
|
||||
//
|
||||
// This function should not be used by applications or libraries. It
|
||||
// is mostly for interoperation with other observability APIs.
|
||||
func ContextWithNoHooks(ctx context.Context) (context.Context, SetHookFunc, GetHookFunc) {
|
||||
switch v := ctx.Value(correlationsKey).(type) {
|
||||
case correlationsData:
|
||||
return context.WithValue(ctx, correlationsKey, v.m), v.setHook, v.getHook
|
||||
default:
|
||||
return ctx, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ContextWithMap returns a context with the Map entered into it.
|
||||
func ContextWithMap(ctx context.Context, m Map) context.Context {
|
||||
switch v := ctx.Value(correlationsKey).(type) {
|
||||
case correlationsData:
|
||||
v.m = m
|
||||
ctx = context.WithValue(ctx, correlationsKey, v)
|
||||
if v.setHook != nil {
|
||||
ctx = v.setHook(ctx)
|
||||
}
|
||||
return ctx
|
||||
default:
|
||||
return context.WithValue(ctx, correlationsKey, m)
|
||||
}
|
||||
}
|
||||
|
||||
// ContextWithNoCorrelationData returns a context stripped of correlation
|
||||
// data.
|
||||
func ContextWithNoCorrelationData(ctx context.Context) context.Context {
|
||||
return context.WithValue(ctx, correlationsKey, nil)
|
||||
}
|
||||
|
||||
// NewContext returns a context with the map from passed context
|
||||
// updated with the passed key-value pairs.
|
||||
func NewContext(ctx context.Context, keyvalues ...attribute.KeyValue) context.Context {
|
||||
return ContextWithMap(ctx, MapFromContext(ctx).Apply(MapUpdate{
|
||||
MultiKV: keyvalues,
|
||||
}))
|
||||
}
|
||||
|
||||
// MapFromContext gets the current Map from a Context.
|
||||
func MapFromContext(ctx context.Context) Map {
|
||||
switch v := ctx.Value(correlationsKey).(type) {
|
||||
case correlationsData:
|
||||
if v.getHook != nil {
|
||||
return v.getHook(ctx, v.m)
|
||||
}
|
||||
return v.m
|
||||
case Map:
|
||||
return v
|
||||
default:
|
||||
return NewEmptyMap()
|
||||
}
|
||||
}
|
||||
348
vendor/go.opentelemetry.io/otel/internal/global/meter.go
generated
vendored
Normal file
348
vendor/go.opentelemetry.io/otel/internal/global/meter.go
generated
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
// 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 (
|
||||
"context"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/number"
|
||||
"go.opentelemetry.io/otel/metric/registry"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
Name, Version 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 metric.MeterImpl
|
||||
impl meterImpl
|
||||
}
|
||||
|
||||
type instrument struct {
|
||||
descriptor metric.Descriptor
|
||||
}
|
||||
|
||||
type syncImpl struct {
|
||||
delegate unsafe.Pointer // (*metric.SyncImpl)
|
||||
|
||||
instrument
|
||||
}
|
||||
|
||||
type asyncImpl struct {
|
||||
delegate unsafe.Pointer // (*metric.AsyncImpl)
|
||||
|
||||
instrument
|
||||
|
||||
runner metric.AsyncRunner
|
||||
}
|
||||
|
||||
// SyncImpler is implemented by all of the sync metric
|
||||
// instruments.
|
||||
type SyncImpler interface {
|
||||
SyncImpl() metric.SyncImpl
|
||||
}
|
||||
|
||||
// AsyncImpler is implemented by all of the async
|
||||
// metric instruments.
|
||||
type AsyncImpler interface {
|
||||
AsyncImpl() metric.AsyncImpl
|
||||
}
|
||||
|
||||
type syncHandle struct {
|
||||
delegate unsafe.Pointer // (*metric.BoundInstrumentImpl)
|
||||
|
||||
inst *syncImpl
|
||||
labels []attribute.KeyValue
|
||||
|
||||
initialize sync.Once
|
||||
}
|
||||
|
||||
var _ metric.MeterProvider = &meterProvider{}
|
||||
var _ metric.MeterImpl = &meterImpl{}
|
||||
var _ metric.InstrumentImpl = &syncImpl{}
|
||||
var _ metric.BoundSyncImpl = &syncHandle{}
|
||||
var _ metric.AsyncImpl = &asyncImpl{}
|
||||
|
||||
func (inst *instrument) Descriptor() metric.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.Name, key.Version, 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...)
|
||||
}
|
||||
|
||||
key := meterKey{
|
||||
Name: instrumentationName,
|
||||
Version: metric.NewMeterConfig(opts...).InstrumentationVersion,
|
||||
}
|
||||
entry, ok := p.meters[key]
|
||||
if !ok {
|
||||
entry = &meterEntry{}
|
||||
entry.unique = registry.NewUniqueInstrumentMeterImpl(&entry.impl)
|
||||
p.meters[key] = entry
|
||||
|
||||
}
|
||||
return metric.WrapMeterImpl(entry.unique, key.Name, metric.WithInstrumentationVersion(key.Version))
|
||||
}
|
||||
|
||||
// Meter interface and delegation
|
||||
|
||||
func (m *meterImpl) setDelegate(name, version string, provider metric.MeterProvider) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
d := new(metric.MeterImpl)
|
||||
*d = provider.Meter(name, metric.WithInstrumentationVersion(version)).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 metric.Descriptor) (metric.SyncImpl, error) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if meterPtr := (*metric.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 metric.MeterImpl) {
|
||||
implPtr := new(metric.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 := (*metric.SyncImpl)(atomic.LoadPointer(&inst.delegate)); implPtr != nil {
|
||||
return (*implPtr).Implementation()
|
||||
}
|
||||
return inst
|
||||
}
|
||||
|
||||
func (inst *syncImpl) Bind(labels []attribute.KeyValue) metric.BoundSyncImpl {
|
||||
if implPtr := (*metric.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 := (*metric.BoundSyncImpl)(atomic.LoadPointer(&bound.delegate))
|
||||
|
||||
if implPtr == nil {
|
||||
return
|
||||
}
|
||||
|
||||
(*implPtr).Unbind()
|
||||
}
|
||||
|
||||
// Async delegation
|
||||
|
||||
func (m *meterImpl) NewAsyncInstrument(
|
||||
desc metric.Descriptor,
|
||||
runner metric.AsyncRunner,
|
||||
) (metric.AsyncImpl, error) {
|
||||
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if meterPtr := (*metric.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 := (*metric.AsyncImpl)(atomic.LoadPointer(&obs.delegate)); implPtr != nil {
|
||||
return (*implPtr).Implementation()
|
||||
}
|
||||
return obs
|
||||
}
|
||||
|
||||
func (obs *asyncImpl) setDelegate(d metric.MeterImpl) {
|
||||
implPtr := new(metric.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 ...metric.Measurement) {
|
||||
if delegatePtr := (*metric.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 := (*metric.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 := (*metric.SyncImpl)(atomic.LoadPointer(&bound.inst.delegate))
|
||||
if instPtr == nil {
|
||||
return
|
||||
}
|
||||
var implPtr *metric.BoundSyncImpl
|
||||
bound.initialize.Do(func() {
|
||||
implPtr = new(metric.BoundSyncImpl)
|
||||
*implPtr = (*instPtr).Bind(bound.labels)
|
||||
atomic.StorePointer(&bound.delegate, unsafe.Pointer(implPtr))
|
||||
})
|
||||
if implPtr == nil {
|
||||
implPtr = (*metric.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),
|
||||
}
|
||||
}
|
||||
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 (
|
||||
"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()
|
||||
}
|
||||
143
vendor/go.opentelemetry.io/otel/internal/global/state.go
generated
vendored
Normal file
143
vendor/go.opentelemetry.io/otel/internal/global/state.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 global
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
type (
|
||||
tracerProviderHolder struct {
|
||||
tp trace.TracerProvider
|
||||
}
|
||||
|
||||
meterProviderHolder struct {
|
||||
mp metric.MeterProvider
|
||||
}
|
||||
|
||||
propagatorsHolder struct {
|
||||
tm propagation.TextMapPropagator
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
globalTracer = defaultTracerValue()
|
||||
globalMeter = defaultMeterValue()
|
||||
globalPropagators = defaultPropagatorsValue()
|
||||
|
||||
delegateMeterOnce sync.Once
|
||||
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})
|
||||
}
|
||||
|
||||
// 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})
|
||||
}
|
||||
|
||||
// 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 defaultMeterValue() *atomic.Value {
|
||||
v := &atomic.Value{}
|
||||
v.Store(meterProviderHolder{mp: newMeterProvider()})
|
||||
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()
|
||||
globalMeter = defaultMeterValue()
|
||||
globalPropagators = defaultPropagatorsValue()
|
||||
delegateMeterOnce = sync.Once{}
|
||||
delegateTraceOnce = sync.Once{}
|
||||
delegateTextMapPropagatorOnce = sync.Once{}
|
||||
}
|
||||
147
vendor/go.opentelemetry.io/otel/internal/global/trace.go
generated
vendored
Normal file
147
vendor/go.opentelemetry.io/otel/internal/global/trace.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
// 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
|
||||
|
||||
/*
|
||||
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/internal/trace/noop"
|
||||
"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.
|
||||
|
||||
key := il{
|
||||
name: name,
|
||||
version: trace.NewTracerConfig(opts...).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}
|
||||
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
|
||||
|
||||
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.SpanOption) (context.Context, trace.Span) {
|
||||
delegate := t.delegate.Load()
|
||||
if delegate != nil {
|
||||
return delegate.(trace.Tracer).Start(ctx, name, opts...)
|
||||
}
|
||||
return noop.Tracer.Start(ctx, name, opts...)
|
||||
}
|
||||
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 (
|
||||
"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))
|
||||
}
|
||||
35
vendor/go.opentelemetry.io/otel/internal/trace/noop/noop.go
generated
vendored
Normal file
35
vendor/go.opentelemetry.io/otel/internal/trace/noop/noop.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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 noop provides noop tracing implementations for tracer and span.
|
||||
package noop
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
var (
|
||||
// Tracer is a noop tracer that starts noop spans.
|
||||
Tracer trace.Tracer
|
||||
|
||||
// Span is a noop Span.
|
||||
Span trace.Span
|
||||
)
|
||||
|
||||
func init() {
|
||||
Tracer = trace.NewNoopTracerProvider().Tracer("")
|
||||
_, Span = Tracer.Start(context.Background(), "")
|
||||
}
|
||||
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.
|
||||
128
vendor/go.opentelemetry.io/otel/metric/config.go
generated
vendored
Normal file
128
vendor/go.opentelemetry.io/otel/metric/config.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
// 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/unit"
|
||||
)
|
||||
|
||||
// InstrumentConfig contains options for metric instrument descriptors.
|
||||
type InstrumentConfig struct {
|
||||
// Description describes the instrument in human-readable terms.
|
||||
Description string
|
||||
// Unit describes the measurement unit for a instrument.
|
||||
Unit unit.Unit
|
||||
// InstrumentationName is the name of the library providing
|
||||
// instrumentation.
|
||||
InstrumentationName string
|
||||
// InstrumentationVersion is the version of the library providing
|
||||
// instrumentation.
|
||||
InstrumentationVersion string
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// WithDescription applies provided description.
|
||||
func WithDescription(desc string) InstrumentOption {
|
||||
return descriptionOption(desc)
|
||||
}
|
||||
|
||||
type descriptionOption string
|
||||
|
||||
func (d descriptionOption) ApplyInstrument(config *InstrumentConfig) {
|
||||
config.Description = string(d)
|
||||
}
|
||||
|
||||
// WithUnit applies provided unit.
|
||||
func WithUnit(unit unit.Unit) InstrumentOption {
|
||||
return unitOption(unit)
|
||||
}
|
||||
|
||||
type unitOption unit.Unit
|
||||
|
||||
func (u unitOption) ApplyInstrument(config *InstrumentConfig) {
|
||||
config.Unit = unit.Unit(u)
|
||||
}
|
||||
|
||||
// WithInstrumentationName sets the instrumentation name.
|
||||
func WithInstrumentationName(name string) InstrumentOption {
|
||||
return instrumentationNameOption(name)
|
||||
}
|
||||
|
||||
type instrumentationNameOption string
|
||||
|
||||
func (i instrumentationNameOption) ApplyInstrument(config *InstrumentConfig) {
|
||||
config.InstrumentationName = string(i)
|
||||
}
|
||||
|
||||
// MeterConfig contains options for Meters.
|
||||
type MeterConfig struct {
|
||||
// InstrumentationVersion is the version of the library providing
|
||||
// instrumentation.
|
||||
InstrumentationVersion string
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// InstrumentationOption is an interface for applying instrumentation specific
|
||||
// options.
|
||||
type InstrumentationOption interface {
|
||||
InstrumentOption
|
||||
MeterOption
|
||||
}
|
||||
|
||||
// WithInstrumentationVersion sets the instrumentation version.
|
||||
func WithInstrumentationVersion(version string) InstrumentationOption {
|
||||
return instrumentationVersionOption(version)
|
||||
}
|
||||
|
||||
type instrumentationVersionOption string
|
||||
|
||||
func (i instrumentationVersionOption) ApplyMeter(config *MeterConfig) {
|
||||
config.InstrumentationVersion = string(i)
|
||||
}
|
||||
|
||||
func (i instrumentationVersionOption) ApplyInstrument(config *InstrumentConfig) {
|
||||
config.InstrumentationVersion = string(i)
|
||||
}
|
||||
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.
|
||||
Additive instruments are semantically intended for capturing a sum. Grouping
|
||||
instruments are intended for capturing a distribution.
|
||||
|
||||
Additive instruments may be monotonic, in which case they are non-decreasing
|
||||
and naturally define a rate.
|
||||
|
||||
The synchronous instrument names are:
|
||||
|
||||
Counter: additive, monotonic
|
||||
UpDownCounter: additive
|
||||
ValueRecorder: grouping
|
||||
|
||||
and the asynchronous instruments are:
|
||||
|
||||
SumObserver: additive, monotonic
|
||||
UpDownSumObserver: additive
|
||||
ValueObserver: 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"
|
||||
54
vendor/go.opentelemetry.io/otel/metric/go.mod
generated
vendored
Normal file
54
vendor/go.opentelemetry.io/otel/metric/go.mod
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
module go.opentelemetry.io/otel/metric
|
||||
|
||||
go 1.14
|
||||
|
||||
replace go.opentelemetry.io/otel => ../
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opencensus => ../bridge/opencensus
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opentracing => ../bridge/opentracing
|
||||
|
||||
replace go.opentelemetry.io/otel/example/jaeger => ../example/jaeger
|
||||
|
||||
replace go.opentelemetry.io/otel/example/namedtracer => ../example/namedtracer
|
||||
|
||||
replace go.opentelemetry.io/otel/example/opencensus => ../example/opencensus
|
||||
|
||||
replace go.opentelemetry.io/otel/example/otel-collector => ../example/otel-collector
|
||||
|
||||
replace go.opentelemetry.io/otel/example/prom-collector => ../example/prom-collector
|
||||
|
||||
replace go.opentelemetry.io/otel/example/prometheus => ../example/prometheus
|
||||
|
||||
replace go.opentelemetry.io/otel/example/zipkin => ../example/zipkin
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/metric/prometheus => ../exporters/metric/prometheus
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/otlp => ../exporters/otlp
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/stdout => ../exporters/stdout
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/trace/jaeger => ../exporters/trace/jaeger
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/trace/zipkin => ../exporters/trace/zipkin
|
||||
|
||||
replace go.opentelemetry.io/otel/internal/tools => ../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ./
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../sdk/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/trace => ../trace
|
||||
|
||||
require (
|
||||
github.com/google/go-cmp v0.5.5
|
||||
github.com/stretchr/testify v1.7.0
|
||||
go.opentelemetry.io/otel v0.20.0
|
||||
go.opentelemetry.io/otel/oteltest v0.20.0
|
||||
)
|
||||
15
vendor/go.opentelemetry.io/otel/metric/go.sum
generated
vendored
Normal file
15
vendor/go.opentelemetry.io/otel/metric/go.sum
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
28
vendor/go.opentelemetry.io/otel/metric/instrumentkind_string.go
generated
vendored
Normal file
28
vendor/go.opentelemetry.io/otel/metric/instrumentkind_string.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// Code generated by "stringer -type=InstrumentKind"; DO NOT EDIT.
|
||||
|
||||
package metric
|
||||
|
||||
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[ValueRecorderInstrumentKind-0]
|
||||
_ = x[ValueObserverInstrumentKind-1]
|
||||
_ = x[CounterInstrumentKind-2]
|
||||
_ = x[UpDownCounterInstrumentKind-3]
|
||||
_ = x[SumObserverInstrumentKind-4]
|
||||
_ = x[UpDownSumObserverInstrumentKind-5]
|
||||
}
|
||||
|
||||
const _InstrumentKind_name = "ValueRecorderInstrumentKindValueObserverInstrumentKindCounterInstrumentKindUpDownCounterInstrumentKindSumObserverInstrumentKindUpDownSumObserverInstrumentKind"
|
||||
|
||||
var _InstrumentKind_index = [...]uint8{0, 27, 54, 75, 102, 127, 158}
|
||||
|
||||
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]]
|
||||
}
|
||||
577
vendor/go.opentelemetry.io/otel/metric/metric.go
generated
vendored
Normal file
577
vendor/go.opentelemetry.io/otel/metric/metric.go
generated
vendored
Normal file
@@ -0,0 +1,577 @@
|
||||
// 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/unit"
|
||||
)
|
||||
|
||||
// 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 MeterImpl
|
||||
name, version string
|
||||
}
|
||||
|
||||
// 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, 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, 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, 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, UpDownCounterInstrumentKind, number.Float64Kind, options))
|
||||
}
|
||||
|
||||
// NewInt64ValueRecorder creates a new integer ValueRecorder 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) NewInt64ValueRecorder(name string, opts ...InstrumentOption) (Int64ValueRecorder, error) {
|
||||
return wrapInt64ValueRecorderInstrument(
|
||||
m.newSync(name, ValueRecorderInstrumentKind, number.Int64Kind, opts))
|
||||
}
|
||||
|
||||
// NewFloat64ValueRecorder creates a new floating point ValueRecorder 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) NewFloat64ValueRecorder(name string, opts ...InstrumentOption) (Float64ValueRecorder, error) {
|
||||
return wrapFloat64ValueRecorderInstrument(
|
||||
m.newSync(name, ValueRecorderInstrumentKind, number.Float64Kind, opts))
|
||||
}
|
||||
|
||||
// NewInt64ValueObserver creates a new integer ValueObserver 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) NewInt64ValueObserver(name string, callback Int64ObserverFunc, opts ...InstrumentOption) (Int64ValueObserver, error) {
|
||||
if callback == nil {
|
||||
return wrapInt64ValueObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapInt64ValueObserverInstrument(
|
||||
m.newAsync(name, ValueObserverInstrumentKind, number.Int64Kind, opts,
|
||||
newInt64AsyncRunner(callback)))
|
||||
}
|
||||
|
||||
// NewFloat64ValueObserver creates a new floating point ValueObserver 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) NewFloat64ValueObserver(name string, callback Float64ObserverFunc, opts ...InstrumentOption) (Float64ValueObserver, error) {
|
||||
if callback == nil {
|
||||
return wrapFloat64ValueObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapFloat64ValueObserverInstrument(
|
||||
m.newAsync(name, ValueObserverInstrumentKind, number.Float64Kind, opts,
|
||||
newFloat64AsyncRunner(callback)))
|
||||
}
|
||||
|
||||
// NewInt64SumObserver creates a new integer SumObserver 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) NewInt64SumObserver(name string, callback Int64ObserverFunc, opts ...InstrumentOption) (Int64SumObserver, error) {
|
||||
if callback == nil {
|
||||
return wrapInt64SumObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapInt64SumObserverInstrument(
|
||||
m.newAsync(name, SumObserverInstrumentKind, number.Int64Kind, opts,
|
||||
newInt64AsyncRunner(callback)))
|
||||
}
|
||||
|
||||
// NewFloat64SumObserver creates a new floating point SumObserver 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) NewFloat64SumObserver(name string, callback Float64ObserverFunc, opts ...InstrumentOption) (Float64SumObserver, error) {
|
||||
if callback == nil {
|
||||
return wrapFloat64SumObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapFloat64SumObserverInstrument(
|
||||
m.newAsync(name, SumObserverInstrumentKind, number.Float64Kind, opts,
|
||||
newFloat64AsyncRunner(callback)))
|
||||
}
|
||||
|
||||
// NewInt64UpDownSumObserver creates a new integer UpDownSumObserver 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) NewInt64UpDownSumObserver(name string, callback Int64ObserverFunc, opts ...InstrumentOption) (Int64UpDownSumObserver, error) {
|
||||
if callback == nil {
|
||||
return wrapInt64UpDownSumObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapInt64UpDownSumObserverInstrument(
|
||||
m.newAsync(name, UpDownSumObserverInstrumentKind, number.Int64Kind, opts,
|
||||
newInt64AsyncRunner(callback)))
|
||||
}
|
||||
|
||||
// NewFloat64UpDownSumObserver creates a new floating point UpDownSumObserver 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) NewFloat64UpDownSumObserver(name string, callback Float64ObserverFunc, opts ...InstrumentOption) (Float64UpDownSumObserver, error) {
|
||||
if callback == nil {
|
||||
return wrapFloat64UpDownSumObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapFloat64UpDownSumObserverInstrument(
|
||||
m.newAsync(name, UpDownSumObserverInstrumentKind, number.Float64Kind, opts,
|
||||
newFloat64AsyncRunner(callback)))
|
||||
}
|
||||
|
||||
// NewInt64ValueObserver creates a new integer ValueObserver 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) NewInt64ValueObserver(name string, opts ...InstrumentOption) (Int64ValueObserver, error) {
|
||||
if b.runner == nil {
|
||||
return wrapInt64ValueObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapInt64ValueObserverInstrument(
|
||||
b.meter.newAsync(name, ValueObserverInstrumentKind, number.Int64Kind, opts, b.runner))
|
||||
}
|
||||
|
||||
// NewFloat64ValueObserver creates a new floating point ValueObserver 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) NewFloat64ValueObserver(name string, opts ...InstrumentOption) (Float64ValueObserver, error) {
|
||||
if b.runner == nil {
|
||||
return wrapFloat64ValueObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapFloat64ValueObserverInstrument(
|
||||
b.meter.newAsync(name, ValueObserverInstrumentKind, number.Float64Kind, opts,
|
||||
b.runner))
|
||||
}
|
||||
|
||||
// NewInt64SumObserver creates a new integer SumObserver 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) NewInt64SumObserver(name string, opts ...InstrumentOption) (Int64SumObserver, error) {
|
||||
if b.runner == nil {
|
||||
return wrapInt64SumObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapInt64SumObserverInstrument(
|
||||
b.meter.newAsync(name, SumObserverInstrumentKind, number.Int64Kind, opts, b.runner))
|
||||
}
|
||||
|
||||
// NewFloat64SumObserver creates a new floating point SumObserver 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) NewFloat64SumObserver(name string, opts ...InstrumentOption) (Float64SumObserver, error) {
|
||||
if b.runner == nil {
|
||||
return wrapFloat64SumObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapFloat64SumObserverInstrument(
|
||||
b.meter.newAsync(name, SumObserverInstrumentKind, number.Float64Kind, opts,
|
||||
b.runner))
|
||||
}
|
||||
|
||||
// NewInt64UpDownSumObserver creates a new integer UpDownSumObserver 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) NewInt64UpDownSumObserver(name string, opts ...InstrumentOption) (Int64UpDownSumObserver, error) {
|
||||
if b.runner == nil {
|
||||
return wrapInt64UpDownSumObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapInt64UpDownSumObserverInstrument(
|
||||
b.meter.newAsync(name, UpDownSumObserverInstrumentKind, number.Int64Kind, opts, b.runner))
|
||||
}
|
||||
|
||||
// NewFloat64UpDownSumObserver creates a new floating point UpDownSumObserver 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) NewFloat64UpDownSumObserver(name string, opts ...InstrumentOption) (Float64UpDownSumObserver, error) {
|
||||
if b.runner == nil {
|
||||
return wrapFloat64UpDownSumObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapFloat64UpDownSumObserverInstrument(
|
||||
b.meter.newAsync(name, UpDownSumObserverInstrumentKind, number.Float64Kind, opts,
|
||||
b.runner))
|
||||
}
|
||||
|
||||
// MeterImpl returns the underlying MeterImpl of this Meter.
|
||||
func (m Meter) MeterImpl() MeterImpl {
|
||||
return m.impl
|
||||
}
|
||||
|
||||
// newAsync constructs one new asynchronous instrument.
|
||||
func (m Meter) newAsync(
|
||||
name string,
|
||||
mkind InstrumentKind,
|
||||
nkind number.Kind,
|
||||
opts []InstrumentOption,
|
||||
runner AsyncRunner,
|
||||
) (
|
||||
AsyncImpl,
|
||||
error,
|
||||
) {
|
||||
if m.impl == nil {
|
||||
return NoopAsync{}, nil
|
||||
}
|
||||
desc := NewDescriptor(name, mkind, nkind, opts...)
|
||||
desc.config.InstrumentationName = m.name
|
||||
desc.config.InstrumentationVersion = m.version
|
||||
return m.impl.NewAsyncInstrument(desc, runner)
|
||||
}
|
||||
|
||||
// newSync constructs one new synchronous instrument.
|
||||
func (m Meter) newSync(
|
||||
name string,
|
||||
metricKind InstrumentKind,
|
||||
numberKind number.Kind,
|
||||
opts []InstrumentOption,
|
||||
) (
|
||||
SyncImpl,
|
||||
error,
|
||||
) {
|
||||
if m.impl == nil {
|
||||
return NoopSync{}, nil
|
||||
}
|
||||
desc := NewDescriptor(name, metricKind, numberKind, opts...)
|
||||
desc.config.InstrumentationName = m.name
|
||||
desc.config.InstrumentationVersion = m.version
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// NewInt64ValueRecorder calls `Meter.NewInt64ValueRecorder` and returns the
|
||||
// instrument, panicking if it encounters an error.
|
||||
func (mm MeterMust) NewInt64ValueRecorder(name string, mos ...InstrumentOption) Int64ValueRecorder {
|
||||
if inst, err := mm.meter.NewInt64ValueRecorder(name, mos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewFloat64ValueRecorder calls `Meter.NewFloat64ValueRecorder` and returns the
|
||||
// instrument, panicking if it encounters an error.
|
||||
func (mm MeterMust) NewFloat64ValueRecorder(name string, mos ...InstrumentOption) Float64ValueRecorder {
|
||||
if inst, err := mm.meter.NewFloat64ValueRecorder(name, mos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewInt64ValueObserver calls `Meter.NewInt64ValueObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (mm MeterMust) NewInt64ValueObserver(name string, callback Int64ObserverFunc, oos ...InstrumentOption) Int64ValueObserver {
|
||||
if inst, err := mm.meter.NewInt64ValueObserver(name, callback, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewFloat64ValueObserver calls `Meter.NewFloat64ValueObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (mm MeterMust) NewFloat64ValueObserver(name string, callback Float64ObserverFunc, oos ...InstrumentOption) Float64ValueObserver {
|
||||
if inst, err := mm.meter.NewFloat64ValueObserver(name, callback, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewInt64SumObserver calls `Meter.NewInt64SumObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (mm MeterMust) NewInt64SumObserver(name string, callback Int64ObserverFunc, oos ...InstrumentOption) Int64SumObserver {
|
||||
if inst, err := mm.meter.NewInt64SumObserver(name, callback, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewFloat64SumObserver calls `Meter.NewFloat64SumObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (mm MeterMust) NewFloat64SumObserver(name string, callback Float64ObserverFunc, oos ...InstrumentOption) Float64SumObserver {
|
||||
if inst, err := mm.meter.NewFloat64SumObserver(name, callback, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewInt64UpDownSumObserver calls `Meter.NewInt64UpDownSumObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (mm MeterMust) NewInt64UpDownSumObserver(name string, callback Int64ObserverFunc, oos ...InstrumentOption) Int64UpDownSumObserver {
|
||||
if inst, err := mm.meter.NewInt64UpDownSumObserver(name, callback, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewFloat64UpDownSumObserver calls `Meter.NewFloat64UpDownSumObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (mm MeterMust) NewFloat64UpDownSumObserver(name string, callback Float64ObserverFunc, oos ...InstrumentOption) Float64UpDownSumObserver {
|
||||
if inst, err := mm.meter.NewFloat64UpDownSumObserver(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),
|
||||
}
|
||||
}
|
||||
|
||||
// NewInt64ValueObserver calls `BatchObserver.NewInt64ValueObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (bm BatchObserverMust) NewInt64ValueObserver(name string, oos ...InstrumentOption) Int64ValueObserver {
|
||||
if inst, err := bm.batch.NewInt64ValueObserver(name, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewFloat64ValueObserver calls `BatchObserver.NewFloat64ValueObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (bm BatchObserverMust) NewFloat64ValueObserver(name string, oos ...InstrumentOption) Float64ValueObserver {
|
||||
if inst, err := bm.batch.NewFloat64ValueObserver(name, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewInt64SumObserver calls `BatchObserver.NewInt64SumObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (bm BatchObserverMust) NewInt64SumObserver(name string, oos ...InstrumentOption) Int64SumObserver {
|
||||
if inst, err := bm.batch.NewInt64SumObserver(name, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewFloat64SumObserver calls `BatchObserver.NewFloat64SumObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (bm BatchObserverMust) NewFloat64SumObserver(name string, oos ...InstrumentOption) Float64SumObserver {
|
||||
if inst, err := bm.batch.NewFloat64SumObserver(name, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewInt64UpDownSumObserver calls `BatchObserver.NewInt64UpDownSumObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (bm BatchObserverMust) NewInt64UpDownSumObserver(name string, oos ...InstrumentOption) Int64UpDownSumObserver {
|
||||
if inst, err := bm.batch.NewInt64UpDownSumObserver(name, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// NewFloat64UpDownSumObserver calls `BatchObserver.NewFloat64UpDownSumObserver` and
|
||||
// returns the instrument, panicking if it encounters an error.
|
||||
func (bm BatchObserverMust) NewFloat64UpDownSumObserver(name string, oos ...InstrumentOption) Float64UpDownSumObserver {
|
||||
if inst, err := bm.batch.NewFloat64UpDownSumObserver(name, oos...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
config InstrumentConfig
|
||||
}
|
||||
|
||||
// NewDescriptor returns a Descriptor with the given contents.
|
||||
func NewDescriptor(name string, ikind InstrumentKind, nkind number.Kind, opts ...InstrumentOption) Descriptor {
|
||||
return Descriptor{
|
||||
name: name,
|
||||
instrumentKind: ikind,
|
||||
numberKind: nkind,
|
||||
config: NewInstrumentConfig(opts...),
|
||||
}
|
||||
}
|
||||
|
||||
// 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.config.Description
|
||||
}
|
||||
|
||||
// Unit describes the units of the metric instrument. Unitless
|
||||
// metrics return the empty string.
|
||||
func (d Descriptor) Unit() unit.Unit {
|
||||
return d.config.Unit
|
||||
}
|
||||
|
||||
// NumberKind returns whether this instrument is declared over int64,
|
||||
// float64, or uint64 values.
|
||||
func (d Descriptor) NumberKind() number.Kind {
|
||||
return d.numberKind
|
||||
}
|
||||
|
||||
// InstrumentationName returns the name of the library that provided
|
||||
// instrumentation for this instrument.
|
||||
func (d Descriptor) InstrumentationName() string {
|
||||
return d.config.InstrumentationName
|
||||
}
|
||||
|
||||
// InstrumentationVersion returns the version of the library that provided
|
||||
// instrumentation for this instrument.
|
||||
func (d Descriptor) InstrumentationVersion() string {
|
||||
return d.config.InstrumentationVersion
|
||||
}
|
||||
777
vendor/go.opentelemetry.io/otel/metric/metric_instrument.go
generated
vendored
Normal file
777
vendor/go.opentelemetry.io/otel/metric/metric_instrument.go
generated
vendored
Normal file
@@ -0,0 +1,777 @@
|
||||
// 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 metric // import "go.opentelemetry.io/otel/metric"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric/number"
|
||||
)
|
||||
|
||||
// ErrSDKReturnedNilImpl is returned when a new `MeterImpl` returns nil.
|
||||
var ErrSDKReturnedNilImpl = errors.New("SDK returned a nil implementation")
|
||||
|
||||
// InstrumentKind describes the kind of instrument.
|
||||
type InstrumentKind int8
|
||||
|
||||
const (
|
||||
// ValueRecorderInstrumentKind indicates a ValueRecorder instrument.
|
||||
ValueRecorderInstrumentKind InstrumentKind = iota
|
||||
// ValueObserverInstrumentKind indicates an ValueObserver instrument.
|
||||
ValueObserverInstrumentKind
|
||||
|
||||
// CounterInstrumentKind indicates a Counter instrument.
|
||||
CounterInstrumentKind
|
||||
// UpDownCounterInstrumentKind indicates a UpDownCounter instrument.
|
||||
UpDownCounterInstrumentKind
|
||||
|
||||
// SumObserverInstrumentKind indicates a SumObserver instrument.
|
||||
SumObserverInstrumentKind
|
||||
// UpDownSumObserverInstrumentKind indicates a UpDownSumObserver
|
||||
// instrument.
|
||||
UpDownSumObserverInstrumentKind
|
||||
)
|
||||
|
||||
// Synchronous returns whether this is a synchronous kind of instrument.
|
||||
func (k InstrumentKind) Synchronous() bool {
|
||||
switch k {
|
||||
case CounterInstrumentKind, UpDownCounterInstrumentKind, ValueRecorderInstrumentKind:
|
||||
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, SumObserverInstrumentKind, UpDownSumObserverInstrumentKind:
|
||||
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, SumObserverInstrumentKind:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PrecomputedSum returns whether this kind of instrument receives precomputed sums.
|
||||
func (k InstrumentKind) PrecomputedSum() bool {
|
||||
return k.Adding() && k.Asynchronous()
|
||||
}
|
||||
|
||||
// Observation is used for reporting an asynchronous batch of metric
|
||||
// values. Instances of this type should be created by asynchronous
|
||||
// instruments (e.g., Int64ValueObserver.Observation()).
|
||||
type Observation struct {
|
||||
// number needs to be aligned for 64-bit atomic operations.
|
||||
number number.Number
|
||||
instrument AsyncImpl
|
||||
}
|
||||
|
||||
// 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 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 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, Observation{
|
||||
instrument: ir.instrument,
|
||||
number: 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, Observation{
|
||||
instrument: fr.instrument,
|
||||
number: 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...)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
var _ AsyncSingleRunner = (*Int64ObserverFunc)(nil)
|
||||
var _ AsyncSingleRunner = (*Float64ObserverFunc)(nil)
|
||||
var _ AsyncBatchRunner = (*BatchObserverFunc)(nil)
|
||||
|
||||
// newInt64AsyncRunner returns a single-observer callback for integer Observer instruments.
|
||||
func newInt64AsyncRunner(c Int64ObserverFunc) AsyncSingleRunner {
|
||||
return &c
|
||||
}
|
||||
|
||||
// newFloat64AsyncRunner returns a single-observer callback for floating point Observer instruments.
|
||||
func newFloat64AsyncRunner(c Float64ObserverFunc) AsyncSingleRunner {
|
||||
return &c
|
||||
}
|
||||
|
||||
// newBatchAsyncRunner returns a batch-observer callback use with multiple Observer instruments.
|
||||
func newBatchAsyncRunner(c BatchObserverFunc) 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 AsyncImpl, function func([]attribute.KeyValue, ...Observation)) {
|
||||
(*i)(ctx, Int64ObserverResult{
|
||||
instrument: impl,
|
||||
function: function,
|
||||
})
|
||||
}
|
||||
|
||||
// Run implements AsyncSingleRunner.
|
||||
func (f *Float64ObserverFunc) Run(ctx context.Context, impl 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,
|
||||
})
|
||||
}
|
||||
|
||||
// wrapInt64ValueObserverInstrument converts an AsyncImpl into Int64ValueObserver.
|
||||
func wrapInt64ValueObserverInstrument(asyncInst AsyncImpl, err error) (Int64ValueObserver, error) {
|
||||
common, err := checkNewAsync(asyncInst, err)
|
||||
return Int64ValueObserver{asyncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapFloat64ValueObserverInstrument converts an AsyncImpl into Float64ValueObserver.
|
||||
func wrapFloat64ValueObserverInstrument(asyncInst AsyncImpl, err error) (Float64ValueObserver, error) {
|
||||
common, err := checkNewAsync(asyncInst, err)
|
||||
return Float64ValueObserver{asyncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapInt64SumObserverInstrument converts an AsyncImpl into Int64SumObserver.
|
||||
func wrapInt64SumObserverInstrument(asyncInst AsyncImpl, err error) (Int64SumObserver, error) {
|
||||
common, err := checkNewAsync(asyncInst, err)
|
||||
return Int64SumObserver{asyncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapFloat64SumObserverInstrument converts an AsyncImpl into Float64SumObserver.
|
||||
func wrapFloat64SumObserverInstrument(asyncInst AsyncImpl, err error) (Float64SumObserver, error) {
|
||||
common, err := checkNewAsync(asyncInst, err)
|
||||
return Float64SumObserver{asyncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapInt64UpDownSumObserverInstrument converts an AsyncImpl into Int64UpDownSumObserver.
|
||||
func wrapInt64UpDownSumObserverInstrument(asyncInst AsyncImpl, err error) (Int64UpDownSumObserver, error) {
|
||||
common, err := checkNewAsync(asyncInst, err)
|
||||
return Int64UpDownSumObserver{asyncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapFloat64UpDownSumObserverInstrument converts an AsyncImpl into Float64UpDownSumObserver.
|
||||
func wrapFloat64UpDownSumObserverInstrument(asyncInst AsyncImpl, err error) (Float64UpDownSumObserver, error) {
|
||||
common, err := checkNewAsync(asyncInst, err)
|
||||
return Float64UpDownSumObserver{asyncInstrument: common}, err
|
||||
}
|
||||
|
||||
// BatchObserver represents an Observer callback that can report
|
||||
// observations for multiple instruments.
|
||||
type BatchObserver struct {
|
||||
meter Meter
|
||||
runner AsyncBatchRunner
|
||||
}
|
||||
|
||||
// Int64ValueObserver is a metric that captures a set of int64 values at a
|
||||
// point in time.
|
||||
type Int64ValueObserver struct {
|
||||
asyncInstrument
|
||||
}
|
||||
|
||||
// Float64ValueObserver is a metric that captures a set of float64 values
|
||||
// at a point in time.
|
||||
type Float64ValueObserver struct {
|
||||
asyncInstrument
|
||||
}
|
||||
|
||||
// Int64SumObserver is a metric that captures a precomputed sum of
|
||||
// int64 values at a point in time.
|
||||
type Int64SumObserver struct {
|
||||
asyncInstrument
|
||||
}
|
||||
|
||||
// Float64SumObserver is a metric that captures a precomputed sum of
|
||||
// float64 values at a point in time.
|
||||
type Float64SumObserver struct {
|
||||
asyncInstrument
|
||||
}
|
||||
|
||||
// Int64UpDownSumObserver is a metric that captures a precomputed sum of
|
||||
// int64 values at a point in time.
|
||||
type Int64UpDownSumObserver struct {
|
||||
asyncInstrument
|
||||
}
|
||||
|
||||
// Float64UpDownSumObserver is a metric that captures a precomputed sum of
|
||||
// float64 values at a point in time.
|
||||
type Float64UpDownSumObserver 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 Int64ValueObserver) Observation(v int64) Observation {
|
||||
return Observation{
|
||||
number: number.NewInt64Number(v),
|
||||
instrument: i.instrument,
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Float64ValueObserver) Observation(v float64) Observation {
|
||||
return Observation{
|
||||
number: number.NewFloat64Number(v),
|
||||
instrument: f.instrument,
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Int64SumObserver) Observation(v int64) Observation {
|
||||
return Observation{
|
||||
number: number.NewInt64Number(v),
|
||||
instrument: i.instrument,
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Float64SumObserver) Observation(v float64) Observation {
|
||||
return Observation{
|
||||
number: number.NewFloat64Number(v),
|
||||
instrument: f.instrument,
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Int64UpDownSumObserver) Observation(v int64) Observation {
|
||||
return Observation{
|
||||
number: number.NewInt64Number(v),
|
||||
instrument: i.instrument,
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Float64UpDownSumObserver) Observation(v float64) Observation {
|
||||
return Observation{
|
||||
number: number.NewFloat64Number(v),
|
||||
instrument: f.instrument,
|
||||
}
|
||||
}
|
||||
|
||||
// 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()).
|
||||
type Measurement struct {
|
||||
// number needs to be aligned for 64-bit atomic operations.
|
||||
number number.Number
|
||||
instrument SyncImpl
|
||||
}
|
||||
|
||||
// syncInstrument contains a SyncImpl.
|
||||
type syncInstrument struct {
|
||||
instrument SyncImpl
|
||||
}
|
||||
|
||||
// syncBoundInstrument contains a BoundSyncImpl.
|
||||
type syncBoundInstrument struct {
|
||||
boundInstrument BoundSyncImpl
|
||||
}
|
||||
|
||||
// asyncInstrument contains a AsyncImpl.
|
||||
type asyncInstrument struct {
|
||||
instrument AsyncImpl
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// AsyncImpl implements AsyncImpl.
|
||||
func (a asyncInstrument) AsyncImpl() AsyncImpl {
|
||||
return a.instrument
|
||||
}
|
||||
|
||||
// SyncImpl returns the implementation object for synchronous instruments.
|
||||
func (s syncInstrument) SyncImpl() 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 newMeasurement(s.instrument, number.NewFloat64Number(value))
|
||||
}
|
||||
|
||||
func (s syncInstrument) int64Measurement(value int64) Measurement {
|
||||
return 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 AsyncImpl, err error) (asyncInstrument, error) {
|
||||
if instrument == nil {
|
||||
if err == nil {
|
||||
err = ErrSDKReturnedNilImpl
|
||||
}
|
||||
instrument = NoopAsync{}
|
||||
}
|
||||
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 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 = NoopSync{}
|
||||
}
|
||||
return syncInstrument{
|
||||
instrument: instrument,
|
||||
}, err
|
||||
}
|
||||
|
||||
func newSyncBoundInstrument(boundInstrument BoundSyncImpl) syncBoundInstrument {
|
||||
return syncBoundInstrument{
|
||||
boundInstrument: boundInstrument,
|
||||
}
|
||||
}
|
||||
|
||||
func newMeasurement(instrument SyncImpl, number number.Number) Measurement {
|
||||
return Measurement{
|
||||
instrument: instrument,
|
||||
number: number,
|
||||
}
|
||||
}
|
||||
|
||||
// wrapInt64CounterInstrument converts a SyncImpl into Int64Counter.
|
||||
func wrapInt64CounterInstrument(syncInst SyncImpl, err error) (Int64Counter, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Int64Counter{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapFloat64CounterInstrument converts a SyncImpl into Float64Counter.
|
||||
func wrapFloat64CounterInstrument(syncInst SyncImpl, err error) (Float64Counter, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Float64Counter{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapInt64UpDownCounterInstrument converts a SyncImpl into Int64UpDownCounter.
|
||||
func wrapInt64UpDownCounterInstrument(syncInst SyncImpl, err error) (Int64UpDownCounter, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Int64UpDownCounter{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapFloat64UpDownCounterInstrument converts a SyncImpl into Float64UpDownCounter.
|
||||
func wrapFloat64UpDownCounterInstrument(syncInst SyncImpl, err error) (Float64UpDownCounter, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Float64UpDownCounter{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapInt64ValueRecorderInstrument converts a SyncImpl into Int64ValueRecorder.
|
||||
func wrapInt64ValueRecorderInstrument(syncInst SyncImpl, err error) (Int64ValueRecorder, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Int64ValueRecorder{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapFloat64ValueRecorderInstrument converts a SyncImpl into Float64ValueRecorder.
|
||||
func wrapFloat64ValueRecorderInstrument(syncInst SyncImpl, err error) (Float64ValueRecorder, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Float64ValueRecorder{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))
|
||||
}
|
||||
|
||||
// Float64ValueRecorder is a metric that records float64 values.
|
||||
type Float64ValueRecorder struct {
|
||||
syncInstrument
|
||||
}
|
||||
|
||||
// Int64ValueRecorder is a metric that records int64 values.
|
||||
type Int64ValueRecorder struct {
|
||||
syncInstrument
|
||||
}
|
||||
|
||||
// BoundFloat64ValueRecorder is a bound instrument for Float64ValueRecorder.
|
||||
//
|
||||
// It inherits the Unbind function from syncBoundInstrument.
|
||||
type BoundFloat64ValueRecorder struct {
|
||||
syncBoundInstrument
|
||||
}
|
||||
|
||||
// BoundInt64ValueRecorder is a bound instrument for Int64ValueRecorder.
|
||||
//
|
||||
// It inherits the Unbind function from syncBoundInstrument.
|
||||
type BoundInt64ValueRecorder struct {
|
||||
syncBoundInstrument
|
||||
}
|
||||
|
||||
// Bind creates a bound instrument for this ValueRecorder. The labels are
|
||||
// associated with values recorded via subsequent calls to Record.
|
||||
func (c Float64ValueRecorder) Bind(labels ...attribute.KeyValue) (h BoundFloat64ValueRecorder) {
|
||||
h.syncBoundInstrument = c.bind(labels)
|
||||
return
|
||||
}
|
||||
|
||||
// Bind creates a bound instrument for this ValueRecorder. The labels are
|
||||
// associated with values recorded via subsequent calls to Record.
|
||||
func (c Int64ValueRecorder) Bind(labels ...attribute.KeyValue) (h BoundInt64ValueRecorder) {
|
||||
h.syncBoundInstrument = c.bind(labels)
|
||||
return
|
||||
}
|
||||
|
||||
// Measurement creates a Measurement object to use with batch
|
||||
// recording.
|
||||
func (c Float64ValueRecorder) Measurement(value float64) Measurement {
|
||||
return c.float64Measurement(value)
|
||||
}
|
||||
|
||||
// Measurement creates a Measurement object to use with batch
|
||||
// recording.
|
||||
func (c Int64ValueRecorder) Measurement(value int64) Measurement {
|
||||
return c.int64Measurement(value)
|
||||
}
|
||||
|
||||
// Record adds a new value to the list of ValueRecorder's records. The
|
||||
// labels should contain the keys and values to be associated with
|
||||
// this value.
|
||||
func (c Float64ValueRecorder) Record(ctx context.Context, value float64, labels ...attribute.KeyValue) {
|
||||
c.directRecord(ctx, number.NewFloat64Number(value), labels)
|
||||
}
|
||||
|
||||
// Record adds a new value to the ValueRecorder's distribution. The
|
||||
// labels should contain the keys and values to be associated with
|
||||
// this value.
|
||||
func (c Int64ValueRecorder) Record(ctx context.Context, value int64, labels ...attribute.KeyValue) {
|
||||
c.directRecord(ctx, number.NewInt64Number(value), labels)
|
||||
}
|
||||
|
||||
// Record adds a new value to the ValueRecorder's distribution using the labels
|
||||
// previously bound to the ValueRecorder via Bind().
|
||||
func (b BoundFloat64ValueRecorder) Record(ctx context.Context, value float64) {
|
||||
b.directRecord(ctx, number.NewFloat64Number(value))
|
||||
}
|
||||
|
||||
// Record adds a new value to the ValueRecorder's distribution using the labels
|
||||
// previously bound to the ValueRecorder via Bind().
|
||||
func (b BoundInt64ValueRecorder) Record(ctx context.Context, value int64) {
|
||||
b.directRecord(ctx, number.NewInt64Number(value))
|
||||
}
|
||||
59
vendor/go.opentelemetry.io/otel/metric/metric_noop.go
generated
vendored
Normal file
59
vendor/go.opentelemetry.io/otel/metric/metric_noop.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/metric"
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric/number"
|
||||
)
|
||||
|
||||
type NoopMeterProvider struct{}
|
||||
|
||||
type noopInstrument struct{}
|
||||
type noopBoundInstrument struct{}
|
||||
type NoopSync struct{ noopInstrument }
|
||||
type NoopAsync struct{ noopInstrument }
|
||||
|
||||
var _ MeterProvider = NoopMeterProvider{}
|
||||
var _ SyncImpl = NoopSync{}
|
||||
var _ BoundSyncImpl = noopBoundInstrument{}
|
||||
var _ AsyncImpl = NoopAsync{}
|
||||
|
||||
func (NoopMeterProvider) Meter(_ string, _ ...MeterOption) Meter {
|
||||
return Meter{}
|
||||
}
|
||||
|
||||
func (noopInstrument) Implementation() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (noopInstrument) Descriptor() Descriptor {
|
||||
return Descriptor{}
|
||||
}
|
||||
|
||||
func (noopBoundInstrument) RecordOne(context.Context, number.Number) {
|
||||
}
|
||||
|
||||
func (noopBoundInstrument) Unbind() {
|
||||
}
|
||||
|
||||
func (NoopSync) Bind([]attribute.KeyValue) BoundSyncImpl {
|
||||
return noopBoundInstrument{}
|
||||
}
|
||||
|
||||
func (NoopSync) RecordOne(context.Context, number.Number, []attribute.KeyValue) {
|
||||
}
|
||||
95
vendor/go.opentelemetry.io/otel/metric/metric_sdkapi.go
generated
vendored
Normal file
95
vendor/go.opentelemetry.io/otel/metric/metric_sdkapi.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 metric // import "go.opentelemetry.io/otel/metric"
|
||||
|
||||
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., ValueRecorder 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
|
||||
}
|
||||
|
||||
// WrapMeterImpl constructs a `Meter` implementation from a
|
||||
// `MeterImpl` implementation.
|
||||
func WrapMeterImpl(impl MeterImpl, instrumentationName string, opts ...MeterOption) Meter {
|
||||
return Meter{
|
||||
impl: impl,
|
||||
name: instrumentationName,
|
||||
version: NewMeterConfig(opts...).InstrumentationVersion,
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
24
vendor/go.opentelemetry.io/otel/metric/registry/doc.go
generated
vendored
Normal file
24
vendor/go.opentelemetry.io/otel/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/metric/registry"
|
||||
170
vendor/go.opentelemetry.io/otel/metric/registry/registry.go
generated
vendored
Normal file
170
vendor/go.opentelemetry.io/otel/metric/registry/registry.go
generated
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
// 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/metric/registry"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
)
|
||||
|
||||
// MeterProvider is a standard MeterProvider for wrapping `MeterImpl`
|
||||
type MeterProvider struct {
|
||||
impl metric.MeterImpl
|
||||
}
|
||||
|
||||
var _ metric.MeterProvider = (*MeterProvider)(nil)
|
||||
|
||||
// uniqueInstrumentMeterImpl implements the metric.MeterImpl interface, adding
|
||||
// uniqueness checking for instrument descriptors. Use NewUniqueInstrumentMeter
|
||||
// to wrap an implementation with uniqueness checking.
|
||||
type uniqueInstrumentMeterImpl struct {
|
||||
lock sync.Mutex
|
||||
impl metric.MeterImpl
|
||||
state map[key]metric.InstrumentImpl
|
||||
}
|
||||
|
||||
var _ metric.MeterImpl = (*uniqueInstrumentMeterImpl)(nil)
|
||||
|
||||
type key struct {
|
||||
instrumentName string
|
||||
instrumentationName string
|
||||
InstrumentationVersion string
|
||||
}
|
||||
|
||||
// NewMeterProvider returns a new provider that implements instrument
|
||||
// name-uniqueness checking.
|
||||
func NewMeterProvider(impl metric.MeterImpl) *MeterProvider {
|
||||
return &MeterProvider{
|
||||
impl: NewUniqueInstrumentMeterImpl(impl),
|
||||
}
|
||||
}
|
||||
|
||||
// Meter implements MeterProvider.
|
||||
func (p *MeterProvider) Meter(instrumentationName string, opts ...metric.MeterOption) metric.Meter {
|
||||
return metric.WrapMeterImpl(p.impl, instrumentationName, opts...)
|
||||
}
|
||||
|
||||
// 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 uniqueness checking.
|
||||
func NewUniqueInstrumentMeterImpl(impl metric.MeterImpl) metric.MeterImpl {
|
||||
return &uniqueInstrumentMeterImpl{
|
||||
impl: impl,
|
||||
state: map[key]metric.InstrumentImpl{},
|
||||
}
|
||||
}
|
||||
|
||||
// RecordBatch implements metric.MeterImpl.
|
||||
func (u *uniqueInstrumentMeterImpl) RecordBatch(ctx context.Context, labels []attribute.KeyValue, ms ...metric.Measurement) {
|
||||
u.impl.RecordBatch(ctx, labels, ms...)
|
||||
}
|
||||
|
||||
func keyOf(descriptor metric.Descriptor) key {
|
||||
return key{
|
||||
descriptor.Name(),
|
||||
descriptor.InstrumentationName(),
|
||||
descriptor.InstrumentationVersion(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewMetricKindMismatchError formats an error that describes a
|
||||
// mismatched metric instrument definition.
|
||||
func NewMetricKindMismatchError(desc metric.Descriptor) error {
|
||||
return fmt.Errorf("metric was %s (%s %s)registered as a %s %s: %w",
|
||||
desc.Name(),
|
||||
desc.InstrumentationName(),
|
||||
desc.InstrumentationVersion(),
|
||||
desc.NumberKind(),
|
||||
desc.InstrumentKind(),
|
||||
ErrMetricKindMismatch)
|
||||
}
|
||||
|
||||
// Compatible determines whether two metric.Descriptors are considered
|
||||
// the same for the purpose of uniqueness checking.
|
||||
func Compatible(candidate, existing metric.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 metric.Descriptor) (metric.InstrumentImpl, error) {
|
||||
impl, ok := u.state[keyOf(descriptor)]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if !Compatible(descriptor, impl.Descriptor()) {
|
||||
return nil, NewMetricKindMismatchError(impl.Descriptor())
|
||||
}
|
||||
|
||||
return impl, nil
|
||||
}
|
||||
|
||||
// NewSyncInstrument implements metric.MeterImpl.
|
||||
func (u *uniqueInstrumentMeterImpl) NewSyncInstrument(descriptor metric.Descriptor) (metric.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.(metric.SyncImpl), nil
|
||||
}
|
||||
|
||||
syncInst, err := u.impl.NewSyncInstrument(descriptor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u.state[keyOf(descriptor)] = syncInst
|
||||
return syncInst, nil
|
||||
}
|
||||
|
||||
// NewAsyncInstrument implements metric.MeterImpl.
|
||||
func (u *uniqueInstrumentMeterImpl) NewAsyncInstrument(
|
||||
descriptor metric.Descriptor,
|
||||
runner metric.AsyncRunner,
|
||||
) (metric.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.(metric.AsyncImpl), nil
|
||||
}
|
||||
|
||||
asyncInst, err := u.impl.NewAsyncInstrument(descriptor, runner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u.state[keyOf(descriptor)] = asyncInst
|
||||
return asyncInst, nil
|
||||
}
|
||||
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)
|
||||
}
|
||||
111
vendor/go.opentelemetry.io/otel/propagation/baggage.go
generated
vendored
Normal file
111
vendor/go.opentelemetry.io/otel/propagation/baggage.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
// 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/url"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/internal/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) {
|
||||
baggageMap := baggage.MapFromContext(ctx)
|
||||
firstIter := true
|
||||
var headerValueBuilder strings.Builder
|
||||
baggageMap.Foreach(func(kv attribute.KeyValue) bool {
|
||||
if !firstIter {
|
||||
headerValueBuilder.WriteRune(',')
|
||||
}
|
||||
firstIter = false
|
||||
headerValueBuilder.WriteString(url.QueryEscape(strings.TrimSpace((string)(kv.Key))))
|
||||
headerValueBuilder.WriteRune('=')
|
||||
headerValueBuilder.WriteString(url.QueryEscape(strings.TrimSpace(kv.Value.Emit())))
|
||||
return true
|
||||
})
|
||||
if headerValueBuilder.Len() > 0 {
|
||||
headerString := headerValueBuilder.String()
|
||||
carrier.Set(baggageHeader, headerString)
|
||||
}
|
||||
}
|
||||
|
||||
// Extract returns a copy of parent with the baggage from the carrier added.
|
||||
func (b Baggage) Extract(parent context.Context, carrier TextMapCarrier) context.Context {
|
||||
bVal := carrier.Get(baggageHeader)
|
||||
if bVal == "" {
|
||||
return parent
|
||||
}
|
||||
|
||||
baggageValues := strings.Split(bVal, ",")
|
||||
keyValues := make([]attribute.KeyValue, 0, len(baggageValues))
|
||||
for _, baggageValue := range baggageValues {
|
||||
valueAndProps := strings.Split(baggageValue, ";")
|
||||
if len(valueAndProps) < 1 {
|
||||
continue
|
||||
}
|
||||
nameValue := strings.Split(valueAndProps[0], "=")
|
||||
if len(nameValue) < 2 {
|
||||
continue
|
||||
}
|
||||
name, err := url.QueryUnescape(nameValue[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
value, err := url.QueryUnescape(nameValue[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
trimmedValue := strings.TrimSpace(value)
|
||||
|
||||
// TODO (skaris): properties defiend https://w3c.github.io/correlation-context/, are currently
|
||||
// just put as part of the value.
|
||||
var trimmedValueWithProps strings.Builder
|
||||
trimmedValueWithProps.WriteString(trimmedValue)
|
||||
for _, prop := range valueAndProps[1:] {
|
||||
trimmedValueWithProps.WriteRune(';')
|
||||
trimmedValueWithProps.WriteString(prop)
|
||||
}
|
||||
|
||||
keyValues = append(keyValues, attribute.String(trimmedName, trimmedValueWithProps.String()))
|
||||
}
|
||||
|
||||
if len(keyValues) > 0 {
|
||||
// Only update the context if valid values were found
|
||||
return baggage.ContextWithMap(parent, baggage.NewMap(baggage.MapUpdate{
|
||||
MultiKV: keyValues,
|
||||
}))
|
||||
}
|
||||
|
||||
return parent
|
||||
}
|
||||
|
||||
// Fields returns the keys who's values are set with Inject.
|
||||
func (b Baggage) Fields() []string {
|
||||
return []string{baggageHeader}
|
||||
}
|
||||
28
vendor/go.opentelemetry.io/otel/propagation/doc.go
generated
vendored
Normal file
28
vendor/go.opentelemetry.io/otel/propagation/doc.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
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.
|
||||
|
||||
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"
|
||||
105
vendor/go.opentelemetry.io/otel/propagation/propagation.go
generated
vendored
Normal file
105
vendor/go.opentelemetry.io/otel/propagation/propagation.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
// 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 {
|
||||
// Get returns the value associated with the passed key.
|
||||
Get(key string) string
|
||||
// Set stores the key-value pair.
|
||||
Set(key string, value string)
|
||||
// Keys lists the keys stored in this carrier.
|
||||
Keys() []string
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// Inject set cross-cutting concerns from the Context into the carrier.
|
||||
Inject(ctx context.Context, carrier TextMapCarrier)
|
||||
// Extract reads cross-cutting concerns from the carrier into a Context.
|
||||
Extract(ctx context.Context, carrier TextMapCarrier) context.Context
|
||||
// Fields returns the keys who's values are set with Inject.
|
||||
Fields() []string
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
178
vendor/go.opentelemetry.io/otel/propagation/trace_context.go
generated
vendored
Normal file
178
vendor/go.opentelemetry.io/otel/propagation/trace_context.go
generated
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
// 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"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"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
|
||||
}
|
||||
|
||||
carrier.Set(tracestateHeader, sc.TraceState().String())
|
||||
|
||||
// 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
|
||||
|
||||
scc.TraceState = 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}
|
||||
}
|
||||
|
||||
func parseTraceState(in string) trace.TraceState {
|
||||
if in == "" {
|
||||
return trace.TraceState{}
|
||||
}
|
||||
|
||||
kvs := []attribute.KeyValue{}
|
||||
for _, entry := range strings.Split(in, ",") {
|
||||
parts := strings.SplitN(entry, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
// Parse failure, abort!
|
||||
return trace.TraceState{}
|
||||
}
|
||||
kvs = append(kvs, attribute.String(parts[0], parts[1]))
|
||||
}
|
||||
|
||||
// Ignoring error here as "failure to parse tracestate MUST NOT
|
||||
// affect the parsing of traceparent."
|
||||
// https://www.w3.org/TR/trace-context/#tracestate-header
|
||||
ts, _ := trace.TraceStateFromKeyValues(kvs...)
|
||||
return ts
|
||||
}
|
||||
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.
|
||||
35
vendor/go.opentelemetry.io/otel/sdk/instrumentation/library.go
generated
vendored
Normal file
35
vendor/go.opentelemetry.io/otel/sdk/instrumentation/library.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
}
|
||||
37
vendor/go.opentelemetry.io/otel/sdk/internal/internal.go
generated
vendored
Normal file
37
vendor/go.opentelemetry.io/otel/sdk/internal/internal.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// 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/sdk/internal"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
)
|
||||
|
||||
// UserAgent is the user agent to be added to the outgoing
|
||||
// requests from the exporters.
|
||||
var UserAgent = fmt.Sprintf("opentelemetry-go/%s", otel.Version())
|
||||
|
||||
// MonotonicEndTime returns the end time at present
|
||||
// but offset from start, monotonically.
|
||||
//
|
||||
// The monotonic clock is used in subtractions hence
|
||||
// the duration since start added back to start gives
|
||||
// end as a monotonic time.
|
||||
// See https://golang.org/pkg/time/#hdr-Monotonic_Clocks
|
||||
func MonotonicEndTime(start time.Time) time.Time {
|
||||
return start.Add(time.Since(start))
|
||||
}
|
||||
50
vendor/go.opentelemetry.io/otel/sdk/internal/sanitize.go
generated
vendored
Normal file
50
vendor/go.opentelemetry.io/otel/sdk/internal/sanitize.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// 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 (
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const labelKeySizeLimit = 100
|
||||
|
||||
// Sanitize returns a string that is trunacated to 100 characters if it's too
|
||||
// long, and replaces non-alphanumeric characters to underscores.
|
||||
func Sanitize(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
if len(s) > labelKeySizeLimit {
|
||||
s = s[:labelKeySizeLimit]
|
||||
}
|
||||
s = strings.Map(sanitizeRune, s)
|
||||
if unicode.IsDigit(rune(s[0])) {
|
||||
s = "key_" + s
|
||||
}
|
||||
if s[0] == '_' {
|
||||
s = "key" + s
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// converts anything that is not a letter or digit to an underscore
|
||||
func sanitizeRune(r rune) rune {
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) {
|
||||
return r
|
||||
}
|
||||
// Everything else turns into an underscore
|
||||
return '_'
|
||||
}
|
||||
64
vendor/go.opentelemetry.io/otel/sdk/resource/auto.go
generated
vendored
Normal file
64
vendor/go.opentelemetry.io/otel/sdk/resource/auto.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 resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrPartialResource is returned by a detector when complete source
|
||||
// information for a Resource is unavailable or the source information
|
||||
// contains invalid values that are omitted from the returned Resource.
|
||||
ErrPartialResource = errors.New("partial resource")
|
||||
)
|
||||
|
||||
// Detector detects OpenTelemetry resource information
|
||||
type Detector interface {
|
||||
// Detect returns an initialized Resource based on gathered information.
|
||||
// If the source information to construct a Resource contains invalid
|
||||
// values, a Resource is returned with the valid parts of the source
|
||||
// information used for initialization along with an appropriately
|
||||
// wrapped ErrPartialResource error.
|
||||
Detect(ctx context.Context) (*Resource, error)
|
||||
}
|
||||
|
||||
// Detect calls all input detectors sequentially and merges each result with the previous one.
|
||||
// It returns the merged error too.
|
||||
func Detect(ctx context.Context, detectors ...Detector) (*Resource, error) {
|
||||
var autoDetectedRes *Resource
|
||||
var errInfo []string
|
||||
for _, detector := range detectors {
|
||||
if detector == nil {
|
||||
continue
|
||||
}
|
||||
res, err := detector.Detect(ctx)
|
||||
if err != nil {
|
||||
errInfo = append(errInfo, err.Error())
|
||||
if !errors.Is(err, ErrPartialResource) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
autoDetectedRes = Merge(autoDetectedRes, res)
|
||||
}
|
||||
|
||||
var aggregatedError error
|
||||
if len(errInfo) > 0 {
|
||||
aggregatedError = fmt.Errorf("detecting resources: %s", errInfo)
|
||||
}
|
||||
return autoDetectedRes, aggregatedError
|
||||
}
|
||||
103
vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go
generated
vendored
Normal file
103
vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
// 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 resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/semconv"
|
||||
)
|
||||
|
||||
type (
|
||||
// TelemetrySDK is a Detector that provides information about
|
||||
// the OpenTelemetry SDK used. This Detector is included as a
|
||||
// builtin. If these resource attributes are not wanted, use
|
||||
// the WithTelemetrySDK(nil) or WithoutBuiltin() options to
|
||||
// explicitly disable them.
|
||||
TelemetrySDK struct{}
|
||||
|
||||
// Host is a Detector that provides information about the host
|
||||
// being run on. This Detector is included as a builtin. If
|
||||
// these resource attributes are not wanted, use the
|
||||
// WithHost(nil) or WithoutBuiltin() options to explicitly
|
||||
// disable them.
|
||||
Host struct{}
|
||||
|
||||
stringDetector struct {
|
||||
K attribute.Key
|
||||
F func() (string, error)
|
||||
}
|
||||
|
||||
defaultServiceNameDetector struct{}
|
||||
)
|
||||
|
||||
var (
|
||||
_ Detector = TelemetrySDK{}
|
||||
_ Detector = Host{}
|
||||
_ Detector = stringDetector{}
|
||||
_ Detector = defaultServiceNameDetector{}
|
||||
)
|
||||
|
||||
// Detect returns a *Resource that describes the OpenTelemetry SDK used.
|
||||
func (TelemetrySDK) Detect(context.Context) (*Resource, error) {
|
||||
return NewWithAttributes(
|
||||
semconv.TelemetrySDKNameKey.String("opentelemetry"),
|
||||
semconv.TelemetrySDKLanguageKey.String("go"),
|
||||
semconv.TelemetrySDKVersionKey.String(otel.Version()),
|
||||
), nil
|
||||
}
|
||||
|
||||
// Detect returns a *Resource that describes the host being run on.
|
||||
func (Host) Detect(ctx context.Context) (*Resource, error) {
|
||||
return StringDetector(semconv.HostNameKey, os.Hostname).Detect(ctx)
|
||||
}
|
||||
|
||||
// StringDetector returns a Detector that will produce a *Resource
|
||||
// containing the string as a value corresponding to k.
|
||||
func StringDetector(k attribute.Key, f func() (string, error)) Detector {
|
||||
return stringDetector{K: k, F: f}
|
||||
}
|
||||
|
||||
// Detect implements Detector.
|
||||
func (sd stringDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
value, err := sd.F()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", string(sd.K), err)
|
||||
}
|
||||
a := sd.K.String(value)
|
||||
if !a.Valid() {
|
||||
return nil, fmt.Errorf("invalid attribute: %q -> %q", a.Key, a.Value.Emit())
|
||||
}
|
||||
return NewWithAttributes(sd.K.String(value)), nil
|
||||
}
|
||||
|
||||
// Detect implements Detector
|
||||
func (defaultServiceNameDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
return StringDetector(
|
||||
semconv.ServiceNameKey,
|
||||
func() (string, error) {
|
||||
executable, err := os.Executable()
|
||||
if err != nil {
|
||||
return "unknown_service:go", nil
|
||||
}
|
||||
return "unknown_service:" + filepath.Base(executable), nil
|
||||
},
|
||||
).Detect(ctx)
|
||||
}
|
||||
165
vendor/go.opentelemetry.io/otel/sdk/resource/config.go
generated
vendored
Normal file
165
vendor/go.opentelemetry.io/otel/sdk/resource/config.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 resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
// config contains configuration for Resource creation.
|
||||
type config struct {
|
||||
// detectors that will be evaluated.
|
||||
detectors []Detector
|
||||
|
||||
// telemetrySDK is used to specify non-default
|
||||
// `telemetry.sdk.*` attributes.
|
||||
telemetrySDK Detector
|
||||
|
||||
// HostResource is used to specify non-default `host.*`
|
||||
// attributes.
|
||||
host Detector
|
||||
|
||||
// FromEnv is used to specify non-default OTEL_RESOURCE_ATTRIBUTES
|
||||
// attributes.
|
||||
fromEnv Detector
|
||||
}
|
||||
|
||||
// Option is the interface that applies a configuration option.
|
||||
type Option interface {
|
||||
// Apply sets the Option value of a config.
|
||||
Apply(*config)
|
||||
|
||||
// A private method to prevent users implementing the
|
||||
// interface and so future additions to it will not
|
||||
// violate compatibility.
|
||||
private()
|
||||
}
|
||||
|
||||
type option struct{}
|
||||
|
||||
func (option) private() {}
|
||||
|
||||
// WithAttributes adds attributes to the configured Resource.
|
||||
func WithAttributes(attributes ...attribute.KeyValue) Option {
|
||||
return WithDetectors(detectAttributes{attributes})
|
||||
}
|
||||
|
||||
type detectAttributes struct {
|
||||
attributes []attribute.KeyValue
|
||||
}
|
||||
|
||||
func (d detectAttributes) Detect(context.Context) (*Resource, error) {
|
||||
return NewWithAttributes(d.attributes...), nil
|
||||
}
|
||||
|
||||
// WithDetectors adds detectors to be evaluated for the configured resource.
|
||||
func WithDetectors(detectors ...Detector) Option {
|
||||
return detectorsOption{detectors: detectors}
|
||||
}
|
||||
|
||||
type detectorsOption struct {
|
||||
option
|
||||
detectors []Detector
|
||||
}
|
||||
|
||||
// Apply implements Option.
|
||||
func (o detectorsOption) Apply(cfg *config) {
|
||||
cfg.detectors = append(cfg.detectors, o.detectors...)
|
||||
}
|
||||
|
||||
// WithTelemetrySDK overrides the builtin `telemetry.sdk.*`
|
||||
// attributes. Use nil to disable these attributes entirely.
|
||||
func WithTelemetrySDK(d Detector) Option {
|
||||
return telemetrySDKOption{Detector: d}
|
||||
}
|
||||
|
||||
type telemetrySDKOption struct {
|
||||
option
|
||||
Detector
|
||||
}
|
||||
|
||||
// Apply implements Option.
|
||||
func (o telemetrySDKOption) Apply(cfg *config) {
|
||||
cfg.telemetrySDK = o.Detector
|
||||
}
|
||||
|
||||
// WithHost overrides the builtin `host.*` attributes. Use nil to
|
||||
// disable these attributes entirely.
|
||||
func WithHost(d Detector) Option {
|
||||
return hostOption{Detector: d}
|
||||
}
|
||||
|
||||
type hostOption struct {
|
||||
option
|
||||
Detector
|
||||
}
|
||||
|
||||
// Apply implements Option.
|
||||
func (o hostOption) Apply(cfg *config) {
|
||||
cfg.host = o.Detector
|
||||
}
|
||||
|
||||
// WithFromEnv overrides the builtin detector for
|
||||
// OTEL_RESOURCE_ATTRIBUTES. Use nil to disable environment checking.
|
||||
func WithFromEnv(d Detector) Option {
|
||||
return fromEnvOption{Detector: d}
|
||||
}
|
||||
|
||||
type fromEnvOption struct {
|
||||
option
|
||||
Detector
|
||||
}
|
||||
|
||||
// Apply implements Option.
|
||||
func (o fromEnvOption) Apply(cfg *config) {
|
||||
cfg.fromEnv = o.Detector
|
||||
}
|
||||
|
||||
// WithoutBuiltin disables all the builtin detectors, including the
|
||||
// telemetry.sdk.*, host.*, and the environment detector.
|
||||
func WithoutBuiltin() Option {
|
||||
return noBuiltinOption{}
|
||||
}
|
||||
|
||||
type noBuiltinOption struct {
|
||||
option
|
||||
}
|
||||
|
||||
// Apply implements Option.
|
||||
func (o noBuiltinOption) Apply(cfg *config) {
|
||||
cfg.host = nil
|
||||
cfg.telemetrySDK = nil
|
||||
cfg.fromEnv = nil
|
||||
}
|
||||
|
||||
// New returns a Resource combined from the provided attributes,
|
||||
// user-provided detectors and builtin detectors.
|
||||
func New(ctx context.Context, opts ...Option) (*Resource, error) {
|
||||
cfg := config{
|
||||
telemetrySDK: TelemetrySDK{},
|
||||
host: Host{},
|
||||
fromEnv: FromEnv{},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt.Apply(&cfg)
|
||||
}
|
||||
detectors := append(
|
||||
[]Detector{cfg.telemetrySDK, cfg.host, cfg.fromEnv},
|
||||
cfg.detectors...,
|
||||
)
|
||||
return Detect(ctx, detectors...)
|
||||
}
|
||||
32
vendor/go.opentelemetry.io/otel/sdk/resource/doc.go
generated
vendored
Normal file
32
vendor/go.opentelemetry.io/otel/sdk/resource/doc.go
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
// 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 resource provides detecting and representing resources.
|
||||
//
|
||||
// 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 fundamental struct is a Resource which holds identifying information
|
||||
// about the entities for which telemetry is exported.
|
||||
//
|
||||
// To automatically construct Resources from an environment a Detector
|
||||
// interface is defined. Implementations of this interface can be passed to
|
||||
// the Detect function to generate a Resource from the merged information.
|
||||
//
|
||||
// To load a user defined Resource from the environment variable
|
||||
// OTEL_RESOURCE_ATTRIBUTES the FromEnv Detector can be used. It will interpret
|
||||
// the value as a list of comma delimited key/value pairs
|
||||
// (e.g. `<key1>=<value1>,<key2>=<value2>,...`).
|
||||
package resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
72
vendor/go.opentelemetry.io/otel/sdk/resource/env.go
generated
vendored
Normal file
72
vendor/go.opentelemetry.io/otel/sdk/resource/env.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
// 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 resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
// envVar is the environment variable name OpenTelemetry Resource information can be assigned to.
|
||||
const envVar = "OTEL_RESOURCE_ATTRIBUTES"
|
||||
|
||||
var (
|
||||
// errMissingValue is returned when a resource value is missing.
|
||||
errMissingValue = fmt.Errorf("%w: missing value", ErrPartialResource)
|
||||
)
|
||||
|
||||
// FromEnv is a Detector that implements the Detector and collects
|
||||
// resources from environment. This Detector is included as a
|
||||
// builtin. If these resource attributes are not wanted, use the
|
||||
// WithFromEnv(nil) or WithoutBuiltin() options to explicitly disable
|
||||
// them.
|
||||
type FromEnv struct{}
|
||||
|
||||
// compile time assertion that FromEnv implements Detector interface
|
||||
var _ Detector = FromEnv{}
|
||||
|
||||
// Detect collects resources from environment
|
||||
func (FromEnv) Detect(context.Context) (*Resource, error) {
|
||||
attrs := strings.TrimSpace(os.Getenv(envVar))
|
||||
|
||||
if attrs == "" {
|
||||
return Empty(), nil
|
||||
}
|
||||
return constructOTResources(attrs)
|
||||
}
|
||||
|
||||
func constructOTResources(s string) (*Resource, error) {
|
||||
pairs := strings.Split(s, ",")
|
||||
attrs := []attribute.KeyValue{}
|
||||
var invalid []string
|
||||
for _, p := range pairs {
|
||||
field := strings.SplitN(p, "=", 2)
|
||||
if len(field) != 2 {
|
||||
invalid = append(invalid, p)
|
||||
continue
|
||||
}
|
||||
k, v := strings.TrimSpace(field[0]), strings.TrimSpace(field[1])
|
||||
attrs = append(attrs, attribute.String(k, v))
|
||||
}
|
||||
var err error
|
||||
if len(invalid) > 0 {
|
||||
err = fmt.Errorf("%w: %v", errMissingValue, invalid)
|
||||
}
|
||||
return NewWithAttributes(attrs...), err
|
||||
}
|
||||
39
vendor/go.opentelemetry.io/otel/sdk/resource/os.go
generated
vendored
Normal file
39
vendor/go.opentelemetry.io/otel/sdk/resource/os.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 resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel/semconv"
|
||||
)
|
||||
|
||||
type osTypeDetector struct{}
|
||||
|
||||
// Detect returns a *Resource that describes the operating system type the
|
||||
// service is running on.
|
||||
func (osTypeDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
osType := runtimeOS()
|
||||
|
||||
return NewWithAttributes(
|
||||
semconv.OSTypeKey.String(strings.ToLower(osType)),
|
||||
), nil
|
||||
}
|
||||
|
||||
// WithOSType adds an attribute with the operating system type to the configured Resource.
|
||||
func WithOSType() Option {
|
||||
return WithDetectors(osTypeDetector{})
|
||||
}
|
||||
237
vendor/go.opentelemetry.io/otel/sdk/resource/process.go
generated
vendored
Normal file
237
vendor/go.opentelemetry.io/otel/sdk/resource/process.go
generated
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
// 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 resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"go.opentelemetry.io/otel/semconv"
|
||||
)
|
||||
|
||||
type pidProvider func() int
|
||||
type executablePathProvider func() (string, error)
|
||||
type commandArgsProvider func() []string
|
||||
type ownerProvider func() (*user.User, error)
|
||||
type runtimeNameProvider func() string
|
||||
type runtimeVersionProvider func() string
|
||||
type runtimeOSProvider func() string
|
||||
type runtimeArchProvider func() string
|
||||
|
||||
var (
|
||||
defaultPidProvider pidProvider = os.Getpid
|
||||
defaultExecutablePathProvider executablePathProvider = os.Executable
|
||||
defaultCommandArgsProvider commandArgsProvider = func() []string { return os.Args }
|
||||
defaultOwnerProvider ownerProvider = user.Current
|
||||
defaultRuntimeNameProvider runtimeNameProvider = func() string { return runtime.Compiler }
|
||||
defaultRuntimeVersionProvider runtimeVersionProvider = runtime.Version
|
||||
defaultRuntimeOSProvider runtimeOSProvider = func() string { return runtime.GOOS }
|
||||
defaultRuntimeArchProvider runtimeArchProvider = func() string { return runtime.GOARCH }
|
||||
)
|
||||
|
||||
var (
|
||||
pid = defaultPidProvider
|
||||
executablePath = defaultExecutablePathProvider
|
||||
commandArgs = defaultCommandArgsProvider
|
||||
owner = defaultOwnerProvider
|
||||
runtimeName = defaultRuntimeNameProvider
|
||||
runtimeVersion = defaultRuntimeVersionProvider
|
||||
runtimeOS = defaultRuntimeOSProvider
|
||||
runtimeArch = defaultRuntimeArchProvider
|
||||
)
|
||||
|
||||
func setDefaultOSProviders() {
|
||||
setOSProviders(
|
||||
defaultPidProvider,
|
||||
defaultExecutablePathProvider,
|
||||
defaultCommandArgsProvider,
|
||||
)
|
||||
}
|
||||
|
||||
func setOSProviders(
|
||||
pidProvider pidProvider,
|
||||
executablePathProvider executablePathProvider,
|
||||
commandArgsProvider commandArgsProvider,
|
||||
) {
|
||||
pid = pidProvider
|
||||
executablePath = executablePathProvider
|
||||
commandArgs = commandArgsProvider
|
||||
}
|
||||
|
||||
func setDefaultRuntimeProviders() {
|
||||
setRuntimeProviders(
|
||||
defaultRuntimeNameProvider,
|
||||
defaultRuntimeVersionProvider,
|
||||
defaultRuntimeOSProvider,
|
||||
defaultRuntimeArchProvider,
|
||||
)
|
||||
}
|
||||
|
||||
func setRuntimeProviders(
|
||||
runtimeNameProvider runtimeNameProvider,
|
||||
runtimeVersionProvider runtimeVersionProvider,
|
||||
runtimeOSProvider runtimeOSProvider,
|
||||
runtimeArchProvider runtimeArchProvider,
|
||||
) {
|
||||
runtimeName = runtimeNameProvider
|
||||
runtimeVersion = runtimeVersionProvider
|
||||
runtimeOS = runtimeOSProvider
|
||||
runtimeArch = runtimeArchProvider
|
||||
}
|
||||
|
||||
func setDefaultUserProviders() {
|
||||
setUserProviders(defaultOwnerProvider)
|
||||
}
|
||||
|
||||
func setUserProviders(ownerProvider ownerProvider) {
|
||||
owner = ownerProvider
|
||||
}
|
||||
|
||||
type processPIDDetector struct{}
|
||||
type processExecutableNameDetector struct{}
|
||||
type processExecutablePathDetector struct{}
|
||||
type processCommandArgsDetector struct{}
|
||||
type processOwnerDetector struct{}
|
||||
type processRuntimeNameDetector struct{}
|
||||
type processRuntimeVersionDetector struct{}
|
||||
type processRuntimeDescriptionDetector struct{}
|
||||
|
||||
// Detect returns a *Resource that describes the process identifier (PID) of the
|
||||
// executing process.
|
||||
func (processPIDDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
return NewWithAttributes(semconv.ProcessPIDKey.Int(pid())), nil
|
||||
}
|
||||
|
||||
// Detect returns a *Resource that describes the name of the process executable.
|
||||
func (processExecutableNameDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
executableName := filepath.Base(commandArgs()[0])
|
||||
|
||||
return NewWithAttributes(semconv.ProcessExecutableNameKey.String(executableName)), nil
|
||||
}
|
||||
|
||||
// Detect returns a *Resource that describes the full path of the process executable.
|
||||
func (processExecutablePathDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
executablePath, err := executablePath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewWithAttributes(semconv.ProcessExecutablePathKey.String(executablePath)), nil
|
||||
}
|
||||
|
||||
// Detect returns a *Resource that describes all the command arguments as received
|
||||
// by the process.
|
||||
func (processCommandArgsDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
return NewWithAttributes(semconv.ProcessCommandArgsKey.Array(commandArgs())), nil
|
||||
}
|
||||
|
||||
// Detect returns a *Resource that describes the username of the user that owns the
|
||||
// process.
|
||||
func (processOwnerDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
owner, err := owner()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewWithAttributes(semconv.ProcessOwnerKey.String(owner.Username)), nil
|
||||
}
|
||||
|
||||
// Detect returns a *Resource that describes the name of the compiler used to compile
|
||||
// this process image.
|
||||
func (processRuntimeNameDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
return NewWithAttributes(semconv.ProcessRuntimeNameKey.String(runtimeName())), nil
|
||||
}
|
||||
|
||||
// Detect returns a *Resource that describes the version of the runtime of this process.
|
||||
func (processRuntimeVersionDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
return NewWithAttributes(semconv.ProcessRuntimeVersionKey.String(runtimeVersion())), nil
|
||||
}
|
||||
|
||||
// Detect returns a *Resource that describes the runtime of this process.
|
||||
func (processRuntimeDescriptionDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
runtimeDescription := fmt.Sprintf(
|
||||
"go version %s %s/%s", runtimeVersion(), runtimeOS(), runtimeArch())
|
||||
|
||||
return NewWithAttributes(
|
||||
semconv.ProcessRuntimeDescriptionKey.String(runtimeDescription),
|
||||
), nil
|
||||
}
|
||||
|
||||
// WithProcessPID adds an attribute with the process identifier (PID) to the
|
||||
// configured Resource.
|
||||
func WithProcessPID() Option {
|
||||
return WithDetectors(processPIDDetector{})
|
||||
}
|
||||
|
||||
// WithProcessExecutableName adds an attribute with the name of the process
|
||||
// executable to the configured Resource.
|
||||
func WithProcessExecutableName() Option {
|
||||
return WithDetectors(processExecutableNameDetector{})
|
||||
}
|
||||
|
||||
// WithProcessExecutablePath adds an attribute with the full path to the process
|
||||
// executable to the configured Resource.
|
||||
func WithProcessExecutablePath() Option {
|
||||
return WithDetectors(processExecutablePathDetector{})
|
||||
}
|
||||
|
||||
// WithProcessCommandArgs adds an attribute with all the command arguments (including
|
||||
// the command/executable itself) as received by the process the configured Resource.
|
||||
func WithProcessCommandArgs() Option {
|
||||
return WithDetectors(processCommandArgsDetector{})
|
||||
}
|
||||
|
||||
// WithProcessOwner adds an attribute with the username of the user that owns the process
|
||||
// to the configured Resource.
|
||||
func WithProcessOwner() Option {
|
||||
return WithDetectors(processOwnerDetector{})
|
||||
}
|
||||
|
||||
// WithProcessRuntimeName adds an attribute with the name of the runtime of this
|
||||
// process to the configured Resource.
|
||||
func WithProcessRuntimeName() Option {
|
||||
return WithDetectors(processRuntimeNameDetector{})
|
||||
}
|
||||
|
||||
// WithProcessRuntimeVersion adds an attribute with the version of the runtime of
|
||||
// this process to the configured Resource.
|
||||
func WithProcessRuntimeVersion() Option {
|
||||
return WithDetectors(processRuntimeVersionDetector{})
|
||||
}
|
||||
|
||||
// WithProcessRuntimeDescription adds an attribute with an additional description
|
||||
// about the runtime of the process to the configured Resource.
|
||||
func WithProcessRuntimeDescription() Option {
|
||||
return WithDetectors(processRuntimeDescriptionDetector{})
|
||||
}
|
||||
|
||||
// WithProcess adds all the Process attributes to the configured Resource.
|
||||
// See individual WithProcess* functions to configure specific attributes.
|
||||
func WithProcess() Option {
|
||||
return WithDetectors(
|
||||
processPIDDetector{},
|
||||
processExecutableNameDetector{},
|
||||
processExecutablePathDetector{},
|
||||
processCommandArgsDetector{},
|
||||
processOwnerDetector{},
|
||||
processRuntimeNameDetector{},
|
||||
processRuntimeVersionDetector{},
|
||||
processRuntimeDescriptionDetector{},
|
||||
)
|
||||
}
|
||||
196
vendor/go.opentelemetry.io/otel/sdk/resource/resource.go
generated
vendored
Normal file
196
vendor/go.opentelemetry.io/otel/sdk/resource/resource.go
generated
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
// 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 resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
// Resource describes an entity about which identifying information
|
||||
// and metadata is exposed. Resource is an immutable object,
|
||||
// equivalent to a map from key to unique value.
|
||||
//
|
||||
// Resources should be passed and stored as pointers
|
||||
// (`*resource.Resource`). The `nil` value is equivalent to an empty
|
||||
// Resource.
|
||||
type Resource struct {
|
||||
attrs attribute.Set
|
||||
}
|
||||
|
||||
var (
|
||||
emptyResource Resource
|
||||
|
||||
defaultResource *Resource = func(r *Resource, err error) *Resource {
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
return r
|
||||
}(Detect(context.Background(), defaultServiceNameDetector{}, FromEnv{}, TelemetrySDK{}))
|
||||
)
|
||||
|
||||
// NewWithAttributes creates a resource from attrs. If attrs contains
|
||||
// duplicate keys, the last value will be used. If attrs contains any invalid
|
||||
// items those items will be dropped.
|
||||
func NewWithAttributes(attrs ...attribute.KeyValue) *Resource {
|
||||
if len(attrs) == 0 {
|
||||
return &emptyResource
|
||||
}
|
||||
|
||||
// Ensure attributes comply with the specification:
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.0.1/specification/common/common.md#attributes
|
||||
s, _ := attribute.NewSetWithFiltered(attrs, func(kv attribute.KeyValue) bool {
|
||||
return kv.Valid()
|
||||
})
|
||||
|
||||
// If attrs only contains invalid entries do not allocate a new resource.
|
||||
if s.Len() == 0 {
|
||||
return &emptyResource
|
||||
}
|
||||
|
||||
return &Resource{s} //nolint
|
||||
}
|
||||
|
||||
// String implements the Stringer interface and provides a
|
||||
// human-readable form of the resource.
|
||||
//
|
||||
// Avoid using this representation as the key in a map of resources,
|
||||
// use Equivalent() as the key instead.
|
||||
func (r *Resource) String() string {
|
||||
if r == nil {
|
||||
return ""
|
||||
}
|
||||
return r.attrs.Encoded(attribute.DefaultEncoder())
|
||||
}
|
||||
|
||||
// Attributes returns a copy of attributes from the resource in a sorted order.
|
||||
// To avoid allocating a new slice, use an iterator.
|
||||
func (r *Resource) Attributes() []attribute.KeyValue {
|
||||
if r == nil {
|
||||
r = Empty()
|
||||
}
|
||||
return r.attrs.ToSlice()
|
||||
}
|
||||
|
||||
// Iter returns an interator of the Resource attributes.
|
||||
// This is ideal to use if you do not want a copy of the attributes.
|
||||
func (r *Resource) Iter() attribute.Iterator {
|
||||
if r == nil {
|
||||
r = Empty()
|
||||
}
|
||||
return r.attrs.Iter()
|
||||
}
|
||||
|
||||
// Equal returns true when a Resource is equivalent to this Resource.
|
||||
func (r *Resource) Equal(eq *Resource) bool {
|
||||
if r == nil {
|
||||
r = Empty()
|
||||
}
|
||||
if eq == nil {
|
||||
eq = Empty()
|
||||
}
|
||||
return r.Equivalent() == eq.Equivalent()
|
||||
}
|
||||
|
||||
// Merge creates a new resource by combining resource a and b.
|
||||
//
|
||||
// If there are common keys between resource a and b, then the value
|
||||
// from resource b will overwrite the value from resource a, even
|
||||
// if resource b's value is empty.
|
||||
func Merge(a, b *Resource) *Resource {
|
||||
if a == nil && b == nil {
|
||||
return Empty()
|
||||
}
|
||||
if a == nil {
|
||||
return b
|
||||
}
|
||||
if b == nil {
|
||||
return a
|
||||
}
|
||||
|
||||
// Note: 'b' attributes will overwrite 'a' with last-value-wins in attribute.Key()
|
||||
// Meaning this is equivalent to: append(a.Attributes(), b.Attributes()...)
|
||||
mi := attribute.NewMergeIterator(b.Set(), a.Set())
|
||||
combine := make([]attribute.KeyValue, 0, a.Len()+b.Len())
|
||||
for mi.Next() {
|
||||
combine = append(combine, mi.Label())
|
||||
}
|
||||
return NewWithAttributes(combine...)
|
||||
}
|
||||
|
||||
// Empty returns an instance of Resource with no attributes. It is
|
||||
// equivalent to a `nil` Resource.
|
||||
func Empty() *Resource {
|
||||
return &emptyResource
|
||||
}
|
||||
|
||||
// Default returns an instance of Resource with a default
|
||||
// "service.name" and OpenTelemetrySDK attributes
|
||||
func Default() *Resource {
|
||||
return defaultResource
|
||||
}
|
||||
|
||||
// Environment returns an instance of Resource with attributes
|
||||
// extracted from the OTEL_RESOURCE_ATTRIBUTES environment variable.
|
||||
func Environment() *Resource {
|
||||
detector := &FromEnv{}
|
||||
resource, err := detector.Detect(context.Background())
|
||||
if err == nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
return resource
|
||||
}
|
||||
|
||||
// Equivalent returns an object that can be compared for equality
|
||||
// between two resources. This value is suitable for use as a key in
|
||||
// a map.
|
||||
func (r *Resource) Equivalent() attribute.Distinct {
|
||||
return r.Set().Equivalent()
|
||||
}
|
||||
|
||||
// Set returns the equivalent *attribute.Set of this resources attributes.
|
||||
func (r *Resource) Set() *attribute.Set {
|
||||
if r == nil {
|
||||
r = Empty()
|
||||
}
|
||||
return &r.attrs
|
||||
}
|
||||
|
||||
// MarshalJSON encodes the resource attributes as a JSON list of { "Key":
|
||||
// "...", "Value": ... } pairs in order sorted by key.
|
||||
func (r *Resource) MarshalJSON() ([]byte, error) {
|
||||
if r == nil {
|
||||
r = Empty()
|
||||
}
|
||||
return r.attrs.MarshalJSON()
|
||||
}
|
||||
|
||||
// Len returns the number of unique key-values in this Resource.
|
||||
func (r *Resource) Len() int {
|
||||
if r == nil {
|
||||
return 0
|
||||
}
|
||||
return r.attrs.Len()
|
||||
}
|
||||
|
||||
// Encoded returns an encoded representation of the resource.
|
||||
func (r *Resource) Encoded(enc attribute.Encoder) string {
|
||||
if r == nil {
|
||||
return ""
|
||||
}
|
||||
return r.attrs.Encoded(enc)
|
||||
}
|
||||
91
vendor/go.opentelemetry.io/otel/sdk/trace/attributesmap.go
generated
vendored
Normal file
91
vendor/go.opentelemetry.io/otel/sdk/trace/attributesmap.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// 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 trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
// attributesMap is a capped map of attributes, holding the most recent attributes.
|
||||
// Eviction is done via a LRU method, the oldest entry is removed to create room for a new entry.
|
||||
// Updates are allowed and they refresh the usage of the key.
|
||||
//
|
||||
// This is based from https://github.com/hashicorp/golang-lru/blob/master/simplelru/lru.go
|
||||
// With a subset of the its operations and specific for holding attribute.KeyValue
|
||||
type attributesMap struct {
|
||||
attributes map[attribute.Key]*list.Element
|
||||
evictList *list.List
|
||||
droppedCount int
|
||||
capacity int
|
||||
}
|
||||
|
||||
func newAttributesMap(capacity int) *attributesMap {
|
||||
lm := &attributesMap{
|
||||
attributes: make(map[attribute.Key]*list.Element),
|
||||
evictList: list.New(),
|
||||
capacity: capacity,
|
||||
}
|
||||
return lm
|
||||
}
|
||||
|
||||
func (am *attributesMap) add(kv attribute.KeyValue) {
|
||||
// Check for existing item
|
||||
if ent, ok := am.attributes[kv.Key]; ok {
|
||||
am.evictList.MoveToFront(ent)
|
||||
ent.Value = &kv
|
||||
return
|
||||
}
|
||||
|
||||
// Add new item
|
||||
entry := am.evictList.PushFront(&kv)
|
||||
am.attributes[kv.Key] = entry
|
||||
|
||||
// Verify size not exceeded
|
||||
if am.evictList.Len() > am.capacity {
|
||||
am.removeOldest()
|
||||
am.droppedCount++
|
||||
}
|
||||
}
|
||||
|
||||
// toKeyValue copies the attributesMap into a slice of attribute.KeyValue and
|
||||
// returns it. If the map is empty, a nil is returned.
|
||||
// TODO: Is it more efficient to return a pointer to the slice?
|
||||
func (am *attributesMap) toKeyValue() []attribute.KeyValue {
|
||||
len := am.evictList.Len()
|
||||
if len == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
attributes := make([]attribute.KeyValue, 0, len)
|
||||
for ent := am.evictList.Back(); ent != nil; ent = ent.Prev() {
|
||||
if value, ok := ent.Value.(*attribute.KeyValue); ok {
|
||||
attributes = append(attributes, *value)
|
||||
}
|
||||
}
|
||||
|
||||
return attributes
|
||||
}
|
||||
|
||||
// removeOldest removes the oldest item from the cache.
|
||||
func (am *attributesMap) removeOldest() {
|
||||
ent := am.evictList.Back()
|
||||
if ent != nil {
|
||||
am.evictList.Remove(ent)
|
||||
kv := ent.Value.(*attribute.KeyValue)
|
||||
delete(am.attributes, kv.Key)
|
||||
}
|
||||
}
|
||||
328
vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go
generated
vendored
Normal file
328
vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go
generated
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
// 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 trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultMaxQueueSize = 2048
|
||||
DefaultBatchTimeout = 5000 * time.Millisecond
|
||||
DefaultExportTimeout = 30000 * time.Millisecond
|
||||
DefaultMaxExportBatchSize = 512
|
||||
)
|
||||
|
||||
type BatchSpanProcessorOption func(o *BatchSpanProcessorOptions)
|
||||
|
||||
type BatchSpanProcessorOptions struct {
|
||||
// MaxQueueSize is the maximum queue size to buffer spans for delayed processing. If the
|
||||
// queue gets full it drops the spans. Use BlockOnQueueFull to change this behavior.
|
||||
// The default value of MaxQueueSize is 2048.
|
||||
MaxQueueSize int
|
||||
|
||||
// BatchTimeout is the maximum duration for constructing a batch. Processor
|
||||
// forcefully sends available spans when timeout is reached.
|
||||
// The default value of BatchTimeout is 5000 msec.
|
||||
BatchTimeout time.Duration
|
||||
|
||||
// ExportTimeout specifies the maximum duration for exporting spans. If the timeout
|
||||
// is reached, the export will be cancelled.
|
||||
// The default value of ExportTimeout is 30000 msec.
|
||||
ExportTimeout time.Duration
|
||||
|
||||
// MaxExportBatchSize is the maximum number of spans to process in a single batch.
|
||||
// If there are more than one batch worth of spans then it processes multiple batches
|
||||
// of spans one batch after the other without any delay.
|
||||
// The default value of MaxExportBatchSize is 512.
|
||||
MaxExportBatchSize int
|
||||
|
||||
// BlockOnQueueFull blocks onEnd() and onStart() method if the queue is full
|
||||
// AND if BlockOnQueueFull is set to true.
|
||||
// Blocking option should be used carefully as it can severely affect the performance of an
|
||||
// application.
|
||||
BlockOnQueueFull bool
|
||||
}
|
||||
|
||||
// batchSpanProcessor is a SpanProcessor that batches asynchronously-received
|
||||
// SpanSnapshots and sends them to a trace.Exporter when complete.
|
||||
type batchSpanProcessor struct {
|
||||
e SpanExporter
|
||||
o BatchSpanProcessorOptions
|
||||
|
||||
queue chan *SpanSnapshot
|
||||
dropped uint32
|
||||
|
||||
batch []*SpanSnapshot
|
||||
batchMutex sync.Mutex
|
||||
timer *time.Timer
|
||||
stopWait sync.WaitGroup
|
||||
stopOnce sync.Once
|
||||
stopCh chan struct{}
|
||||
}
|
||||
|
||||
var _ SpanProcessor = (*batchSpanProcessor)(nil)
|
||||
|
||||
// NewBatchSpanProcessor creates a new SpanProcessor that will send completed
|
||||
// span batches to the exporter with the supplied options.
|
||||
//
|
||||
// If the exporter is nil, the span processor will preform no action.
|
||||
func NewBatchSpanProcessor(exporter SpanExporter, options ...BatchSpanProcessorOption) SpanProcessor {
|
||||
o := BatchSpanProcessorOptions{
|
||||
BatchTimeout: DefaultBatchTimeout,
|
||||
ExportTimeout: DefaultExportTimeout,
|
||||
MaxQueueSize: DefaultMaxQueueSize,
|
||||
MaxExportBatchSize: DefaultMaxExportBatchSize,
|
||||
}
|
||||
for _, opt := range options {
|
||||
opt(&o)
|
||||
}
|
||||
bsp := &batchSpanProcessor{
|
||||
e: exporter,
|
||||
o: o,
|
||||
batch: make([]*SpanSnapshot, 0, o.MaxExportBatchSize),
|
||||
timer: time.NewTimer(o.BatchTimeout),
|
||||
queue: make(chan *SpanSnapshot, o.MaxQueueSize),
|
||||
stopCh: make(chan struct{}),
|
||||
}
|
||||
|
||||
bsp.stopWait.Add(1)
|
||||
go func() {
|
||||
defer bsp.stopWait.Done()
|
||||
bsp.processQueue()
|
||||
bsp.drainQueue()
|
||||
}()
|
||||
|
||||
return bsp
|
||||
}
|
||||
|
||||
// OnStart method does nothing.
|
||||
func (bsp *batchSpanProcessor) OnStart(parent context.Context, s ReadWriteSpan) {}
|
||||
|
||||
// OnEnd method enqueues a ReadOnlySpan for later processing.
|
||||
func (bsp *batchSpanProcessor) OnEnd(s ReadOnlySpan) {
|
||||
// Do not enqueue spans if we are just going to drop them.
|
||||
if bsp.e == nil {
|
||||
return
|
||||
}
|
||||
bsp.enqueue(s.Snapshot())
|
||||
}
|
||||
|
||||
// Shutdown flushes the queue and waits until all spans are processed.
|
||||
// It only executes once. Subsequent call does nothing.
|
||||
func (bsp *batchSpanProcessor) Shutdown(ctx context.Context) error {
|
||||
var err error
|
||||
bsp.stopOnce.Do(func() {
|
||||
wait := make(chan struct{})
|
||||
go func() {
|
||||
close(bsp.stopCh)
|
||||
bsp.stopWait.Wait()
|
||||
if bsp.e != nil {
|
||||
if err := bsp.e.Shutdown(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
close(wait)
|
||||
}()
|
||||
// Wait until the wait group is done or the context is cancelled
|
||||
select {
|
||||
case <-wait:
|
||||
case <-ctx.Done():
|
||||
err = ctx.Err()
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// ForceFlush exports all ended spans that have not yet been exported.
|
||||
func (bsp *batchSpanProcessor) ForceFlush(ctx context.Context) error {
|
||||
var err error
|
||||
if bsp.e != nil {
|
||||
wait := make(chan struct{})
|
||||
go func() {
|
||||
if err := bsp.exportSpans(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
close(wait)
|
||||
}()
|
||||
// Wait until the export is finished or the context is cancelled/timed out
|
||||
select {
|
||||
case <-wait:
|
||||
case <-ctx.Done():
|
||||
err = ctx.Err()
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func WithMaxQueueSize(size int) BatchSpanProcessorOption {
|
||||
return func(o *BatchSpanProcessorOptions) {
|
||||
o.MaxQueueSize = size
|
||||
}
|
||||
}
|
||||
|
||||
func WithMaxExportBatchSize(size int) BatchSpanProcessorOption {
|
||||
return func(o *BatchSpanProcessorOptions) {
|
||||
o.MaxExportBatchSize = size
|
||||
}
|
||||
}
|
||||
|
||||
func WithBatchTimeout(delay time.Duration) BatchSpanProcessorOption {
|
||||
return func(o *BatchSpanProcessorOptions) {
|
||||
o.BatchTimeout = delay
|
||||
}
|
||||
}
|
||||
|
||||
func WithExportTimeout(timeout time.Duration) BatchSpanProcessorOption {
|
||||
return func(o *BatchSpanProcessorOptions) {
|
||||
o.ExportTimeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
func WithBlocking() BatchSpanProcessorOption {
|
||||
return func(o *BatchSpanProcessorOptions) {
|
||||
o.BlockOnQueueFull = true
|
||||
}
|
||||
}
|
||||
|
||||
// exportSpans is a subroutine of processing and draining the queue.
|
||||
func (bsp *batchSpanProcessor) exportSpans(ctx context.Context) error {
|
||||
bsp.timer.Reset(bsp.o.BatchTimeout)
|
||||
|
||||
bsp.batchMutex.Lock()
|
||||
defer bsp.batchMutex.Unlock()
|
||||
|
||||
if bsp.o.ExportTimeout > 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, bsp.o.ExportTimeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
if len(bsp.batch) > 0 {
|
||||
if err := bsp.e.ExportSpans(ctx, bsp.batch); err != nil {
|
||||
return err
|
||||
}
|
||||
bsp.batch = bsp.batch[:0]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// processQueue removes spans from the `queue` channel until processor
|
||||
// is shut down. It calls the exporter in batches of up to MaxExportBatchSize
|
||||
// waiting up to BatchTimeout to form a batch.
|
||||
func (bsp *batchSpanProcessor) processQueue() {
|
||||
defer bsp.timer.Stop()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-bsp.stopCh:
|
||||
return
|
||||
case <-bsp.timer.C:
|
||||
if err := bsp.exportSpans(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
case sd := <-bsp.queue:
|
||||
bsp.batchMutex.Lock()
|
||||
bsp.batch = append(bsp.batch, sd)
|
||||
shouldExport := len(bsp.batch) == bsp.o.MaxExportBatchSize
|
||||
bsp.batchMutex.Unlock()
|
||||
if shouldExport {
|
||||
if !bsp.timer.Stop() {
|
||||
<-bsp.timer.C
|
||||
}
|
||||
if err := bsp.exportSpans(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drainQueue awaits the any caller that had added to bsp.stopWait
|
||||
// to finish the enqueue, then exports the final batch.
|
||||
func (bsp *batchSpanProcessor) drainQueue() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case sd := <-bsp.queue:
|
||||
if sd == nil {
|
||||
if err := bsp.exportSpans(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
bsp.batchMutex.Lock()
|
||||
bsp.batch = append(bsp.batch, sd)
|
||||
shouldExport := len(bsp.batch) == bsp.o.MaxExportBatchSize
|
||||
bsp.batchMutex.Unlock()
|
||||
|
||||
if shouldExport {
|
||||
if err := bsp.exportSpans(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
close(bsp.queue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (bsp *batchSpanProcessor) enqueue(sd *SpanSnapshot) {
|
||||
if !sd.SpanContext.IsSampled() {
|
||||
return
|
||||
}
|
||||
|
||||
// This ensures the bsp.queue<- below does not panic as the
|
||||
// processor shuts down.
|
||||
defer func() {
|
||||
x := recover()
|
||||
switch err := x.(type) {
|
||||
case nil:
|
||||
return
|
||||
case runtime.Error:
|
||||
if err.Error() == "send on closed channel" {
|
||||
return
|
||||
}
|
||||
}
|
||||
panic(x)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-bsp.stopCh:
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
if bsp.o.BlockOnQueueFull {
|
||||
bsp.queue <- sd
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case bsp.queue <- sd:
|
||||
default:
|
||||
atomic.AddUint32(&bsp.dropped, 1)
|
||||
}
|
||||
}
|
||||
68
vendor/go.opentelemetry.io/otel/sdk/trace/config.go
generated
vendored
Normal file
68
vendor/go.opentelemetry.io/otel/sdk/trace/config.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// 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 trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
// SpanLimits represents the limits of a span.
|
||||
type SpanLimits struct {
|
||||
// AttributeCountLimit is the maximum allowed span attribute count.
|
||||
AttributeCountLimit int
|
||||
|
||||
// EventCountLimit is the maximum allowed span event count.
|
||||
EventCountLimit int
|
||||
|
||||
// LinkCountLimit is the maximum allowed span link count.
|
||||
LinkCountLimit int
|
||||
|
||||
// AttributePerEventCountLimit is the maximum allowed attribute per span event count.
|
||||
AttributePerEventCountLimit int
|
||||
|
||||
// AttributePerLinkCountLimit is the maximum allowed attribute per span link count.
|
||||
AttributePerLinkCountLimit int
|
||||
}
|
||||
|
||||
func (sl *SpanLimits) ensureDefault() {
|
||||
if sl.EventCountLimit <= 0 {
|
||||
sl.EventCountLimit = DefaultEventCountLimit
|
||||
}
|
||||
if sl.AttributeCountLimit <= 0 {
|
||||
sl.AttributeCountLimit = DefaultAttributeCountLimit
|
||||
}
|
||||
if sl.LinkCountLimit <= 0 {
|
||||
sl.LinkCountLimit = DefaultLinkCountLimit
|
||||
}
|
||||
if sl.AttributePerEventCountLimit <= 0 {
|
||||
sl.AttributePerEventCountLimit = DefaultAttributePerEventCountLimit
|
||||
}
|
||||
if sl.AttributePerLinkCountLimit <= 0 {
|
||||
sl.AttributePerLinkCountLimit = DefaultAttributePerLinkCountLimit
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// DefaultAttributeCountLimit is the default maximum allowed span attribute count.
|
||||
DefaultAttributeCountLimit = 128
|
||||
|
||||
// DefaultEventCountLimit is the default maximum allowed span event count.
|
||||
DefaultEventCountLimit = 128
|
||||
|
||||
// DefaultLinkCountLimit is the default maximum allowed span link count.
|
||||
DefaultLinkCountLimit = 128
|
||||
|
||||
// DefaultAttributePerEventCountLimit is the default maximum allowed attribute per span event count.
|
||||
DefaultAttributePerEventCountLimit = 128
|
||||
|
||||
// DefaultAttributePerLinkCountLimit is the default maximum allowed attribute per span link count.
|
||||
DefaultAttributePerLinkCountLimit = 128
|
||||
)
|
||||
25
vendor/go.opentelemetry.io/otel/sdk/trace/doc.go
generated
vendored
Normal file
25
vendor/go.opentelemetry.io/otel/sdk/trace/doc.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// 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 trace contains support for OpenTelemetry distributed tracing.
|
||||
|
||||
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 following assumes a basic familiarity with OpenTelemetry concepts.
|
||||
See https://opentelemetry.io.
|
||||
*/
|
||||
package trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
38
vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go
generated
vendored
Normal file
38
vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.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 trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
type evictedQueue struct {
|
||||
queue []interface{}
|
||||
capacity int
|
||||
droppedCount int
|
||||
}
|
||||
|
||||
func newEvictedQueue(capacity int) *evictedQueue {
|
||||
eq := &evictedQueue{
|
||||
capacity: capacity,
|
||||
queue: make([]interface{}, 0),
|
||||
}
|
||||
|
||||
return eq
|
||||
}
|
||||
|
||||
func (eq *evictedQueue) add(value interface{}) {
|
||||
if len(eq.queue) == eq.capacity {
|
||||
eq.queue = eq.queue[1:]
|
||||
eq.droppedCount++
|
||||
}
|
||||
eq.queue = append(eq.queue, value)
|
||||
}
|
||||
67
vendor/go.opentelemetry.io/otel/sdk/trace/id_generator.go
generated
vendored
Normal file
67
vendor/go.opentelemetry.io/otel/sdk/trace/id_generator.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 trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
crand "crypto/rand"
|
||||
"encoding/binary"
|
||||
"math/rand"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// IDGenerator allows custom generators for TraceID and SpanID.
|
||||
type IDGenerator interface {
|
||||
NewIDs(ctx context.Context) (trace.TraceID, trace.SpanID)
|
||||
NewSpanID(ctx context.Context, traceID trace.TraceID) trace.SpanID
|
||||
}
|
||||
|
||||
type randomIDGenerator struct {
|
||||
sync.Mutex
|
||||
randSource *rand.Rand
|
||||
}
|
||||
|
||||
var _ IDGenerator = &randomIDGenerator{}
|
||||
|
||||
// NewSpanID returns a non-zero span ID from a randomly-chosen sequence.
|
||||
func (gen *randomIDGenerator) NewSpanID(ctx context.Context, traceID trace.TraceID) trace.SpanID {
|
||||
gen.Lock()
|
||||
defer gen.Unlock()
|
||||
sid := trace.SpanID{}
|
||||
gen.randSource.Read(sid[:])
|
||||
return sid
|
||||
}
|
||||
|
||||
// NewIDs returns a non-zero trace ID and a non-zero span ID from a
|
||||
// randomly-chosen sequence.
|
||||
func (gen *randomIDGenerator) NewIDs(ctx context.Context) (trace.TraceID, trace.SpanID) {
|
||||
gen.Lock()
|
||||
defer gen.Unlock()
|
||||
tid := trace.TraceID{}
|
||||
gen.randSource.Read(tid[:])
|
||||
sid := trace.SpanID{}
|
||||
gen.randSource.Read(sid[:])
|
||||
return tid, sid
|
||||
}
|
||||
|
||||
func defaultIDGenerator() IDGenerator {
|
||||
gen := &randomIDGenerator{}
|
||||
var rngSeed int64
|
||||
_ = binary.Read(crand.Reader, binary.LittleEndian, &rngSeed)
|
||||
gen.randSource = rand.New(rand.NewSource(rngSeed))
|
||||
return gen
|
||||
}
|
||||
324
vendor/go.opentelemetry.io/otel/sdk/trace/provider.go
generated
vendored
Normal file
324
vendor/go.opentelemetry.io/otel/sdk/trace/provider.go
generated
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
// 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 trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTracerName = "go.opentelemetry.io/otel/sdk/tracer"
|
||||
)
|
||||
|
||||
// TODO (MrAlias): unify this API option design:
|
||||
// https://github.com/open-telemetry/opentelemetry-go/issues/536
|
||||
|
||||
// TracerProviderConfig
|
||||
type TracerProviderConfig struct {
|
||||
processors []SpanProcessor
|
||||
|
||||
// sampler is the default sampler used when creating new spans.
|
||||
sampler Sampler
|
||||
|
||||
// idGenerator is used to generate all Span and Trace IDs when needed.
|
||||
idGenerator IDGenerator
|
||||
|
||||
// spanLimits defines the attribute, event, and link limits for spans.
|
||||
spanLimits SpanLimits
|
||||
|
||||
// resource contains attributes representing an entity that produces telemetry.
|
||||
resource *resource.Resource
|
||||
}
|
||||
|
||||
type TracerProviderOption func(*TracerProviderConfig)
|
||||
|
||||
type TracerProvider struct {
|
||||
mu sync.Mutex
|
||||
namedTracer map[instrumentation.Library]*tracer
|
||||
spanProcessors atomic.Value
|
||||
sampler Sampler
|
||||
idGenerator IDGenerator
|
||||
spanLimits SpanLimits
|
||||
resource *resource.Resource
|
||||
}
|
||||
|
||||
var _ trace.TracerProvider = &TracerProvider{}
|
||||
|
||||
// NewTracerProvider returns a new and configured TracerProvider.
|
||||
//
|
||||
// By default the returned TracerProvider is configured with:
|
||||
// - a ParentBased(AlwaysSample) Sampler
|
||||
// - a random number IDGenerator
|
||||
// - the resource.Default() Resource
|
||||
// - the default SpanLimits.
|
||||
//
|
||||
// The passed opts are used to override these default values and configure the
|
||||
// returned TracerProvider appropriately.
|
||||
func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
|
||||
o := &TracerProviderConfig{}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
|
||||
ensureValidTracerProviderConfig(o)
|
||||
|
||||
tp := &TracerProvider{
|
||||
namedTracer: make(map[instrumentation.Library]*tracer),
|
||||
sampler: o.sampler,
|
||||
idGenerator: o.idGenerator,
|
||||
spanLimits: o.spanLimits,
|
||||
resource: o.resource,
|
||||
}
|
||||
|
||||
for _, sp := range o.processors {
|
||||
tp.RegisterSpanProcessor(sp)
|
||||
}
|
||||
|
||||
return tp
|
||||
}
|
||||
|
||||
// Tracer returns a Tracer with the given name and options. If a Tracer for
|
||||
// the given name and options does not exist it is created, otherwise the
|
||||
// existing Tracer is returned.
|
||||
//
|
||||
// If name is empty, DefaultTracerName is used instead.
|
||||
//
|
||||
// This method is safe to be called concurrently.
|
||||
func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
|
||||
c := trace.NewTracerConfig(opts...)
|
||||
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
if name == "" {
|
||||
name = defaultTracerName
|
||||
}
|
||||
il := instrumentation.Library{
|
||||
Name: name,
|
||||
Version: c.InstrumentationVersion,
|
||||
}
|
||||
t, ok := p.namedTracer[il]
|
||||
if !ok {
|
||||
t = &tracer{
|
||||
provider: p,
|
||||
instrumentationLibrary: il,
|
||||
}
|
||||
p.namedTracer[il] = t
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// RegisterSpanProcessor adds the given SpanProcessor to the list of SpanProcessors
|
||||
func (p *TracerProvider) RegisterSpanProcessor(s SpanProcessor) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
new := spanProcessorStates{}
|
||||
if old, ok := p.spanProcessors.Load().(spanProcessorStates); ok {
|
||||
new = append(new, old...)
|
||||
}
|
||||
newSpanSync := &spanProcessorState{
|
||||
sp: s,
|
||||
state: &sync.Once{},
|
||||
}
|
||||
new = append(new, newSpanSync)
|
||||
p.spanProcessors.Store(new)
|
||||
}
|
||||
|
||||
// UnregisterSpanProcessor removes the given SpanProcessor from the list of SpanProcessors
|
||||
func (p *TracerProvider) UnregisterSpanProcessor(s SpanProcessor) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
spss := spanProcessorStates{}
|
||||
old, ok := p.spanProcessors.Load().(spanProcessorStates)
|
||||
if !ok || len(old) == 0 {
|
||||
return
|
||||
}
|
||||
spss = append(spss, old...)
|
||||
|
||||
// stop the span processor if it is started and remove it from the list
|
||||
var stopOnce *spanProcessorState
|
||||
var idx int
|
||||
for i, sps := range spss {
|
||||
if sps.sp == s {
|
||||
stopOnce = sps
|
||||
idx = i
|
||||
}
|
||||
}
|
||||
if stopOnce != nil {
|
||||
stopOnce.state.Do(func() {
|
||||
if err := s.Shutdown(context.Background()); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
if len(spss) > 1 {
|
||||
copy(spss[idx:], spss[idx+1:])
|
||||
}
|
||||
spss[len(spss)-1] = nil
|
||||
spss = spss[:len(spss)-1]
|
||||
|
||||
p.spanProcessors.Store(spss)
|
||||
}
|
||||
|
||||
// ForceFlush immediately exports all spans that have not yet been exported for
|
||||
// all the registered span processors.
|
||||
func (p *TracerProvider) ForceFlush(ctx context.Context) error {
|
||||
spss, ok := p.spanProcessors.Load().(spanProcessorStates)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to load span processors")
|
||||
}
|
||||
if len(spss) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, sps := range spss {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
if err := sps.sp.ForceFlush(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown shuts down the span processors in the order they were registered.
|
||||
func (p *TracerProvider) Shutdown(ctx context.Context) error {
|
||||
spss, ok := p.spanProcessors.Load().(spanProcessorStates)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to load span processors")
|
||||
}
|
||||
if len(spss) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, sps := range spss {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
var err error
|
||||
sps.state.Do(func() {
|
||||
err = sps.sp.Shutdown(ctx)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithSyncer registers the exporter with the TracerProvider using a
|
||||
// SimpleSpanProcessor.
|
||||
func WithSyncer(e SpanExporter) TracerProviderOption {
|
||||
return WithSpanProcessor(NewSimpleSpanProcessor(e))
|
||||
}
|
||||
|
||||
// WithBatcher registers the exporter with the TracerProvider using a
|
||||
// BatchSpanProcessor configured with the passed opts.
|
||||
func WithBatcher(e SpanExporter, opts ...BatchSpanProcessorOption) TracerProviderOption {
|
||||
return WithSpanProcessor(NewBatchSpanProcessor(e, opts...))
|
||||
}
|
||||
|
||||
// WithSpanProcessor registers the SpanProcessor with a TracerProvider.
|
||||
func WithSpanProcessor(sp SpanProcessor) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
opts.processors = append(opts.processors, sp)
|
||||
}
|
||||
}
|
||||
|
||||
// WithResource returns a TracerProviderOption that will configure the
|
||||
// Resource r as a TracerProvider's Resource. The configured Resource is
|
||||
// referenced by all the Tracers the TracerProvider creates. It represents the
|
||||
// entity producing telemetry.
|
||||
//
|
||||
// If this option is not used, the TracerProvider will use the
|
||||
// resource.Default() Resource by default.
|
||||
func WithResource(r *resource.Resource) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
opts.resource = resource.Merge(resource.Environment(), r)
|
||||
}
|
||||
}
|
||||
|
||||
// WithIDGenerator returns a TracerProviderOption that will configure the
|
||||
// IDGenerator g as a TracerProvider's IDGenerator. The configured IDGenerator
|
||||
// is used by the Tracers the TracerProvider creates to generate new Span and
|
||||
// Trace IDs.
|
||||
//
|
||||
// If this option is not used, the TracerProvider will use a random number
|
||||
// IDGenerator by default.
|
||||
func WithIDGenerator(g IDGenerator) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
if g != nil {
|
||||
opts.idGenerator = g
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithSampler returns a TracerProviderOption that will configure the Sampler
|
||||
// s as a TracerProvider's Sampler. The configured Sampler is used by the
|
||||
// Tracers the TracerProvider creates to make their sampling decisions for the
|
||||
// Spans they create.
|
||||
//
|
||||
// If this option is not used, the TracerProvider will use a
|
||||
// ParentBased(AlwaysSample) Sampler by default.
|
||||
func WithSampler(s Sampler) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
if s != nil {
|
||||
opts.sampler = s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithSpanLimits returns a TracerProviderOption that will configure the
|
||||
// SpanLimits sl as a TracerProvider's SpanLimits. The configured SpanLimits
|
||||
// are used used by the Tracers the TracerProvider and the Spans they create
|
||||
// to limit tracing resources used.
|
||||
//
|
||||
// If this option is not used, the TracerProvider will use the default
|
||||
// SpanLimits.
|
||||
func WithSpanLimits(sl SpanLimits) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
opts.spanLimits = sl
|
||||
}
|
||||
}
|
||||
|
||||
// ensureValidTracerProviderConfig ensures that given TracerProviderConfig is valid.
|
||||
func ensureValidTracerProviderConfig(cfg *TracerProviderConfig) {
|
||||
if cfg.sampler == nil {
|
||||
cfg.sampler = ParentBased(AlwaysSample())
|
||||
}
|
||||
if cfg.idGenerator == nil {
|
||||
cfg.idGenerator = defaultIDGenerator()
|
||||
}
|
||||
cfg.spanLimits.ensureDefault()
|
||||
if cfg.resource == nil {
|
||||
cfg.resource = resource.Default()
|
||||
}
|
||||
}
|
||||
290
vendor/go.opentelemetry.io/otel/sdk/trace/sampling.go
generated
vendored
Normal file
290
vendor/go.opentelemetry.io/otel/sdk/trace/sampling.go
generated
vendored
Normal file
@@ -0,0 +1,290 @@
|
||||
// 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 trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Sampler decides whether a trace should be sampled and exported.
|
||||
type Sampler interface {
|
||||
ShouldSample(parameters SamplingParameters) SamplingResult
|
||||
Description() string
|
||||
}
|
||||
|
||||
// SamplingParameters contains the values passed to a Sampler.
|
||||
type SamplingParameters struct {
|
||||
ParentContext context.Context
|
||||
TraceID trace.TraceID
|
||||
Name string
|
||||
Kind trace.SpanKind
|
||||
Attributes []attribute.KeyValue
|
||||
Links []trace.Link
|
||||
}
|
||||
|
||||
// SamplingDecision indicates whether a span is dropped, recorded and/or sampled.
|
||||
type SamplingDecision uint8
|
||||
|
||||
// Valid sampling decisions
|
||||
const (
|
||||
// Drop will not record the span and all attributes/events will be dropped
|
||||
Drop SamplingDecision = iota
|
||||
|
||||
// Record indicates the span's `IsRecording() == true`, but `Sampled` flag
|
||||
// *must not* be set
|
||||
RecordOnly
|
||||
|
||||
// RecordAndSample has span's `IsRecording() == true` and `Sampled` flag
|
||||
// *must* be set
|
||||
RecordAndSample
|
||||
)
|
||||
|
||||
// SamplingResult conveys a SamplingDecision, set of Attributes and a Tracestate.
|
||||
type SamplingResult struct {
|
||||
Decision SamplingDecision
|
||||
Attributes []attribute.KeyValue
|
||||
Tracestate trace.TraceState
|
||||
}
|
||||
|
||||
type traceIDRatioSampler struct {
|
||||
traceIDUpperBound uint64
|
||||
description string
|
||||
}
|
||||
|
||||
func (ts traceIDRatioSampler) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
psc := trace.SpanContextFromContext(p.ParentContext)
|
||||
x := binary.BigEndian.Uint64(p.TraceID[0:8]) >> 1
|
||||
if x < ts.traceIDUpperBound {
|
||||
return SamplingResult{
|
||||
Decision: RecordAndSample,
|
||||
Tracestate: psc.TraceState(),
|
||||
}
|
||||
}
|
||||
return SamplingResult{
|
||||
Decision: Drop,
|
||||
Tracestate: psc.TraceState(),
|
||||
}
|
||||
}
|
||||
|
||||
func (ts traceIDRatioSampler) Description() string {
|
||||
return ts.description
|
||||
}
|
||||
|
||||
// TraceIDRatioBased samples a given fraction of traces. Fractions >= 1 will
|
||||
// always sample. Fractions < 0 are treated as zero. To respect the
|
||||
// parent trace's `SampledFlag`, the `TraceIDRatioBased` sampler should be used
|
||||
// as a delegate of a `Parent` sampler.
|
||||
//nolint:golint // golint complains about stutter of `trace.TraceIDRatioBased`
|
||||
func TraceIDRatioBased(fraction float64) Sampler {
|
||||
if fraction >= 1 {
|
||||
return AlwaysSample()
|
||||
}
|
||||
|
||||
if fraction <= 0 {
|
||||
fraction = 0
|
||||
}
|
||||
|
||||
return &traceIDRatioSampler{
|
||||
traceIDUpperBound: uint64(fraction * (1 << 63)),
|
||||
description: fmt.Sprintf("TraceIDRatioBased{%g}", fraction),
|
||||
}
|
||||
}
|
||||
|
||||
type alwaysOnSampler struct{}
|
||||
|
||||
func (as alwaysOnSampler) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
return SamplingResult{
|
||||
Decision: RecordAndSample,
|
||||
Tracestate: trace.SpanContextFromContext(p.ParentContext).TraceState(),
|
||||
}
|
||||
}
|
||||
|
||||
func (as alwaysOnSampler) Description() string {
|
||||
return "AlwaysOnSampler"
|
||||
}
|
||||
|
||||
// AlwaysSample returns a Sampler that samples every trace.
|
||||
// Be careful about using this sampler in a production application with
|
||||
// significant traffic: a new trace will be started and exported for every
|
||||
// request.
|
||||
func AlwaysSample() Sampler {
|
||||
return alwaysOnSampler{}
|
||||
}
|
||||
|
||||
type alwaysOffSampler struct{}
|
||||
|
||||
func (as alwaysOffSampler) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
return SamplingResult{
|
||||
Decision: Drop,
|
||||
Tracestate: trace.SpanContextFromContext(p.ParentContext).TraceState(),
|
||||
}
|
||||
}
|
||||
|
||||
func (as alwaysOffSampler) Description() string {
|
||||
return "AlwaysOffSampler"
|
||||
}
|
||||
|
||||
// NeverSample returns a Sampler that samples no traces.
|
||||
func NeverSample() Sampler {
|
||||
return alwaysOffSampler{}
|
||||
}
|
||||
|
||||
// ParentBased returns a composite sampler which behaves differently,
|
||||
// based on the parent of the span. If the span has no parent,
|
||||
// the root(Sampler) is used to make sampling decision. If the span has
|
||||
// a parent, depending on whether the parent is remote and whether it
|
||||
// is sampled, one of the following samplers will apply:
|
||||
// - remoteParentSampled(Sampler) (default: AlwaysOn)
|
||||
// - remoteParentNotSampled(Sampler) (default: AlwaysOff)
|
||||
// - localParentSampled(Sampler) (default: AlwaysOn)
|
||||
// - localParentNotSampled(Sampler) (default: AlwaysOff)
|
||||
func ParentBased(root Sampler, samplers ...ParentBasedSamplerOption) Sampler {
|
||||
return parentBased{
|
||||
root: root,
|
||||
config: configureSamplersForParentBased(samplers),
|
||||
}
|
||||
}
|
||||
|
||||
type parentBased struct {
|
||||
root Sampler
|
||||
config config
|
||||
}
|
||||
|
||||
func configureSamplersForParentBased(samplers []ParentBasedSamplerOption) config {
|
||||
c := config{
|
||||
remoteParentSampled: AlwaysSample(),
|
||||
remoteParentNotSampled: NeverSample(),
|
||||
localParentSampled: AlwaysSample(),
|
||||
localParentNotSampled: NeverSample(),
|
||||
}
|
||||
|
||||
for _, so := range samplers {
|
||||
so.Apply(&c)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// config is a group of options for parentBased sampler.
|
||||
type config struct {
|
||||
remoteParentSampled, remoteParentNotSampled Sampler
|
||||
localParentSampled, localParentNotSampled Sampler
|
||||
}
|
||||
|
||||
// ParentBasedSamplerOption configures the sampler for a particular sampling case.
|
||||
type ParentBasedSamplerOption interface {
|
||||
Apply(*config)
|
||||
|
||||
// A private method to prevent users implementing the
|
||||
// interface and so future additions to it will not
|
||||
// violate compatibility.
|
||||
private()
|
||||
}
|
||||
|
||||
// WithRemoteParentSampled sets the sampler for the case of sampled remote parent.
|
||||
func WithRemoteParentSampled(s Sampler) ParentBasedSamplerOption {
|
||||
return remoteParentSampledOption{s}
|
||||
}
|
||||
|
||||
type remoteParentSampledOption struct {
|
||||
s Sampler
|
||||
}
|
||||
|
||||
func (o remoteParentSampledOption) Apply(config *config) {
|
||||
config.remoteParentSampled = o.s
|
||||
}
|
||||
|
||||
func (remoteParentSampledOption) private() {}
|
||||
|
||||
// WithRemoteParentNotSampled sets the sampler for the case of remote parent
|
||||
// which is not sampled.
|
||||
func WithRemoteParentNotSampled(s Sampler) ParentBasedSamplerOption {
|
||||
return remoteParentNotSampledOption{s}
|
||||
}
|
||||
|
||||
type remoteParentNotSampledOption struct {
|
||||
s Sampler
|
||||
}
|
||||
|
||||
func (o remoteParentNotSampledOption) Apply(config *config) {
|
||||
config.remoteParentNotSampled = o.s
|
||||
}
|
||||
|
||||
func (remoteParentNotSampledOption) private() {}
|
||||
|
||||
// WithLocalParentSampled sets the sampler for the case of sampled local parent.
|
||||
func WithLocalParentSampled(s Sampler) ParentBasedSamplerOption {
|
||||
return localParentSampledOption{s}
|
||||
}
|
||||
|
||||
type localParentSampledOption struct {
|
||||
s Sampler
|
||||
}
|
||||
|
||||
func (o localParentSampledOption) Apply(config *config) {
|
||||
config.localParentSampled = o.s
|
||||
}
|
||||
|
||||
func (localParentSampledOption) private() {}
|
||||
|
||||
// WithLocalParentNotSampled sets the sampler for the case of local parent
|
||||
// which is not sampled.
|
||||
func WithLocalParentNotSampled(s Sampler) ParentBasedSamplerOption {
|
||||
return localParentNotSampledOption{s}
|
||||
}
|
||||
|
||||
type localParentNotSampledOption struct {
|
||||
s Sampler
|
||||
}
|
||||
|
||||
func (o localParentNotSampledOption) Apply(config *config) {
|
||||
config.localParentNotSampled = o.s
|
||||
}
|
||||
|
||||
func (localParentNotSampledOption) private() {}
|
||||
|
||||
func (pb parentBased) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
psc := trace.SpanContextFromContext(p.ParentContext)
|
||||
if psc.IsValid() {
|
||||
if psc.IsRemote() {
|
||||
if psc.IsSampled() {
|
||||
return pb.config.remoteParentSampled.ShouldSample(p)
|
||||
}
|
||||
return pb.config.remoteParentNotSampled.ShouldSample(p)
|
||||
}
|
||||
|
||||
if psc.IsSampled() {
|
||||
return pb.config.localParentSampled.ShouldSample(p)
|
||||
}
|
||||
return pb.config.localParentNotSampled.ShouldSample(p)
|
||||
}
|
||||
return pb.root.ShouldSample(p)
|
||||
}
|
||||
|
||||
func (pb parentBased) Description() string {
|
||||
return fmt.Sprintf("ParentBased{root:%s,remoteParentSampled:%s,"+
|
||||
"remoteParentNotSampled:%s,localParentSampled:%s,localParentNotSampled:%s}",
|
||||
pb.root.Description(),
|
||||
pb.config.remoteParentSampled.Description(),
|
||||
pb.config.remoteParentNotSampled.Description(),
|
||||
pb.config.localParentSampled.Description(),
|
||||
pb.config.localParentNotSampled.Description(),
|
||||
)
|
||||
}
|
||||
80
vendor/go.opentelemetry.io/otel/sdk/trace/simple_span_processor.go
generated
vendored
Normal file
80
vendor/go.opentelemetry.io/otel/sdk/trace/simple_span_processor.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.
|
||||
|
||||
package trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
)
|
||||
|
||||
// simpleSpanProcessor is a SpanProcessor that synchronously sends all
|
||||
// completed Spans to a trace.Exporter immediately.
|
||||
type simpleSpanProcessor struct {
|
||||
exporterMu sync.RWMutex
|
||||
exporter SpanExporter
|
||||
stopOnce sync.Once
|
||||
}
|
||||
|
||||
var _ SpanProcessor = (*simpleSpanProcessor)(nil)
|
||||
|
||||
// NewSimpleSpanProcessor returns a new SpanProcessor that will synchronously
|
||||
// send completed spans to the exporter immediately.
|
||||
func NewSimpleSpanProcessor(exporter SpanExporter) SpanProcessor {
|
||||
ssp := &simpleSpanProcessor{
|
||||
exporter: exporter,
|
||||
}
|
||||
return ssp
|
||||
}
|
||||
|
||||
// OnStart does nothing.
|
||||
func (ssp *simpleSpanProcessor) OnStart(context.Context, ReadWriteSpan) {}
|
||||
|
||||
// OnEnd immediately exports a ReadOnlySpan.
|
||||
func (ssp *simpleSpanProcessor) OnEnd(s ReadOnlySpan) {
|
||||
ssp.exporterMu.RLock()
|
||||
defer ssp.exporterMu.RUnlock()
|
||||
|
||||
if ssp.exporter != nil && s.SpanContext().TraceFlags().IsSampled() {
|
||||
ss := s.Snapshot()
|
||||
if err := ssp.exporter.ExportSpans(context.Background(), []*SpanSnapshot{ss}); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown shuts down the exporter this SimpleSpanProcessor exports to.
|
||||
func (ssp *simpleSpanProcessor) Shutdown(ctx context.Context) error {
|
||||
var err error
|
||||
ssp.stopOnce.Do(func() {
|
||||
ssp.exporterMu.Lock()
|
||||
exporter := ssp.exporter
|
||||
// Set exporter to nil so subsequent calls to OnEnd are ignored
|
||||
// gracefully.
|
||||
ssp.exporter = nil
|
||||
ssp.exporterMu.Unlock()
|
||||
|
||||
// Clear the ssp.exporter prior to shutting it down so if that creates
|
||||
// a span that needs to be exported there is no deadlock.
|
||||
err = exporter.Shutdown(ctx)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// ForceFlush does nothing as there is no data to flush.
|
||||
func (ssp *simpleSpanProcessor) ForceFlush(context.Context) error {
|
||||
return nil
|
||||
}
|
||||
617
vendor/go.opentelemetry.io/otel/sdk/trace/span.go
generated
vendored
Normal file
617
vendor/go.opentelemetry.io/otel/sdk/trace/span.go
generated
vendored
Normal file
@@ -0,0 +1,617 @@
|
||||
// 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 trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/semconv"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||
"go.opentelemetry.io/otel/sdk/internal"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
)
|
||||
|
||||
// ReadOnlySpan allows reading information from the data structure underlying a
|
||||
// trace.Span. It is used in places where reading information from a span is
|
||||
// necessary but changing the span isn't necessary or allowed.
|
||||
// TODO: Should we make the methods unexported? The purpose of this interface
|
||||
// is controlling access to `span` fields, not having multiple implementations.
|
||||
type ReadOnlySpan interface {
|
||||
Name() string
|
||||
SpanContext() trace.SpanContext
|
||||
Parent() trace.SpanContext
|
||||
SpanKind() trace.SpanKind
|
||||
StartTime() time.Time
|
||||
EndTime() time.Time
|
||||
Attributes() []attribute.KeyValue
|
||||
Links() []trace.Link
|
||||
Events() []trace.Event
|
||||
StatusCode() codes.Code
|
||||
StatusMessage() string
|
||||
Tracer() trace.Tracer
|
||||
IsRecording() bool
|
||||
InstrumentationLibrary() instrumentation.Library
|
||||
Resource() *resource.Resource
|
||||
Snapshot() *SpanSnapshot
|
||||
|
||||
// A private method to prevent users implementing the
|
||||
// interface and so future additions to it will not
|
||||
// violate compatibility.
|
||||
private()
|
||||
}
|
||||
|
||||
// ReadWriteSpan exposes the same methods as trace.Span and in addition allows
|
||||
// reading information from the underlying data structure.
|
||||
// This interface exposes the union of the methods of trace.Span (which is a
|
||||
// "write-only" span) and ReadOnlySpan. New methods for writing or reading span
|
||||
// information should be added under trace.Span or ReadOnlySpan, respectively.
|
||||
type ReadWriteSpan interface {
|
||||
trace.Span
|
||||
ReadOnlySpan
|
||||
}
|
||||
|
||||
// span is an implementation of the OpenTelemetry Span API representing the
|
||||
// individual component of a trace.
|
||||
type span struct {
|
||||
// mu protects the contents of this span.
|
||||
mu sync.Mutex
|
||||
|
||||
// parent holds the parent span of this span as a trace.SpanContext.
|
||||
parent trace.SpanContext
|
||||
|
||||
// spanKind represents the kind of this span as a trace.SpanKind.
|
||||
spanKind trace.SpanKind
|
||||
|
||||
// name is the name of this span.
|
||||
name string
|
||||
|
||||
// startTime is the time at which this span was started.
|
||||
startTime time.Time
|
||||
|
||||
// endTime is the time at which this span was ended. It contains the zero
|
||||
// value of time.Time until the span is ended.
|
||||
endTime time.Time
|
||||
|
||||
// statusCode represents the status of this span as a codes.Code value.
|
||||
statusCode codes.Code
|
||||
|
||||
// statusMessage represents the status of this span as a string.
|
||||
statusMessage string
|
||||
|
||||
// childSpanCount holds the number of child spans created for this span.
|
||||
childSpanCount int
|
||||
|
||||
// resource contains attributes representing an entity that produced this
|
||||
// span.
|
||||
resource *resource.Resource
|
||||
|
||||
// instrumentationLibrary defines the instrumentation library used to
|
||||
// provide instrumentation.
|
||||
instrumentationLibrary instrumentation.Library
|
||||
|
||||
// spanContext holds the SpanContext of this span.
|
||||
spanContext trace.SpanContext
|
||||
|
||||
// attributes are capped at configured limit. When the capacity is reached
|
||||
// an oldest entry is removed to create room for a new entry.
|
||||
attributes *attributesMap
|
||||
|
||||
// messageEvents are stored in FIFO queue capped by configured limit.
|
||||
messageEvents *evictedQueue
|
||||
|
||||
// links are stored in FIFO queue capped by configured limit.
|
||||
links *evictedQueue
|
||||
|
||||
// executionTracerTaskEnd ends the execution tracer span.
|
||||
executionTracerTaskEnd func()
|
||||
|
||||
// tracer is the SDK tracer that created this span.
|
||||
tracer *tracer
|
||||
|
||||
// spanLimits holds the limits to this span.
|
||||
spanLimits SpanLimits
|
||||
}
|
||||
|
||||
var _ trace.Span = &span{}
|
||||
|
||||
// SpanContext returns the SpanContext of this span.
|
||||
func (s *span) SpanContext() trace.SpanContext {
|
||||
if s == nil {
|
||||
return trace.SpanContext{}
|
||||
}
|
||||
return s.spanContext
|
||||
}
|
||||
|
||||
// IsRecording returns if this span is being recorded. If this span has ended
|
||||
// this will return false.
|
||||
func (s *span) IsRecording() bool {
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
return !s.startTime.IsZero() && s.endTime.IsZero()
|
||||
}
|
||||
|
||||
// SetStatus sets the status of this span in the form of a code and a
|
||||
// message. This overrides the existing value of this span's status if one
|
||||
// exists. Message will be set only if status is error. If this span is not being
|
||||
// recorded than this method does nothing.
|
||||
func (s *span) SetStatus(code codes.Code, msg string) {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
s.mu.Lock()
|
||||
s.statusCode = code
|
||||
if code == codes.Error {
|
||||
s.statusMessage = msg
|
||||
}
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
// SetAttributes sets attributes of this span.
|
||||
//
|
||||
// If a key from attributes already exists the value associated with that key
|
||||
// will be overwritten with the value contained in attributes.
|
||||
//
|
||||
// If this span is not being recorded than this method does nothing.
|
||||
func (s *span) SetAttributes(attributes ...attribute.KeyValue) {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
s.copyToCappedAttributes(attributes...)
|
||||
}
|
||||
|
||||
// End ends the span. This method does nothing if the span is already ended or
|
||||
// is not being recorded.
|
||||
//
|
||||
// The only SpanOption currently supported is WithTimestamp which will set the
|
||||
// end time for a Span's life-cycle.
|
||||
//
|
||||
// If this method is called while panicking an error event is added to the
|
||||
// Span before ending it and the panic is continued.
|
||||
func (s *span) End(options ...trace.SpanOption) {
|
||||
// Do not start by checking if the span is being recorded which requires
|
||||
// acquiring a lock. Make a minimal check that the span is not nil.
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Store the end time as soon as possible to avoid artificially increasing
|
||||
// the span's duration in case some operation below takes a while.
|
||||
et := internal.MonotonicEndTime(s.startTime)
|
||||
|
||||
// Do relative expensive check now that we have an end time and see if we
|
||||
// need to do any more processing.
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
|
||||
if recovered := recover(); recovered != nil {
|
||||
// Record but don't stop the panic.
|
||||
defer panic(recovered)
|
||||
s.addEvent(
|
||||
semconv.ExceptionEventName,
|
||||
trace.WithAttributes(
|
||||
semconv.ExceptionTypeKey.String(typeStr(recovered)),
|
||||
semconv.ExceptionMessageKey.String(fmt.Sprint(recovered)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if s.executionTracerTaskEnd != nil {
|
||||
s.executionTracerTaskEnd()
|
||||
}
|
||||
|
||||
config := trace.NewSpanConfig(options...)
|
||||
|
||||
s.mu.Lock()
|
||||
// Setting endTime to non-zero marks the span as ended and not recording.
|
||||
if config.Timestamp.IsZero() {
|
||||
s.endTime = et
|
||||
} else {
|
||||
s.endTime = config.Timestamp
|
||||
}
|
||||
s.mu.Unlock()
|
||||
|
||||
sps, ok := s.tracer.provider.spanProcessors.Load().(spanProcessorStates)
|
||||
mustExportOrProcess := ok && len(sps) > 0
|
||||
if mustExportOrProcess {
|
||||
for _, sp := range sps {
|
||||
sp.sp.OnEnd(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RecordError will record err as a span event for this span. An additional call to
|
||||
// SetStatus is required if the Status of the Span should be set to Error, this method
|
||||
// does not change the Span status. If this span is not being recorded or err is nil
|
||||
// than this method does nothing.
|
||||
func (s *span) RecordError(err error, opts ...trace.EventOption) {
|
||||
if s == nil || err == nil || !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
|
||||
opts = append(opts, trace.WithAttributes(
|
||||
semconv.ExceptionTypeKey.String(typeStr(err)),
|
||||
semconv.ExceptionMessageKey.String(err.Error()),
|
||||
))
|
||||
s.addEvent(semconv.ExceptionEventName, opts...)
|
||||
}
|
||||
|
||||
func typeStr(i interface{}) string {
|
||||
t := reflect.TypeOf(i)
|
||||
if t.PkgPath() == "" && t.Name() == "" {
|
||||
// Likely a builtin type.
|
||||
return t.String()
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
|
||||
}
|
||||
|
||||
// Tracer returns the Tracer that created this span.
|
||||
func (s *span) Tracer() trace.Tracer {
|
||||
return s.tracer
|
||||
}
|
||||
|
||||
// AddEvent adds an event with the provided name and options. If this span is
|
||||
// not being recorded than this method does nothing.
|
||||
func (s *span) AddEvent(name string, o ...trace.EventOption) {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
s.addEvent(name, o...)
|
||||
}
|
||||
|
||||
func (s *span) addEvent(name string, o ...trace.EventOption) {
|
||||
c := trace.NewEventConfig(o...)
|
||||
|
||||
// Discard over limited attributes
|
||||
var discarded int
|
||||
if len(c.Attributes) > s.spanLimits.AttributePerEventCountLimit {
|
||||
discarded = len(c.Attributes) - s.spanLimits.AttributePerEventCountLimit
|
||||
c.Attributes = c.Attributes[:s.spanLimits.AttributePerEventCountLimit]
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.messageEvents.add(trace.Event{
|
||||
Name: name,
|
||||
Attributes: c.Attributes,
|
||||
DroppedAttributeCount: discarded,
|
||||
Time: c.Timestamp,
|
||||
})
|
||||
}
|
||||
|
||||
// SetName sets the name of this span. If this span is not being recorded than
|
||||
// this method does nothing.
|
||||
func (s *span) SetName(name string) {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.name = name
|
||||
}
|
||||
|
||||
// Name returns the name of this span.
|
||||
func (s *span) Name() string {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.name
|
||||
}
|
||||
|
||||
// Name returns the SpanContext of this span's parent span.
|
||||
func (s *span) Parent() trace.SpanContext {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.parent
|
||||
}
|
||||
|
||||
// SpanKind returns the SpanKind of this span.
|
||||
func (s *span) SpanKind() trace.SpanKind {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.spanKind
|
||||
}
|
||||
|
||||
// StartTime returns the time this span started.
|
||||
func (s *span) StartTime() time.Time {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.startTime
|
||||
}
|
||||
|
||||
// EndTime returns the time this span ended. For spans that have not yet
|
||||
// ended, the returned value will be the zero value of time.Time.
|
||||
func (s *span) EndTime() time.Time {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.endTime
|
||||
}
|
||||
|
||||
// Attributes returns the attributes of this span.
|
||||
func (s *span) Attributes() []attribute.KeyValue {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.attributes.evictList.Len() == 0 {
|
||||
return []attribute.KeyValue{}
|
||||
}
|
||||
return s.attributes.toKeyValue()
|
||||
}
|
||||
|
||||
// Links returns the links of this span.
|
||||
func (s *span) Links() []trace.Link {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if len(s.links.queue) == 0 {
|
||||
return []trace.Link{}
|
||||
}
|
||||
return s.interfaceArrayToLinksArray()
|
||||
}
|
||||
|
||||
// Events returns the events of this span.
|
||||
func (s *span) Events() []trace.Event {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if len(s.messageEvents.queue) == 0 {
|
||||
return []trace.Event{}
|
||||
}
|
||||
return s.interfaceArrayToMessageEventArray()
|
||||
}
|
||||
|
||||
// StatusCode returns the status code of this span.
|
||||
func (s *span) StatusCode() codes.Code {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.statusCode
|
||||
}
|
||||
|
||||
// StatusMessage returns the status message of this span.
|
||||
func (s *span) StatusMessage() string {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.statusMessage
|
||||
}
|
||||
|
||||
// InstrumentationLibrary returns the instrumentation.Library associated with
|
||||
// the Tracer that created this span.
|
||||
func (s *span) InstrumentationLibrary() instrumentation.Library {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.instrumentationLibrary
|
||||
}
|
||||
|
||||
// Resource returns the Resource associated with the Tracer that created this
|
||||
// span.
|
||||
func (s *span) Resource() *resource.Resource {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.resource
|
||||
}
|
||||
|
||||
func (s *span) addLink(link trace.Link) {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
// Discard over limited attributes
|
||||
if len(link.Attributes) > s.spanLimits.AttributePerLinkCountLimit {
|
||||
link.DroppedAttributeCount = len(link.Attributes) - s.spanLimits.AttributePerLinkCountLimit
|
||||
link.Attributes = link.Attributes[:s.spanLimits.AttributePerLinkCountLimit]
|
||||
}
|
||||
|
||||
s.links.add(link)
|
||||
}
|
||||
|
||||
// Snapshot creates a snapshot representing the current state of the span as an
|
||||
// export.SpanSnapshot and returns a pointer to it.
|
||||
func (s *span) Snapshot() *SpanSnapshot {
|
||||
var sd SpanSnapshot
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
sd.ChildSpanCount = s.childSpanCount
|
||||
sd.EndTime = s.endTime
|
||||
sd.InstrumentationLibrary = s.instrumentationLibrary
|
||||
sd.Name = s.name
|
||||
sd.Parent = s.parent
|
||||
sd.Resource = s.resource
|
||||
sd.SpanContext = s.spanContext
|
||||
sd.SpanKind = s.spanKind
|
||||
sd.StartTime = s.startTime
|
||||
sd.StatusCode = s.statusCode
|
||||
sd.StatusMessage = s.statusMessage
|
||||
|
||||
if s.attributes.evictList.Len() > 0 {
|
||||
sd.Attributes = s.attributes.toKeyValue()
|
||||
sd.DroppedAttributeCount = s.attributes.droppedCount
|
||||
}
|
||||
if len(s.messageEvents.queue) > 0 {
|
||||
sd.MessageEvents = s.interfaceArrayToMessageEventArray()
|
||||
sd.DroppedMessageEventCount = s.messageEvents.droppedCount
|
||||
}
|
||||
if len(s.links.queue) > 0 {
|
||||
sd.Links = s.interfaceArrayToLinksArray()
|
||||
sd.DroppedLinkCount = s.links.droppedCount
|
||||
}
|
||||
return &sd
|
||||
}
|
||||
|
||||
func (s *span) interfaceArrayToLinksArray() []trace.Link {
|
||||
linkArr := make([]trace.Link, 0)
|
||||
for _, value := range s.links.queue {
|
||||
linkArr = append(linkArr, value.(trace.Link))
|
||||
}
|
||||
return linkArr
|
||||
}
|
||||
|
||||
func (s *span) interfaceArrayToMessageEventArray() []trace.Event {
|
||||
messageEventArr := make([]trace.Event, 0)
|
||||
for _, value := range s.messageEvents.queue {
|
||||
messageEventArr = append(messageEventArr, value.(trace.Event))
|
||||
}
|
||||
return messageEventArr
|
||||
}
|
||||
|
||||
func (s *span) copyToCappedAttributes(attributes ...attribute.KeyValue) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for _, a := range attributes {
|
||||
// Ensure attributes conform to the specification:
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.0.1/specification/common/common.md#attributes
|
||||
if a.Valid() {
|
||||
s.attributes.add(a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *span) addChild() {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
s.mu.Lock()
|
||||
s.childSpanCount++
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func (*span) private() {}
|
||||
|
||||
func startSpanInternal(ctx context.Context, tr *tracer, name string, o *trace.SpanConfig) *span {
|
||||
span := &span{}
|
||||
|
||||
provider := tr.provider
|
||||
|
||||
// If told explicitly to make this a new root use a zero value SpanContext
|
||||
// as a parent which contains an invalid trace ID and is not remote.
|
||||
var psc trace.SpanContext
|
||||
if !o.NewRoot {
|
||||
psc = trace.SpanContextFromContext(ctx)
|
||||
}
|
||||
|
||||
// If there is a valid parent trace ID, use it to ensure the continuity of
|
||||
// the trace. Always generate a new span ID so other components can rely
|
||||
// on a unique span ID, even if the Span is non-recording.
|
||||
var tid trace.TraceID
|
||||
var sid trace.SpanID
|
||||
if !psc.TraceID().IsValid() {
|
||||
tid, sid = provider.idGenerator.NewIDs(ctx)
|
||||
} else {
|
||||
tid = psc.TraceID()
|
||||
sid = provider.idGenerator.NewSpanID(ctx, tid)
|
||||
}
|
||||
|
||||
spanLimits := provider.spanLimits
|
||||
span.attributes = newAttributesMap(spanLimits.AttributeCountLimit)
|
||||
span.messageEvents = newEvictedQueue(spanLimits.EventCountLimit)
|
||||
span.links = newEvictedQueue(spanLimits.LinkCountLimit)
|
||||
span.spanLimits = spanLimits
|
||||
|
||||
samplingResult := provider.sampler.ShouldSample(SamplingParameters{
|
||||
ParentContext: ctx,
|
||||
TraceID: tid,
|
||||
Name: name,
|
||||
Kind: o.SpanKind,
|
||||
Attributes: o.Attributes,
|
||||
Links: o.Links,
|
||||
})
|
||||
|
||||
scc := trace.SpanContextConfig{
|
||||
TraceID: tid,
|
||||
SpanID: sid,
|
||||
TraceState: samplingResult.Tracestate,
|
||||
}
|
||||
if isSampled(samplingResult) {
|
||||
scc.TraceFlags = psc.TraceFlags() | trace.FlagsSampled
|
||||
} else {
|
||||
scc.TraceFlags = psc.TraceFlags() &^ trace.FlagsSampled
|
||||
}
|
||||
span.spanContext = trace.NewSpanContext(scc)
|
||||
|
||||
if !isRecording(samplingResult) {
|
||||
return span
|
||||
}
|
||||
|
||||
startTime := o.Timestamp
|
||||
if startTime.IsZero() {
|
||||
startTime = time.Now()
|
||||
}
|
||||
span.startTime = startTime
|
||||
|
||||
span.spanKind = trace.ValidateSpanKind(o.SpanKind)
|
||||
span.name = name
|
||||
span.parent = psc
|
||||
span.resource = provider.resource
|
||||
span.instrumentationLibrary = tr.instrumentationLibrary
|
||||
|
||||
span.SetAttributes(samplingResult.Attributes...)
|
||||
|
||||
return span
|
||||
}
|
||||
|
||||
func isRecording(s SamplingResult) bool {
|
||||
return s.Decision == RecordOnly || s.Decision == RecordAndSample
|
||||
}
|
||||
|
||||
func isSampled(s SamplingResult) bool {
|
||||
return s.Decision == RecordAndSample
|
||||
}
|
||||
|
||||
// SpanSnapshot is a snapshot of a span which contains all the information
|
||||
// collected by the span. Its main purpose is exporting completed spans.
|
||||
// Although SpanSnapshot fields can be accessed and potentially modified,
|
||||
// SpanSnapshot should be treated as immutable. Changes to the span from which
|
||||
// the SpanSnapshot was created are NOT reflected in the SpanSnapshot.
|
||||
type SpanSnapshot struct {
|
||||
SpanContext trace.SpanContext
|
||||
Parent trace.SpanContext
|
||||
SpanKind trace.SpanKind
|
||||
Name string
|
||||
StartTime time.Time
|
||||
// The wall clock time of EndTime will be adjusted to always be offset
|
||||
// from StartTime by the duration of the span.
|
||||
EndTime time.Time
|
||||
Attributes []attribute.KeyValue
|
||||
MessageEvents []trace.Event
|
||||
Links []trace.Link
|
||||
StatusCode codes.Code
|
||||
StatusMessage string
|
||||
|
||||
// DroppedAttributeCount contains dropped attributes for the span itself.
|
||||
DroppedAttributeCount int
|
||||
DroppedMessageEventCount int
|
||||
DroppedLinkCount int
|
||||
|
||||
// ChildSpanCount holds the number of child span created for this span.
|
||||
ChildSpanCount int
|
||||
|
||||
// Resource contains attributes representing an entity that produced this span.
|
||||
Resource *resource.Resource
|
||||
|
||||
// InstrumentationLibrary defines the instrumentation library used to
|
||||
// provide instrumentation.
|
||||
InstrumentationLibrary instrumentation.Library
|
||||
}
|
||||
39
vendor/go.opentelemetry.io/otel/sdk/trace/span_exporter.go
generated
vendored
Normal file
39
vendor/go.opentelemetry.io/otel/sdk/trace/span_exporter.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 trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import "context"
|
||||
|
||||
// SpanExporter handles the delivery of SpanSnapshot structs to external
|
||||
// receivers. This is the final component in the trace export pipeline.
|
||||
type SpanExporter interface {
|
||||
// ExportSpans exports a batch of SpanSnapshots.
|
||||
//
|
||||
// This function is called synchronously, so there is no concurrency
|
||||
// safety requirement. However, due to the synchronous calling pattern,
|
||||
// it is critical that all timeouts and cancellations contained in the
|
||||
// passed context must be honored.
|
||||
//
|
||||
// Any retry logic must be contained in this function. The SDK that
|
||||
// calls this function will not implement any retry logic. All errors
|
||||
// returned by this function are considered unrecoverable and will be
|
||||
// reported to a configured error Handler.
|
||||
ExportSpans(ctx context.Context, ss []*SpanSnapshot) error
|
||||
// Shutdown notifies the exporter of a pending halt to operations. The
|
||||
// exporter is expected to preform any cleanup or synchronization it
|
||||
// requires while honoring all timeouts and cancellations contained in
|
||||
// the passed context.
|
||||
Shutdown(ctx context.Context) error
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user