Skip to content

Commit

Permalink
Merge branch 'main' into migration-to-new-runtimedetails-approach
Browse files Browse the repository at this point in the history
  • Loading branch information
tamirdavid1 authored Dec 30, 2024
2 parents 7b94b17 + 371fd0d commit ef5bf97
Show file tree
Hide file tree
Showing 56 changed files with 3,773 additions and 2,174 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:
uses: kyverno/action-install-chainsaw@v0.2.12

- name: Create Kind Cluster
uses: helm/kind-action@v1.11.0
uses: helm/kind-action@v1.12.0
with:
node_image: ${{ matrix.kind-image }}
version: 'v0.25.0'
Expand Down
92 changes: 48 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ Odigos is an open-source distributed tracing solution that simplifyes and improv

## Key Features

* **Code-Free Instrumentation** : Set up distributed tracing in minutes, eliminating manual code modifications.
* **Multi-Language Support** : Works with Java, Python, .NET, Node.js, and Go applications.
* **eBPF-Powered** : Utilizes eBPF technology for high-performance instrumentation of Go applications. eBPF-based instrumentation for Java, Python, and Node.js is available in the enterprise edition.
* **OpenTelemetry Compatible** : Generates traces in OpenTelemetry format for broad tool compatibility.
* **Vendor Agnostic** : Integrates with various monitoring solutions, avoiding vendor lock-in.
* **Automatic Scaling** : Manages and scales OpenTelemetry collectors based on data volume.
* **Opinionated Defaults** : Supplies common defaults and best practices out-of-the-box, requiring no deep knowledge of OpenTelemetry.
- **Code-Free Instrumentation** : Set up distributed tracing in minutes, eliminating manual code modifications.
- **Multi-Language Support** : Works with Java, Python, .NET, Node.js, and Go applications.
- **eBPF-Powered** : Utilizes eBPF technology for high-performance instrumentation of Go applications. eBPF-based instrumentation for Java, Python, and Node.js is available in the enterprise edition.
- **OpenTelemetry Compatible** : Generates traces in OpenTelemetry format for broad tool compatibility.
- **Vendor Agnostic** : Integrates with various monitoring solutions, avoiding vendor lock-in.
- **Automatic Scaling** : Manages and scales OpenTelemetry collectors based on data volume.
- **Opinionated Defaults** : Supplies common defaults and best practices out-of-the-box, requiring no deep knowledge of OpenTelemetry.

## Why Choose Odigos

