Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[exporter/azuremonitor] Add metrics support #14916

Merged
16 changes: 16 additions & 0 deletions .chloggen/azuremonitorexporter-metrics.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: azuremonitorexporter

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Adds metrics exporting

# One or more tracking issues related to the change
issues: [14915]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:
26 changes: 15 additions & 11 deletions exporter/azuremonitorexporter/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Azure Monitor Exporter

| Status | |
|--------------------------|--------------|
| Stability | [beta] |
| Supported pipeline types | logs, traces |
| Distributions | [contrib] |
| Status | |
|--------------------------|-----------------------|
| Stability | [beta] |
| Supported pipeline types | logs, traces, metrics |
| Distributions | [contrib] |

This exporter sends logs and trace data to [Azure Monitor](https://docs.microsoft.com/azure/azure-monitor/).
This exporter sends logs, traces and metrics to [Azure Monitor](https://docs.microsoft.com/azure/azure-monitor/).

## Configuration

Expand Down Expand Up @@ -62,15 +62,19 @@ The exact mapping can be found [here](trace_to_envelope.go).

All attributes are also mapped to custom properties if they are booleans or strings and to custom measurements if they are ints or doubles.

#### Span Events

Span events are optionally saved to the Application Insights `traces` table.
Exception events are saved to the Application Insights `exception` table.

### Logs

This exporter saves log records to Application Insights `traces` table.
[TraceId](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-traceid) is mapped to `operation_id` column and [SpanId](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-spanid) is mapped to `operation_parentId` column.

[beta]:https://github.com/open-telemetry/opentelemetry-collector#beta
[contrib]:https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib
### Metrics

### Span Events
This exporter saves metrics to Application Insights `customMetrics` table.

Span events are optionally saved to the Application Insights `traces` table.
Exception events are saved to the Application Insights `exception` table.
[beta]:https://github.com/open-telemetry/opentelemetry-collector#beta
[contrib]:https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib
66 changes: 66 additions & 0 deletions exporter/azuremonitorexporter/contracts_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 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 azuremonitorexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/azuremonitorexporter"

import (
"github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
"go.opentelemetry.io/collector/pdata/pcommon" // Applies resource attributes values to data properties
conventions "go.opentelemetry.io/collector/semconv/v1.6.1"
)

const (
instrumentationLibraryName string = "instrumentationlibrary.name"
instrumentationLibraryVersion string = "instrumentationlibrary.version"
)

// Applies resource attributes values to data properties
func applyResourcesToDataProperties(dataProperties map[string]string, resourceAttributes pcommon.Map) {
// Copy all the resource labels into the base data properties. Resource values are always strings
resourceAttributes.Range(func(k string, v pcommon.Value) bool {
dataProperties[k] = v.Str()
return true
})
}

// Sets important ai.cloud.* tags on the envelope
func applyCloudTagsToEnvelope(envelope *contracts.Envelope, resourceAttributes pcommon.Map) {
// Extract key service.* labels from the Resource labels and construct CloudRole and CloudRoleInstance envelope tags
// https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/resource/semantic_conventions
if serviceName, serviceNameExists := resourceAttributes.Get(conventions.AttributeServiceName); serviceNameExists {
cloudRole := serviceName.Str()

if serviceNamespace, serviceNamespaceExists := resourceAttributes.Get(conventions.AttributeServiceNamespace); serviceNamespaceExists {
cloudRole = serviceNamespace.Str() + "." + cloudRole
}

envelope.Tags[contracts.CloudRole] = cloudRole
}

if serviceInstance, exists := resourceAttributes.Get(conventions.AttributeServiceInstanceID); exists {
envelope.Tags[contracts.CloudRoleInstance] = serviceInstance.Str()
}
}

// Applies instrumentation values to data properties
func applyInstrumentationScopeValueToDataProperties(dataProperties map[string]string, instrumentationScope pcommon.InstrumentationScope) {
// Copy the instrumentation properties
if instrumentationScope.Name() != "" {
dataProperties[instrumentationLibraryName] = instrumentationScope.Name()
}

if instrumentationScope.Version() != "" {
dataProperties[instrumentationLibraryVersion] = instrumentationScope.Version()
}
}
18 changes: 17 additions & 1 deletion exporter/azuremonitorexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ func NewFactory() exporter.Factory {
typeStr,
createDefaultConfig,
exporter.WithTraces(f.createTracesExporter, stability),
exporter.WithLogs(f.createLogsExporter, stability))
exporter.WithLogs(f.createLogsExporter, stability),
exporter.WithMetrics(f.createMetricsExporter, stability))
}

// Implements the interface from go.opentelemetry.io/collector/exporter/factory.go
Expand Down Expand Up @@ -91,6 +92,21 @@ func (f *factory) createLogsExporter(
return newLogsExporter(exporterConfig, tc, set)
}

func (f *factory) createMetricsExporter(
ctx context.Context,
set exporter.CreateSettings,
cfg component.Config,
) (exporter.Metrics, error) {
exporterConfig, ok := cfg.(*Config)

if !ok {
return nil, errUnexpectedConfigurationType
}

tc := f.getTransportChannel(exporterConfig, set.Logger)
return newMetricsExporter(exporterConfig, tc, set)
}

// Configures the transport channel.
// This method is not thread-safe
func (f *factory) getTransportChannel(exporterConfig *Config, logger *zap.Logger) transportChannel {
Expand Down
3 changes: 2 additions & 1 deletion exporter/azuremonitorexporter/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require (
)

require (
code.cloudfoundry.org/clock v1.0.0 // indirect
code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c // indirect
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gofrs/uuid v4.0.0+incompatible // indirect
Expand All @@ -31,6 +31,7 @@ require (
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.6.1 // indirect
github.com/stretchr/objx v0.5.0 // indirect
Expand Down
6 changes: 3 additions & 3 deletions exporter/azuremonitorexporter/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading