Skip to content

Commit

Permalink
[GEN-1847]: add AppDynamics as destination (#1905)
Browse files Browse the repository at this point in the history
  • Loading branch information
BenElferink authored Dec 3, 2024
1 parent a53f818 commit 89aa4d0
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 66 deletions.
80 changes: 42 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,44 +82,48 @@ For more details, see our [quickstart guide](https://docs.odigos.io/intro).

**For step-by-step instructions detailed for every destination, see these [docs](https://docs.odigos.io/backends).**

### Managed


| | Traces | Metrics | Logs |
| ------------------------- | -------- | --------- | ------ |
| New Relic ||||
| Datadog ||||
| Grafana Cloud ||||
| Honeycomb ||||
| Chronosphere ||| |
| Logz.io ||||
| qryn.cloud ||||
| OpsVerse ||||
| Dynatrace ||||
| AWS S3 ||||
| Google Cloud Monitoring || ||
| Google Cloud Storage || ||
| Azure Blob Storage || ||
| Splunk || | |
| Lightstep || | |
| Sentry || | |
| Axiom || ||
| Sumo Logic ||||
| Coralogix ||||

### Open Source


| | Traces | Metrics | Logs |
| --------------- | -------- | --------- | ------ |
| Prometheus | || |
| Tempo || | |
| Loki | | ||
| Jaeger || | |
| SigNoz ||||
| qryn ||||
| Elasticsearch || ||
| Quickwit || ||
### 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 ||||

## Self-Hosted (Open Source) Destinations

| Destination | Traces | Metrics | Logs |
|---------------|:------:|:-------:|:----:|
| 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
127 changes: 127 additions & 0 deletions common/config/appdynamics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package config

import (
"errors"
"strings"

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

const (
APPDYNAMICS_APPLICATION_NAME = "APPDYNAMICS_APPLICATION_NAME"
APPDYNAMICS_ACCOUNT_NAME = "APPDYNAMICS_ACCOUNT_NAME"
APPDYNAMICS_ENDPOINT_URL = "APPDYNAMICS_ENDPOINT_URL"
APPDYNAMICS_API_KEY = "APPDYNAMICS_API_KEY"
)

type AppDynamics struct{}

func (m *AppDynamics) DestType() common.DestinationType {
// DestinationType defined in common/dests.go
return common.AppDynamicsDestinationType
}

func (m *AppDynamics) ModifyConfig(dest ExporterConfigurer, currentConfig *Config) error {
config := dest.GetConfig()
uniqueUri := "appdynamics-" + dest.GetID()

endpoint, endpointExists := config[APPDYNAMICS_ENDPOINT_URL]
if !endpointExists {
return errors.New("AppDynamics Endpoint URL (\"APPDYNAMICS_ENDPOINT_URL\") not specified, AppDynamics will not be configured")
}

isHttpEndpoint := strings.HasPrefix(endpoint, "http://")
isHttpsEndpoint := strings.HasPrefix(endpoint, "https://")

if !isHttpEndpoint && !isHttpsEndpoint {
return errors.New("AppDynamics Endpoint URL (\"APPDYNAMICS_ENDPOINT_URL\") malformed, HTTP prefix is required, AppDynamics will not be configured")
}

accountName, accountNameExists := config[APPDYNAMICS_ACCOUNT_NAME]
if !accountNameExists {
return errors.New("AppDynamics Account Name (\"APPDYNAMICS_ACCOUNT_NAME\") not specified, AppDynamics will not be configured")
}

applicationName, applicationNameExists := config[APPDYNAMICS_APPLICATION_NAME]
if !applicationNameExists {
applicationName = "odigos"
}

endpointParts := strings.Split(endpoint, ".")
if len(endpointParts) > 0 {
// Replace the first part of the endpoint with the account name (instead of collecting another input from the user).
// Example:
// endpoint - "https://<something-with-dashes>.saas.appdynamics.com"
// host - "<account-name>.saas.appdynamics.com"
endpointParts[0] = accountName
}
host := strings.Join(endpointParts, ".")

// Create config for exporter

exporterName := "otlphttp/" + uniqueUri
currentConfig.Exporters[exporterName] = GenericMap{
"endpoint": endpoint,
"headers": GenericMap{
"x-api-key": "${APPDYNAMICS_API_KEY}",
},
}

// Create config for processor

processorName := "resource/" + uniqueUri
currentConfig.Processors[processorName] = GenericMap{
"attributes": []GenericMap{
{
// This is required by AppDynamics, without it they will accept the data but not display it.
// This key will be used to identify the cluster in AppDynamics.
"key": "service.namespace",
"value": applicationName,
"action": "insert",
},
{
"key": "appdynamics.controller.account",
"value": accountName,
"action": "insert",
},
{
"key": "appdynamics.controller.host",
"value": host,
"action": "insert",
},
{
"key": "appdynamics.controller.port",
"value": 443,
"action": "insert",
},
},
}

// Apply configs to serivce

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

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

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

return nil
}
2 changes: 1 addition & 1 deletion common/config/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const (
)

var availableConfigers = []Configer{
&Middleware{}, &Honeycomb{}, &GrafanaCloudPrometheus{}, &GrafanaCloudTempo{},
&Middleware{}, &AppDynamics{}, &Honeycomb{}, &GrafanaCloudPrometheus{}, &GrafanaCloudTempo{},
&GrafanaCloudLoki{}, &Datadog{}, &NewRelic{}, &Logzio{}, &Last9{}, &Prometheus{},
&Tempo{}, &Loki{}, &Jaeger{}, &GenericOTLP{}, &OTLPHttp{}, &Elasticsearch{}, &Quickwit{}, &Signoz{}, &Qryn{},
&OpsVerse{}, &Splunk{}, &Lightstep{}, &GoogleCloud{}, &GoogleCloudStorage{}, &Sentry{}, &AzureBlobStorage{},
Expand Down
1 change: 1 addition & 0 deletions common/dests.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package common
type DestinationType string

const (
AppDynamicsDestinationType DestinationType = "appdynamics"
AWSS3DestinationType DestinationType = "s3"
AxiomDestinationType DestinationType = "axiom"
AzureBlobDestinationType DestinationType = "azureblob"
Expand Down
41 changes: 41 additions & 0 deletions destinations/data/appdynamics.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
apiVersion: internal.odigos.io/v1beta1
kind: Destination
metadata:
type: appdynamics
displayName: AppDynamics
category: managed
spec:
image: appdynamics.svg
signals:
traces:
supported: true
metrics:
supported: false
logs:
supported: false
fields:
- name: APPDYNAMICS_APPLICATION_NAME
displayName: Application Name
componentType: input
componentProps:
type: text
required: false
- name: APPDYNAMICS_ACCOUNT_NAME
displayName: Account Name
componentType: input
componentProps:
type: text
required: true
- name: APPDYNAMICS_ENDPOINT_URL
displayName: Endpoint URL
componentType: input
componentProps:
type: text
required: true
- name: APPDYNAMICS_API_KEY
displayName: API Key
componentType: input
secret: true
componentProps:
type: password
required: true
10 changes: 10 additions & 0 deletions destinations/logos/appdynamics.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 36 additions & 26 deletions docs/backends-overview.mdx
Original file line number Diff line number Diff line change
@@ -1,33 +1,43 @@
---
title: "Overview"
title: 'Overview'
---

Odigos has destinations for many observability backends.

| | Traces | Metrics | Logs | Open Source |
| ----------------------- | :---: | :-----: | :--: | :---------: |
| SigNoz |||||
| qryn |||||
| Uptrace |||||
| Elasticsearch || |||
| Jaeger || | ||
| Tempo || | ||
| Prometheus | || ||
| Loki | | |||
| Datadog |||| |
| Grafana Cloud |||| |
| Honeycomb |||| |
| Logz.io |||| |
| New Relic |||| |
| OpsVerse |||| |
| qryn.cloud |||| |
| Causely ||| | |
| AWS S3 || || |
| Azure Blob Storage || || |
| Google Cloud Monitoring || || |
| Google Cloud Storage || || |
| Lightstep || | | |
| Sentry || | | |
| Splunk || | | |
| Destination | Category | Traces | Metrics | Logs |
|-------------------------|------------------|:------:|:-------:|:----:|
| AppDynamics | Managed || | |
| Axiom | Managed || ||
| AWS S3 | Managed || ||
| Azure Blob Storage | Managed || ||
| Causely | Managed || | |
| Chronosphere | Managed ||| |
| ClickHouse | Self-Hosted ||||
| Coralogix | Managed ||||
| Datadog | Managed ||||
| Dynatrace | Managed ||||
| Elasticsearch | Self-Hosted || ||
| Gigapipe | Managed || | |
| Google Cloud Monitoring | Managed ||| |
| Google Cloud Storage | Managed || ||
| Grafana Cloud | Managed ||||
| Honeycomb | Managed ||||
| Jaeger | Self-Hosted || | |
| Last9 | Managed ||| |
| Lightstep | Managed || | |
| Loki | Self-Hosted | | ||
| Logz.io | Managed ||||
| New Relic | Managed ||||
| OpsVerse | Managed ||||
| OTLP | Managed ||||
| OTLP HTTP | Managed ||||
| Prometheus | Self-Hosted | || |
| Quickwit | Self-Hosted || | |
| qryn | Self-Hosted ||||
| Sentry | Managed || | |
| SigNoz | Self-Hosted ||||
| Splunk | Managed || | |
| Sumo Logic | Managed ||||
| Tempo | Self-Hosted || | |

Can't find the destination you need? Help us by following our quick [adding new destination](/adding-new-dest) guide and submit a PR.
Loading

0 comments on commit 89aa4d0

Please sign in to comment.