Expand Down Expand Up @@ -85,48 +85,52 @@ For more details, see our [quickstart guide](https://docs.odigos.io/intro).

### Managed Destinations


| Destination | Traces | Metrics | Logs |
| ------------------------- | :------: | :-------: | :----: |
| AppDynamics ||||
| Axiom || ||
| AWS S3 || ||
| Azure Blob Storage || ||
| Causely || | |
| Chronosphere ||| |
| Coralogix ||||
| Datadog ||||
| Dynatrace ||||
| Gigapipe || | |
| Google Cloud Monitoring ||| |
| Google Cloud Storage || ||
| Grafana Cloud ||||
| Honeycomb ||||
| Last9 ||| |
| Lightstep || | |
| Logz.io ||||
| New Relic ||||
| OpsVerse ||||
| Sentry || | |
| Splunk || | |
| Sumo Logic ||||
| ----------------------- | :----: | :-----: | :--: |
| AppDynamics ||||
| Axiom || ||
| AWS S3 || ||
| Azure Blob Storage || ||
| Better Stack | |||
| Causely || | |
| Chronosphere ||| |
| Coralogix ||||
| Dash0 ||||
| Datadog ||||
| Dynatrace ||||
| Gigapipe || | |
| Google Cloud Monitoring ||| |
| Google Cloud Storage || ||
| Grafana Cloud ||||
| Groundcover inCloud ||||
| Honeycomb ||||
| HyperDX ||||
| KloudMate ||||
| Last9 ||| |
| Lightstep || | |
| Logz.io ||||
| Lumigo ||||
| New Relic ||||
| OpsVerse ||||
| Sentry || | |
| Splunk || | |
| Sumo Logic ||||

## Self-Hosted (Open Source) Destinations


| Destination | Traces | Metrics | Logs |
| --------------- | :------: | :-------: | :----: |
| ClickHouse ||||
| Elasticsearch || ||
| Jaeger || | |
| Loki | | ||
| OTLP ||||
| OTLP HTTP ||||
| Prometheus | || |
| Quickwit || | |
| qryn ||||
| SigNoz ||||
| Tempo || | |
| ------------- | :----: | :-----: | :--: |
| ClickHouse || ||
| Elasticsearch || ||
| Jaeger || | |
| Loki | | ||
| OTLP || ||
| OTLP HTTP || ||
| Prometheus | | | |
| Quickwit || | |
| qryn || ||
| SigNoz || ||
| Tempo || | |

Can't find the destination you need? Help us by following our quick [add new destination](https://docs.odigos.io/adding-new-dest) guide and submitting a PR.

Expand Down
2 changes: 1 addition & 1 deletion agents/python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# index_url = 'http://host.docker.internal:8080/packages/odigos_opentelemetry_python-0.1.1-py3-none-any.whl'

install_requires = [
f"odigos-opentelemetry-python @ {index_url}" if index_url else "odigos-opentelemetry-python"
f"odigos-opentelemetry-python @ {index_url}" if index_url else "odigos-opentelemetry-python==1.0.22"
]

setup(
Expand Down
27 changes: 27 additions & 0 deletions api/odigos/v1alpha1/instrumentationconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,33 @@ type InstrumentationConfig struct {
Status InstrumentationConfigStatus `json:"status,omitempty"`
}

type OtherAgent struct {
Name string `json:"name,omitempty"`
}

// +kubebuilder:object:generate=true
type EnvVar struct {
Name string `json:"name"`
Value string `json:"value"`
}

// +kubebuilder:object:generate=true
type RuntimeDetailsByContainer struct {
ContainerName string `json:"containerName"`
Language common.ProgrammingLanguage `json:"language"`
RuntimeVersion string `json:"runtimeVersion,omitempty"`
EnvVars []EnvVar `json:"envVars,omitempty"`
OtherAgent *OtherAgent `json:"otherAgent,omitempty"`
LibCType *common.LibCType `json:"libCType,omitempty"`

// Stores the error message from the CRI runtime if returned to prevent instrumenting the container if an error exists.
CriErrorMessage *string `json:"criErrorMessage,omitempty"`
// Holds the environment variables retrieved from the container runtime.
EnvFromContainerRuntime []EnvVar `json:"envFromContainerRuntime,omitempty"`
// A temporary variable used during migration to track whether the new runtime detection process has been executed. If empty, it indicates the process has not yet been run. This field may be removed later.
RuntimeUpdateState *ProcessingState `json:"runtimeUpdateState,omitempty"`
}

type InstrumentationConfigStatus struct {
// Capture Runtime Details for the workloads that this CR applies to.
RuntimeDetailsByContainer []RuntimeDetailsByContainer `json:"runtimeDetailsByContainer,omitempty"`
Expand Down
27 changes: 0 additions & 27 deletions api/odigos/v1alpha1/instrumentedapplication_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,6 @@ type InstrumentationLibraryOptions struct {
Options []ConfigOption `json:"options"`
}

// +kubebuilder:object:generate=true
type EnvVar struct {
Name string `json:"name"`
Value string `json:"value"`
}

type OtherAgent struct {
Name string `json:"name,omitempty"`
}

type ProcessingState string

const (
Expand All @@ -51,23 +41,6 @@ const (
ProcessingStateSkipped ProcessingState = "Skipped" // Used when env originally come from manifest
)

// +kubebuilder:object:generate=true
type RuntimeDetailsByContainer struct {
ContainerName string `json:"containerName"`
Language common.ProgrammingLanguage `json:"language"`
RuntimeVersion string `json:"runtimeVersion,omitempty"`
EnvVars []EnvVar `json:"envVars,omitempty"`
OtherAgent *OtherAgent `json:"otherAgent,omitempty"`
LibCType *common.LibCType `json:"libCType,omitempty"`

// Stores the error message from the CRI runtime if returned to prevent instrumenting the container if an error exists.
CriErrorMessage *string `json:"criErrorMessage,omitempty"`
// Holds the environment variables retrieved from the container runtime.
EnvFromContainerRuntime []EnvVar `json:"envFromContainerRuntime,omitempty"`
// A temporary variable used during migration to track whether the new runtime detection process has been executed. If empty, it indicates the process has not yet been run. This field may be removed later.
RuntimeUpdateState *ProcessingState `json:"runtimeUpdateState,omitempty"`
}

// +kubebuilder:object:generate=true
type OptionByContainer struct {
ContainerName string `json:"containerName"`
Expand Down
54 changes: 54 additions & 0 deletions common/config/betterstack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package config

import (
"github.com/odigos-io/odigos/common"
)

type BetterStack struct{}

func (j *BetterStack) DestType() common.DestinationType {
return common.BetterStackDestinationType
}

func (j *BetterStack) ModifyConfig(dest ExporterConfigurer, cfg *Config) error {
uniqueUri := "betterstack-" + dest.GetID()

processorName := "attributes/" + uniqueUri
cfg.Processors[processorName] = GenericMap{
"actions": []GenericMap{
{
"key": "better_stack_source_token",
"value": "${BETTERSTACK_TOKEN}",
"action": "insert",
},
},
}

if isMetricsEnabled(dest) {
exporterName := "prometheusremotewrite/" + uniqueUri
cfg.Exporters[exporterName] = GenericMap{
"endpoint": "https://in-otel.logs.betterstack.com/metrics",
}

pipeName := "metrics/" + uniqueUri
cfg.Service.Pipelines[pipeName] = Pipeline{
Processors: []string{processorName},
Exporters: []string{exporterName},
}
}

if isLoggingEnabled(dest) {
exporterName := "otlp/" + uniqueUri
cfg.Exporters[exporterName] = GenericMap{
"endpoint": "https://in-otel.logs.betterstack.com:443",
}

pipeName := "logs/" + uniqueUri
cfg.Service.Pipelines[pipeName] = Pipeline{
Processors: []string{processorName},
Exporters: []string{exporterName},
}
}

return nil
}
68 changes: 68 additions & 0 deletions common/config/dash0.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package config

import (
"errors"

"github.com/odigos-io/odigos/common"
)

const (
Dash0Endpoint = "DASH0_ENDPOINT"
)

var (
ErrorDash0EndpointMissing = errors.New("Dash0 is missing a required field (\"DASH0_ENDPOINT\"), Dash0 will not be configured")
)

type Dash0 struct{}

func (j *Dash0) DestType() common.DestinationType {
return common.Dash0DestinationType
}

func (j *Dash0) ModifyConfig(dest ExporterConfigurer, currentConfig *Config) error {
config := dest.GetConfig()
uniqueUri := "dash0-" + dest.GetID()

url, exists := config[Dash0Endpoint]
if !exists {
return ErrorDash0EndpointMissing
}
endpoint, err := parseOtlpGrpcUrl(url, true)
if err != nil {
return err
}

exporterName := "otlp/" + uniqueUri
exporterConfig := GenericMap{
"endpoint": endpoint,
"headers": GenericMap{
"Authorization": "Bearer ${DASH0_TOKEN}",
},
}

currentConfig.Exporters[exporterName] = exporterConfig

if isTracingEnabled(dest) {
pipeName := "traces/" + uniqueUri
currentConfig.Service.Pipelines[pipeName] = Pipeline{
Exporters: []string{exporterName},
}
}

if isMetricsEnabled(dest) {
pipeName := "metrics/" + uniqueUri
currentConfig.Service.Pipelines[pipeName] = Pipeline{
Exporters: []string{exporterName},
}
}

if isLoggingEnabled(dest) {
pipeName := "logs/" + uniqueUri
currentConfig.Service.Pipelines[pipeName] = Pipeline{
Exporters: []string{exporterName},
}
}

return nil
}
71 changes: 71 additions & 0 deletions common/config/groundcover.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package config

import (
"errors"

"github.com/odigos-io/odigos/common"
)

const (
GroundcoverEndpoint = "GROUNDCOVER_ENDPOINT"
GroundcoverApiKey = "GROUNDCOVER_API_KEY"
)

var (
ErrorGroundcoverEndpointMissing = errors.New("Groundcover is missing a required field (\"GROUNDCOVER_ENDPOINT\"), Groundcover will not be configured")
ErrorGroundcoverApiKeyMissing = errors.New("Groundcover is missing a required field (\"GROUNDCOVER_API_KEY\"), Groundcover will not be configured")
)

type Groundcover struct{}

func (j *Groundcover) DestType() common.DestinationType {
return common.GroundcoverDestinationType
}

func (j *Groundcover) ModifyConfig(dest ExporterConfigurer, currentConfig *Config) error {
config := dest.GetConfig()
uniqueUri := "groundcover-" + dest.GetID()

url, exists := config[GroundcoverEndpoint]
if !exists {
return ErrorGroundcoverEndpointMissing
}

endpoint, err := parseOtlpGrpcUrl(url, true)
if err != nil {
return err
}

exporterName := "otlp/" + uniqueUri
exporterConfig := GenericMap{
"endpoint": endpoint,
"headers": GenericMap{
"apikey": "${GROUNDCOVER_API_KEY}",
},
}

currentConfig.Exporters[exporterName] = exporterConfig

if isTracingEnabled(dest) {
tracesPipelineName := "traces/" + uniqueUri
currentConfig.Service.Pipelines[tracesPipelineName] = Pipeline{
Exporters: []string{exporterName},
}
}

if isMetricsEnabled(dest) {
tracesPipelineName := "metrics/" + uniqueUri
currentConfig.Service.Pipelines[tracesPipelineName] = Pipeline{
Exporters: []string{exporterName},
}
}

if isLoggingEnabled(dest) {
tracesPipelineName := "logs/" + uniqueUri
currentConfig.Service.Pipelines[tracesPipelineName] = Pipeline{
Exporters: []string{exporterName},
}
}

return nil
}
Loading

0 comments on commit ef5bf97

Please sign in to comment.