diff --git a/README.md b/README.md index d1e80dafc1..33d2b531c8 100644 --- a/README.md +++ b/README.md @@ -23,22 +23,22 @@ ### ✨ Language Agnostic Auto-instrumentation -Odigos supports any application written in Java, Python, .NET, Node.js, and **Go**. +Odigos supports any application written in Java, Python, .NET, Node.js, and **Go**. Historically, compiled languages like Go have been difficult to instrument without code changes. Odigos solves this problem by uniquely leveraging [eBPF](https://ebpf.io). ![Works on any application](assets/choose_apps.png) ### 🤝 Keep your existing observability tools -Odigos currently supports all the popular managed and open-source destinations. +Odigos currently supports all the popular managed and open-source destinations. By producing data in the [OpenTelemetry](https://opentelemetry.io) format, Odigos can be used with any observability tool that supports OTLP. For a complete list of supported destinations, see [here](#supported-destinations). ![Works with any observability tool](assets/choose_dest.png) -### 🎛️ Collectors Management -Odigos automatically scales OpenTelemetry collectors based on observability data volume. +### 🎛️ Collectors Management +Odigos automatically scales OpenTelemetry collectors based on observability data volume. Manage and configure collectors via a convenient web UI. ![Collectors Management](assets/overview_page.png) @@ -82,6 +82,7 @@ For more details, see our [quickstart guide](https://docs.odigos.io/intro). | Axiom | ✅ | | ✅ | | Sumo Logic | ✅ | ✅ | ✅ | | Coralogix | ✅ | ✅ | ✅ | +| Last9 | ✅ | ✅ | ✅ | ### Open Source diff --git a/common/config/last9.go b/common/config/last9.go new file mode 100644 index 0000000000..cae2f1af4f --- /dev/null +++ b/common/config/last9.go @@ -0,0 +1,65 @@ +package config + +import ( + "errors" + + "github.com/odigos-io/odigos/common" +) + +const ( + l9OtlpEndpointKey = "LAST9_OTLP_ENDPOINT" + l9OtlpAuthHeaderKey = "LAST9_OTLP_BASIC_AUTH_HEADER" +) + +type MyDest struct{} + +func (m *MyDest) DestType() common.DestinationType { + // DestinationType defined in common/dests.go + return common.Last9DestinationType +} + +func (m *MyDest) ModifyConfig(dest ExporterConfigurer, currentConfig *Config) error { + config := dest.GetConfig() + l9OtlpEndpoint, exists := config[l9OtlpEndpointKey] + if !exists { + return errors.New("Last9 OpenTelemetry Endpoint key(\"LAST9_OTLP_ENDPOINT\") not specified, Last9 will not be configured") + } + + l9OtlpAuthHeader, exists := config[l9OtlpAuthHeaderKey] + if !exists { + return errors.New("Last9 OpenTelemetry Basic Auth Header key(\"LAST9_OTLP_BASIC_AUTH_HEADER\") not specified, Last9 will not be configured") + } + + // to make sure that the exporter name is unique, we'll ask a ID from destination + exporterName := "otlp/last9-" + dest.GetID() + currentConfig.Exporters["otlp/last9"] = GenericMap{ + "endpoint": l9OtlpEndpoint, + "headers": GenericMap{ + "Authorization": l9OtlpAuthHeader, + }, + } + + // Modify the config here + if isTracingEnabled(dest) { + tracesPipelineName := "traces/last9-" + dest.GetID() + currentConfig.Service.Pipelines[tracesPipelineName] = Pipeline{ + Exporters: []string{exporterName}, + } + } + + if isMetricsEnabled(dest) { + metricsPipelineName := "metrics/last9-" + dest.GetID() + currentConfig.Service.Pipelines[metricsPipelineName] = Pipeline{ + Exporters: []string{exporterName}, + } + } + + if isLoggingEnabled(dest) { + logsPipelineName := "logs/last9-" + dest.GetID() + currentConfig.Service.Pipelines[logsPipelineName] = Pipeline{ + Exporters: []string{exporterName}, + } + } + + return nil +} diff --git a/common/config/root.go b/common/config/root.go index adae1e3fc7..0f885bb744 100644 --- a/common/config/root.go +++ b/common/config/root.go @@ -15,7 +15,7 @@ const ( var availableConfigers = []Configer{ &Middleware{}, &Honeycomb{}, &GrafanaCloudPrometheus{}, &GrafanaCloudTempo{}, - &GrafanaCloudLoki{}, &Datadog{}, &NewRelic{}, &Logzio{}, &Prometheus{}, + &GrafanaCloudLoki{}, &Datadog{}, &NewRelic{}, &Logzio{}, &Last9{}, &Prometheus{}, &Tempo{}, &Loki{}, &Jaeger{}, &GenericOTLP{}, &OTLPHttp{}, &Elasticsearch{}, &Quickwit{}, &Signoz{}, &Qryn{}, &OpsVerse{}, &Splunk{}, &Lightstep{}, &GoogleCloud{}, &GoogleCloudStorage{}, &Sentry{}, &AzureBlobStorage{}, &AWSS3{}, &Dynatrace{}, &Chronosphere{}, &ElasticAPM{}, &Axiom{}, &SumoLogic{}, &Coralogix{}, &Clickhouse{}, diff --git a/common/dests.go b/common/dests.go index 014bc09dee..5c2f1dad5c 100644 --- a/common/dests.go +++ b/common/dests.go @@ -23,6 +23,7 @@ const ( GrafanaCloudTempoDestinationType DestinationType = "grafanacloudtempo" HoneycombDestinationType DestinationType = "honeycomb" JaegerDestinationType DestinationType = "jaeger" + Last9DestinationType DestinationType = "last9" LightstepDestinationType DestinationType = "lightstep" LogzioDestinationType DestinationType = "logzio" LokiDestinationType DestinationType = "loki" diff --git a/destinations/data/last9.yaml b/destinations/data/last9.yaml new file mode 100644 index 0000000000..ac9f8246bf --- /dev/null +++ b/destinations/data/last9.yaml @@ -0,0 +1,30 @@ +apiVersion: internal.odigos.io/v1beta1 +kind: Destination +metadata: + type: last9 + displayName: Last9 + category: managed +spec: + image: last9.svg + signals: + traces: + supported: true + metrics: + supported: true + logs: + supported: true + fields: + - name: LAST9_OTLP_ENDPOINT + displayName: Last9 OpenTelemetry Endpoint + componentType: input + componentProps: + type: text + required: true + tooltip: 'Last9 OpenTelemetry Endpoint. Can be found at https://app.last9.io/integrations?category=all&integration=OpenTelemetry' + - name: LAST9_OTLP_BASIC_AUTH_HEADER + displayName: Basic Auth Header + componentType: input + componentProps: + type: password + required: true + placeholder: "Last9 Basic Auth Header" diff --git a/destinations/logos/last9.svg b/destinations/logos/last9.svg new file mode 100644 index 0000000000..a5e0c1a163 --- /dev/null +++ b/destinations/logos/last9.svg @@ -0,0 +1 @@ + \ No newline at end of file