diff --git a/internal/newtelemetry/api.go b/internal/newtelemetry/api.go index 115a4a5003..ba221232df 100644 --- a/internal/newtelemetry/api.go +++ b/internal/newtelemetry/api.go @@ -7,6 +7,8 @@ package newtelemetry import ( "net/http" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/newtelemetry/types" ) type ClientConfig struct { @@ -14,47 +16,36 @@ type ClientConfig struct { // Defaults to https://instrumentation-telemetry-intake.datadoghq.com/api/v2/apmtelemetry AgentlessURL string - // AgentURL is the url to the agent without the path + // AgentURL is the url to the agent without the path, AgentURL string // APIKey is the API key to use for sending telemetry, defaults to the env var DD_API_KEY. APIKey string - // HTTPClient is the http client to use for sending telemetry, defaults to http.DefaultClient. + // HTTPClient is the http client to use for sending telemetry, defaults to a http.DefaultClient copy. HTTPClient http.RoundTripper } -// NewClient creates a new telemetry client with the given service, environment, and version and config. -func NewClient(service, env, version string, config ClientConfig) (Client, error) { - return nil, nil -} - -// StartApp starts the telemetry client with the given client send the app-started telemetry and sets it as the global client. -func StartApp(client Client) error { - return nil -} - -// StopApp creates the app-stopped telemetry, adding to the queue and flush all the queue before stopping the client. -func StopApp() { -} - +// MetricHandle can be used to submit different values for the same metric. // MetricHandle is used to reduce lock contention when submitting metrics. // This can also be used ephemerally to submit a single metric value like this: // -// telemetry.Metric(telemetry.Appsec, "my-count").Submit(1.0, []string{"tag1:true", "tag2:1.0"}) +// telemetry.Metric(telemetry.Appsec, "my-count", map[string]string{"tag1": "true", "tag2": "1.0"}).Submit(1.0) type MetricHandle interface { - Submit(value float64, tags []string) + Submit(value float64) flush() } -// Logger is the interface i -type Logger interface { +// TelemetryLogger is the interface implementing the telemetry logs. Supports log deduplication. All methods are Thread-safe +// This is an interface for easier testing but all functions will be mirrored at the package level to call +// the global client. +type TelemetryLogger interface { // WithTags creates a new Logger which will send a comma-separated list of tags with the next logs - WithTags(tags string) Logger + WithTags(tags string) TelemetryLogger // WithStackTrace creates a new Logger which will send a stack trace generated for each next log. - WithStackTrace(tags string) Logger + WithStackTrace() TelemetryLogger // Error sends a telemetry log at the ERROR level Error(text string) @@ -66,39 +57,60 @@ type Logger interface { Debug(text string) } -// Client constitutes all the functions available concurrently for the telemetry users. +// Integration is an integration that is configured to be traced. +type Integration struct { + Name string + Version string + AutoEnabled bool + Compatible bool + Error string +} + +// Client constitutes all the functions available concurrently for the telemetry users. All methods are thread-safe +// This is an interface for easier testing but all functions will be mirrored at the package level to call +// the global client. type Client interface { - // Count creates a new metric handle for the given namespace and name that can be used to submit values. - Count(namespace Namespace, name string) MetricHandle - // Rate creates a new metric handle for the given namespace and name that can be used to submit values. - Rate(namespace Namespace, name string) MetricHandle + // Count creates a new metric handle for the given parameters that can be used to submit values. + Count(namespace types.Namespace, name string, tags map[string]string) MetricHandle + + // Rate creates a new metric handle for the given parameters that can be used to submit values. + Rate(namespace types.Namespace, name string, tags map[string]string) MetricHandle - // Gauge creates a new metric handle for the given namespace and name that can be used to submit values. - Gauge(namespace Namespace, name string) MetricHandle + // Gauge creates a new metric handle for the given parameters that can be used to submit values. + Gauge(namespace types.Namespace, name string, tags map[string]string) MetricHandle - // Distribution creates a new metric handle for the given namespace and name that can be used to submit values. - Distribution(namespace Namespace, name string) MetricHandle + // Distribution creates a new metric handle for the given parameters that can be used to submit values. + Distribution(namespace types.Namespace, name string, tags map[string]string) MetricHandle // Logger returns an implementation of the Logger interface which sends telemetry logs. - Logger() Logger + Logger() TelemetryLogger - // ProductOnOff sent the telemetry necessary to signal that a product is enabled/disabled. - ProductOnOff(product Namespace, enabled bool) + // ProductStarted declares a product to have started at the customer’s request + ProductStarted(product types.Namespace) + + // ProductStopped declares a product to have being stopped by the customer + ProductStopped(product types.Namespace) + + // ProductStartError declares that a product could not start because of the following error + ProductStartError(product types.Namespace, err error) // AddAppConfig adds a key value pair to the app configuration and send the change to telemetry // value has to be json serializable and the origin is the source of the change. - AddAppConfig(key string, value any, origin Origin) + AddAppConfig(key string, value any, origin types.Origin) - // AddBulkAppConfig adds a list of key value pairs to the app configuration and send the change to telemetry. + // AddBulkAppConfig adds a list of key value pairs to the app configuration and sends the change to telemetry. // Same as AddAppConfig but for multiple values. - AddBulkAppConfig(kvs []Configuration) + AddBulkAppConfig(kvs map[string]any, origin types.Origin) + + // MarkIntegrationAsLoaded marks an integration as loaded in the telemetry + MarkIntegrationAsLoaded(integration Integration) // flush closes the client and flushes any remaining data. flush() // appStart sends the telemetry necessary to signal that the app is starting. - appStart() + appStart() error // appStop sends the telemetry necessary to signal that the app is stopping and calls Close() appStop() diff --git a/internal/newtelemetry/client.go b/internal/newtelemetry/client.go new file mode 100644 index 0000000000..7beb7e6f8e --- /dev/null +++ b/internal/newtelemetry/client.go @@ -0,0 +1,89 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package newtelemetry + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/internal/newtelemetry/types" +) + +// NewClient creates a new telemetry client with the given service, environment, and version and config. +func NewClient(service, env, version string, config ClientConfig) (Client, error) { + return nil, nil +} + +type client struct{} + +func (c client) MarkIntegrationAsLoaded(integration Integration) { + //TODO implement me + panic("implement me") +} + +func (c client) Count(namespace types.Namespace, name string, tags map[string]string) MetricHandle { + //TODO implement me + panic("implement me") +} + +func (c client) Rate(namespace types.Namespace, name string, tags map[string]string) MetricHandle { + //TODO implement me + panic("implement me") +} + +func (c client) Gauge(namespace types.Namespace, name string, tags map[string]string) MetricHandle { + //TODO implement me + panic("implement me") +} + +func (c client) Distribution(namespace types.Namespace, name string, tags map[string]string) MetricHandle { + //TODO implement me + panic("implement me") +} + +func (c client) Logger() TelemetryLogger { + //TODO implement me + panic("implement me") +} + +func (c client) ProductStarted(product types.Namespace) { + //TODO implement me + panic("implement me") +} + +func (c client) ProductStopped(product types.Namespace) { + //TODO implement me + panic("implement me") +} + +func (c client) ProductStartError(product types.Namespace, err error) { + //TODO implement me + panic("implement me") +} + +func (c client) AddAppConfig(key string, value any, origin types.Origin) { + //TODO implement me + panic("implement me") +} + +func (c client) AddBulkAppConfig(kvs map[string]any, origin types.Origin) { + //TODO implement me + panic("implement me") +} + +func (c client) flush() { + //TODO implement me + panic("implement me") +} + +func (c client) appStart() error { + //TODO implement me + panic("implement me") +} + +func (c client) appStop() { + //TODO implement me + panic("implement me") +} + +var _ Client = (*client)(nil) diff --git a/internal/newtelemetry/config.go b/internal/newtelemetry/config.go deleted file mode 100644 index f09fd791b9..0000000000 --- a/internal/newtelemetry/config.go +++ /dev/null @@ -1,14 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2024 Datadog, Inc. - -package newtelemetry - -type InternalConfig struct { - Enabled bool - HeartbeatInterval int - DependencyCollectionEnabled bool - MetricsEnabled bool - LogsEnabled bool -} diff --git a/internal/newtelemetry/defaults.go b/internal/newtelemetry/defaults.go index 498c9d2e9b..58fa3ac11f 100644 --- a/internal/newtelemetry/defaults.go +++ b/internal/newtelemetry/defaults.go @@ -15,6 +15,7 @@ var ( // We copy the transport to avoid using the default one, as it might be // augmented with tracing and we don't want these calls to be recorded. // See https://golang.org/pkg/net/http/#DefaultTransport . + //orchestrion:ignore defaultHTTPClient = &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, diff --git a/internal/newtelemetry/globalclient.go b/internal/newtelemetry/globalclient.go new file mode 100644 index 0000000000..1811458b5e --- /dev/null +++ b/internal/newtelemetry/globalclient.go @@ -0,0 +1,89 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package newtelemetry + +import ( + "sync/atomic" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/newtelemetry/types" +) + +var globalClient atomic.Pointer[Client] + +// StartApp starts the telemetry client with the given client send the app-started telemetry and sets it as the global client. +func StartApp(client Client) error { + if err := client.appStart(); err != nil { + return err + } + SwapClient(client) + return nil +} + +// SwapClient swaps the global client with the given client and flush the old client. +func SwapClient(client Client) { + if oldClient := globalClient.Swap(&client); oldClient != nil && *oldClient != nil { + (*oldClient).flush() + } +} + +// StopApp creates the app-stopped telemetry, adding to the queue and flush all the queue before stopping the client. +func StopApp() { + if client := globalClient.Swap(nil); client != nil && *client != nil { + (*client).appStop() + (*client).flush() + } +} + +func Count(namespace types.Namespace, name string, tags map[string]string) MetricHandle { + return (*globalClient.Load()).Count(namespace, name, tags) +} + +// Rate creates a new metric handle for the given parameters that can be used to submit values. +func Rate(namespace types.Namespace, name string, tags map[string]string) MetricHandle { + return (*globalClient.Load()).Rate(namespace, name, tags) +} + +// Gauge creates a new metric handle for the given parameters that can be used to submit values. +func Gauge(namespace types.Namespace, name string, tags map[string]string) MetricHandle { + return (*globalClient.Load()).Gauge(namespace, name, tags) +} + +// Distribution creates a new metric handle for the given parameters that can be used to submit values. +func Distribution(namespace types.Namespace, name string, tags map[string]string) MetricHandle { + return (*globalClient.Load()).Distribution(namespace, name, tags) +} + +// Logger returns an implementation of the TelemetryLogger interface which sends telemetry logs. +func Logger() TelemetryLogger { + return (*globalClient.Load()).Logger() +} + +// ProductStarted declares a product to have started at the customer’s request +func ProductStarted(product types.Namespace) { + (*globalClient.Load()).ProductStarted(product) +} + +// ProductStopped declares a product to have being stopped by the customer +func ProductStopped(product types.Namespace) { + (*globalClient.Load()).ProductStopped(product) +} + +// ProductStartError declares that a product could not start because of the following error +func ProductStartError(product types.Namespace, err error) { + (*globalClient.Load()).ProductStartError(product, err) +} + +// AddAppConfig adds a key value pair to the app configuration and send the change to telemetry +// value has to be json serializable and the origin is the source of the change. +func AddAppConfig(key string, value any, origin types.Origin) { + (*globalClient.Load()).AddAppConfig(key, value, origin) +} + +// AddBulkAppConfig adds a list of key value pairs to the app configuration and sends the change to telemetry. +// Same as AddAppConfig but for multiple values. +func AddBulkAppConfig(kvs map[string]any, origin types.Origin) { + (*globalClient.Load()).AddBulkAppConfig(kvs, origin) +} diff --git a/internal/newtelemetry/hot_pointer.go b/internal/newtelemetry/hot_pointer.go index b8383f45ac..f2d52be5aa 100644 --- a/internal/newtelemetry/hot_pointer.go +++ b/internal/newtelemetry/hot_pointer.go @@ -27,6 +27,11 @@ func (hp *hotPointer[T]) Lock() *T { return hp.value } +// Unlock unlocks the lock +func (hp *hotPointer[T]) Unlock() { + hp.writeMu.Unlock() +} + // StandbyValue returns the standby value WITHOUT locking. Which means it cannot be used concurrently. func (hp *hotPointer[T]) StandbyValue() *T { return hp.standby diff --git a/internal/newtelemetry/ringbuffer.go b/internal/newtelemetry/internal/ringbuffer.go similarity index 99% rename from internal/newtelemetry/ringbuffer.go rename to internal/newtelemetry/internal/ringbuffer.go index 8366a3de34..f8af3c48e3 100644 --- a/internal/newtelemetry/ringbuffer.go +++ b/internal/newtelemetry/internal/ringbuffer.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2024 Datadog, Inc. -package newtelemetry +package internal import ( "sync" diff --git a/internal/newtelemetry/internal/transport/body.go b/internal/newtelemetry/internal/transport/body.go new file mode 100644 index 0000000000..761db0555d --- /dev/null +++ b/internal/newtelemetry/internal/transport/body.go @@ -0,0 +1,52 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package transport + +import ( + "runtime" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" + "gopkg.in/DataDog/dd-trace-go.v1/internal/hostname" + "gopkg.in/DataDog/dd-trace-go.v1/internal/osinfo" + tracerversion "gopkg.in/DataDog/dd-trace-go.v1/internal/version" +) + +// Body is the common high-level structure encapsulating a telemetry request body +type Body struct { + APIVersion string `json:"api_version"` + RequestType RequestType `json:"request_type"` + TracerTime int64 `json:"tracer_time"` + RuntimeID string `json:"runtime_id"` + SeqID int64 `json:"seq_id"` + Debug bool `json:"debug"` + Payload interface{} `json:"payload"` + Application Application `json:"application"` + Host Host `json:"host"` +} + +func NewBody(service, env, version string) *Body { + return &Body{ + APIVersion: "v2", + RuntimeID: globalconfig.RuntimeID(), + Application: Application{ + ServiceName: service, + Env: env, + ServiceVersion: version, + TracerVersion: tracerversion.Tag, + LanguageName: "go", + LanguageVersion: runtime.Version(), + }, + Host: Host{ + Hostname: hostname.Get(), + OS: osinfo.OSName(), + OSVersion: osinfo.OSVersion(), + Architecture: osinfo.Architecture(), + KernelName: osinfo.KernelName(), + KernelRelease: osinfo.KernelRelease(), + KernelVersion: osinfo.KernelVersion(), + }, + } +} diff --git a/internal/newtelemetry/message.go b/internal/newtelemetry/internal/transport/message.go similarity index 75% rename from internal/newtelemetry/message.go rename to internal/newtelemetry/internal/transport/message.go index e8c5f12148..d7ec1ce833 100644 --- a/internal/newtelemetry/message.go +++ b/internal/newtelemetry/internal/transport/message.go @@ -1,14 +1,14 @@ // Unless explicitly stated otherwise all files in this repository are licensed // under the Apache License Version 2.0. // This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2022 Datadog, Inc. +// Copyright 2024 Datadog, Inc. -package newtelemetry +package transport import ( - "bytes" - "fmt" "net/http" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/newtelemetry/types" ) // Request captures all necessary information for a telemetry event submission @@ -19,19 +19,6 @@ type Request struct { URL string } -// Body is the common high-level structure encapsulating a telemetry request body -type Body struct { - APIVersion string `json:"api_version"` - RequestType RequestType `json:"request_type"` - TracerTime int64 `json:"tracer_time"` - RuntimeID string `json:"runtime_id"` - SeqID int64 `json:"seq_id"` - Debug bool `json:"debug"` - Payload interface{} `json:"payload"` - Application Application `json:"application"` - Host Host `json:"host"` -} - // RequestType determines how the Payload of a request should be handled type RequestType string @@ -63,19 +50,6 @@ const ( RequestTypeAppIntegrationsChange RequestType = "app-integrations-change" ) -// Namespace describes an APM product to distinguish telemetry coming from -// different products used by the same application -type Namespace string - -const ( - NamespaceGeneral Namespace = "general" - NamespaceTracers Namespace = "tracers" - NamespaceProfilers Namespace = "profilers" - NamespaceAppSec Namespace = "appsec" - NamespaceIAST Namespace = "iast" - NamespaceTelemetry Namespace = "telemetry" -) - // MetricType is the type of metric being sent, either count, gauge, rate or distribution type MetricType string @@ -139,73 +113,15 @@ type ConfigurationChange struct { RemoteConfig *RemoteConfig `json:"remote_config,omitempty"` } -type Origin int - -const ( - OriginDefault Origin = iota - OriginCode - OriginDDConfig - OriginEnvVar - OriginRemoteConfig -) - -func (o Origin) String() string { - switch o { - case OriginDefault: - return "default" - case OriginCode: - return "code" - case OriginDDConfig: - return "dd_config" - case OriginEnvVar: - return "env_var" - case OriginRemoteConfig: - return "remote_config" - default: - return fmt.Sprintf("unknown origin %d", o) - } -} - -func (o Origin) MarshalJSON() ([]byte, error) { - var b bytes.Buffer - b.WriteString(`"`) - b.WriteString(o.String()) - b.WriteString(`"`) - return b.Bytes(), nil -} - // Configuration is a library-specific configuration value // that should be initialized through StringConfig, IntConfig, FloatConfig, or BoolConfig type Configuration struct { Name string `json:"name"` Value interface{} `json:"value"` // origin is the source of the config. It is one of {default, env_var, code, dd_config, remote_config}. - Origin Origin `json:"origin"` - Error Error `json:"error"` - IsOverriden bool `json:"is_overridden"` -} - -// TODO: be able to pass in origin, error, isOverriden info to config -// constructors - -// StringConfig returns a Configuration struct with a string value -func StringConfig(key string, val string) Configuration { - return Configuration{Name: key, Value: val} -} - -// IntConfig returns a Configuration struct with a int value -func IntConfig(key string, val int) Configuration { - return Configuration{Name: key, Value: val} -} - -// FloatConfig returns a Configuration struct with a float value -func FloatConfig(key string, val float64) Configuration { - return Configuration{Name: key, Value: val} -} - -// BoolConfig returns a Configuration struct with a bool value -func BoolConfig(key string, val bool) Configuration { - return Configuration{Name: key, Value: val} + Origin types.Origin `json:"origin"` + Error Error `json:"error"` + IsOverriden bool `json:"is_overridden"` } // ProductsPayload is the top-level key for the app-product-change payload. @@ -263,13 +179,13 @@ type AdditionalPayload struct { // Metrics corresponds to the "generate-metrics" request type type Metrics struct { - Namespace Namespace `json:"namespace"` - Series []Series `json:"series"` + Namespace types.Namespace `json:"namespace"` + Series []Series `json:"series"` } // DistributionMetrics corresponds to the "distributions" request type type DistributionMetrics struct { - Namespace Namespace `json:"namespace"` + Namespace types.Namespace `json:"namespace"` Series []DistributionSeries `json:"series"` } @@ -289,8 +205,8 @@ type Series struct { // NOTE: If this field isn't present in the request, the API assumes // the metric is common. So we can't "omitempty" even though the // field is technically optional. - Common bool `json:"common"` - Namespace Namespace `json:"namespace,omitempty"` + Common bool `json:"common"` + Namespace types.Namespace `json:"namespace,omitempty"` } // DistributionSeries is a sequence of observations for a distribution metric. diff --git a/internal/newtelemetry/payload.go b/internal/newtelemetry/payload.go deleted file mode 100644 index 888eb1fd3d..0000000000 --- a/internal/newtelemetry/payload.go +++ /dev/null @@ -1,10 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2024 Datadog, Inc. - -package newtelemetry - -type Payload interface { - RequestType() RequestType -} diff --git a/internal/newtelemetry/requesy_body_pool.go b/internal/newtelemetry/requesy_body_pool.go deleted file mode 100644 index 352b51ec72..0000000000 --- a/internal/newtelemetry/requesy_body_pool.go +++ /dev/null @@ -1,69 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2024 Datadog, Inc. - -package newtelemetry - -import ( - "runtime" - "sync" - "sync/atomic" - "time" - - "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" - "gopkg.in/DataDog/dd-trace-go.v1/internal/hostname" - "gopkg.in/DataDog/dd-trace-go.v1/internal/osinfo" - tracerversion "gopkg.in/DataDog/dd-trace-go.v1/internal/version" -) - -type RequestBodyPool struct { - pool sync.Pool - seqID atomic.Int64 -} - -func NewRequestPool(service, env, version string) *RequestBodyPool { - return &RequestBodyPool{ - pool: sync.Pool{ - New: func() any { - return &Body{ - APIVersion: "v2", - RuntimeID: globalconfig.RuntimeID(), - Application: Application{ - ServiceName: service, - Env: env, - ServiceVersion: version, - TracerVersion: tracerversion.Tag, - LanguageName: "go", - LanguageVersion: runtime.Version(), - }, - Host: Host{ - Hostname: hostname.Get(), - OS: osinfo.OSName(), - OSVersion: osinfo.OSVersion(), - Architecture: osinfo.Architecture(), - KernelName: osinfo.KernelName(), - KernelRelease: osinfo.KernelRelease(), - KernelVersion: osinfo.KernelVersion(), - }, - } - }, - }, - } -} - -// Get returns a new Body from the pool, ready to be turned into JSON and sent to the API. -func (p *RequestBodyPool) Get(payload Payload) *Body { - body := p.pool.Get().(*Body) - body.SeqID = p.seqID.Add(1) - body.TracerTime = time.Now().Unix() - body.Payload = payload - body.RequestType = payload.RequestType() - return body -} - -// Put returns a Body to the pool. -func (p *RequestBodyPool) Put(body *Body) { - body.Payload = nil - p.pool.Put(body) -} diff --git a/internal/newtelemetry/types/namespace.go b/internal/newtelemetry/types/namespace.go new file mode 100644 index 0000000000..c86453ecea --- /dev/null +++ b/internal/newtelemetry/types/namespace.go @@ -0,0 +1,19 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package types + +// Namespace describes an APM product to distinguish telemetry coming from +// different products used by the same application +type Namespace string + +const ( + NamespaceGeneral Namespace = "general" + NamespaceTracers Namespace = "tracers" + NamespaceProfilers Namespace = "profilers" + NamespaceAppSec Namespace = "appsec" + NamespaceIAST Namespace = "iast" + NamespaceTelemetry Namespace = "telemetry" +) diff --git a/internal/newtelemetry/types/origin.go b/internal/newtelemetry/types/origin.go new file mode 100644 index 0000000000..9d45a10ab9 --- /dev/null +++ b/internal/newtelemetry/types/origin.go @@ -0,0 +1,46 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package types + +import ( + "bytes" + "fmt" +) + +type Origin int + +const ( + OriginDefault Origin = iota + OriginCode + OriginDDConfig + OriginEnvVar + OriginRemoteConfig +) + +func (o Origin) String() string { + switch o { + case OriginDefault: + return "default" + case OriginCode: + return "code" + case OriginDDConfig: + return "dd_config" + case OriginEnvVar: + return "env_var" + case OriginRemoteConfig: + return "remote_config" + default: + return fmt.Sprintf("unknown origin %d", o) + } +} + +func (o Origin) MarshalJSON() ([]byte, error) { + var b bytes.Buffer + b.WriteString(`"`) + b.WriteString(o.String()) + b.WriteString(`"`) + return b.Bytes(), nil +}