Skip to content

Commit

Permalink
New otelcol.exporter.debug component (#5867)
Browse files Browse the repository at this point in the history
New otelcol.exporter.debug component.

---------

Co-authored-by: Paulin Todev <paulin.todev@gmail.com>
  • Loading branch information
BarunKGP and ptodev committed Jun 13, 2024
1 parent 584f497 commit e152752
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ internal API changes are not present.
Main (unreleased)
-----------------

### Features

- A new `otelcol.exporter.debug` component for printing OTel telemetry from
other `otelcol` components to the console. (@BarunKGP)

v0.41.1 (2024-06-07)
--------------------

Expand Down
1 change: 1 addition & 0 deletions docs/sources/flow/reference/compatibility/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ The following components, grouped by namespace, _export_ OpenTelemetry `otelcol.
- [otelcol.connector.servicegraph](../components/otelcol.connector.servicegraph)
- [otelcol.connector.spanlogs](../components/otelcol.connector.spanlogs)
- [otelcol.connector.spanmetrics](../components/otelcol.connector.spanmetrics)
- [otelcol.exporter.debug](../components/otelcol.exporter.debug)
- [otelcol.exporter.loadbalancing](../components/otelcol.exporter.loadbalancing)
- [otelcol.exporter.logging](../components/otelcol.exporter.logging)
- [otelcol.exporter.loki](../components/otelcol.exporter.loki)
Expand Down
102 changes: 102 additions & 0 deletions docs/sources/flow/reference/components/otelcol.exporter.debug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
aliases:
- /docs/grafana-cloud/agent/flow/reference/components/otelcol.exporter.debug/
- /docs/grafana-cloud/monitor-infrastructure/agent/flow/reference/components/otelcol.exporter.debug/
- /docs/grafana-cloud/monitor-infrastructure/integrations/agent/flow/reference/components/otelcol.exporter.debug/
- /docs/grafana-cloud/send-data/agent/flow/reference/components/otelcol.exporter.debug/
canonical: https://grafana.com/docs/agent/latest/flow/reference/components/otelcol.exporter.debug/
description: Learn about otelcol.exporter.debug
labels:
stage: experimental
title: otelcol.exporter.debug
---

# otelcol.exporter.debug

`otelcol.exporter.debug` accepts telemetry data from other `otelcol` components and writes them to the console (stderr).
You can control the verbosity of the logs.

{{< admonition type="note" >}}
`otelcol.exporter.debug` is a wrapper over the upstream OpenTelemetry Collector `debug` exporter.
If necessary, bug reports or feature requests are redirected to the upstream repository.
{{< /admonition >}}

Multiple `otelcol.exporter.debug` components can be specified by giving them different labels.

## Usage

```river
otelcol.exporter.debug "LABEL" { }
```

## Arguments

`otelcol.exporter.debug` supports the following arguments:

Name | Type | Description | Default | Required
---- | ---- | ----------- | ------- | --------
`verbosity` | `string` | Verbosity of the generated logs. | `"normal"` | no
`sampling_initial` | `int` | Number of messages initially logged each second. | `2` | no
`sampling_thereafter` | `int` | Sampling rate after the initial messages are logged. | `500` | no

The `verbosity` argument must be one of `"basic"`, `"normal"`, or `"detailed"`.

## Exported fields

The following fields are exported and can be referenced by other components:

Name | Type | Description
---- | ---- | -----------
`input` | `otelcol.Consumer` | A value that other components can use to send telemetry data to.

`input` accepts `otelcol.Consumer` data for any telemetry signal (metrics,
logs, or traces).

## Component health

`otelcol.exporter.debug` is only reported as unhealthy if given an invalid
configuration.

## Debug information

`otelcol.exporter.debug` does not expose any component-specific debug
information.

## Example

This example scrapes Prometheus UNIX metrics and writes them to the console:

```river
prometheus.exporter.unix "default" { }
prometheus.scrape "default" {
targets = prometheus.exporter.unix.default.targets
forward_to = [otelcol.receiver.prometheus.default.receiver]
}
otelcol.receiver.prometheus "default" {
output {
metrics = [otelcol.exporter.debug.default.input]
}
}
otelcol.exporter.debug "default" {
verbosity = "detailed"
sampling_initial = 1
sampling_thereafter = 1
}
```
<!-- START GENERATED COMPATIBLE COMPONENTS -->

## Compatible components

`otelcol.exporter.debug` has exports that can be consumed by the following components:

- Components that consume [OpenTelemetry `otelcol.Consumer`](../../compatibility/#opentelemetry-otelcolconsumer-consumers)

{{< admonition type="note" >}}
Connecting some components may not be sensible or components may require further configuration to make the connection work correctly.
Refer to the linked documentation for more details.
{{< /admonition >}}

<!-- END GENERATED COMPATIBLE COMPONENTS -->
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ require (
go.opentelemetry.io/collector/confmap/converter/expandconverter v0.96.0
go.opentelemetry.io/collector/confmap/provider/fileprovider v0.96.0
go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.96.0
go.opentelemetry.io/collector/exporter/debugexporter v0.96.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0
golang.org/x/crypto/x509roots/fallback v0.0.0-20240208163226-62c9f1799c91
k8s.io/apimachinery v0.29.2
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2348,6 +2348,8 @@ go.opentelemetry.io/collector/consumer v0.96.0 h1:JN4JHelp5EGMGoC2UVelTMG6hyZjgt
go.opentelemetry.io/collector/consumer v0.96.0/go.mod h1:Vn+qzzKgekDFayCVV8peSH5Btx1xrt/bmzD9gTxgidQ=
go.opentelemetry.io/collector/exporter v0.96.0 h1:SmOSaP+zUNq0nl+BcllsCSsYePdUNIIUfW5sXKKaUlI=
go.opentelemetry.io/collector/exporter v0.96.0/go.mod h1:DcuGaxcINhOV2LgojDI56r3830cUtuCsNadINMIU23c=
go.opentelemetry.io/collector/exporter/debugexporter v0.96.0 h1:88v2GWCIuYgd3e4KdwF0JLklIgBzETBw0e3dkEJ7BbI=
go.opentelemetry.io/collector/exporter/debugexporter v0.96.0/go.mod h1:mZjJ0G6Pn6aSS7T4UeEjXSHt3pgslvaZa/4Uam8DKuo=
go.opentelemetry.io/collector/exporter/loggingexporter v0.96.0 h1:fKHt4iTcD7C0utDzeww6ZYVlDYaC0dw9wtzVwLha4CM=
go.opentelemetry.io/collector/exporter/loggingexporter v0.96.0/go.mod h1:vpuKdiIQ6yjwZbKiiAs/MV8rZMKiQfPF55vX8UxO8fk=
go.opentelemetry.io/collector/exporter/otlpexporter v0.96.0 h1:vZEd10B/zj7WkBWSVegDkGOwv7FZhUwyk60E2zkYwL4=
Expand Down
1 change: 1 addition & 0 deletions internal/component/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import (
_ "github.com/grafana/agent/internal/component/otelcol/connector/servicegraph" // Import otelcol.connector.servicegraph
_ "github.com/grafana/agent/internal/component/otelcol/connector/spanlogs" // Import otelcol.connector.spanlogs
_ "github.com/grafana/agent/internal/component/otelcol/connector/spanmetrics" // Import otelcol.connector.spanmetrics
_ "github.com/grafana/agent/internal/component/otelcol/exporter/debug" // Import otelcol.exporter.debug
_ "github.com/grafana/agent/internal/component/otelcol/exporter/loadbalancing" // Import otelcol.exporter.loadbalancing
_ "github.com/grafana/agent/internal/component/otelcol/exporter/logging" // Import otelcol.exporter.logging
_ "github.com/grafana/agent/internal/component/otelcol/exporter/loki" // Import otelcol.exporter.loki
Expand Down
96 changes: 96 additions & 0 deletions internal/component/otelcol/exporter/debug/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package debug

import (
"fmt"

"github.com/grafana/agent/internal/component"
"github.com/grafana/agent/internal/component/otelcol"
"github.com/grafana/agent/internal/component/otelcol/exporter"
"github.com/grafana/agent/internal/featuregate"
otelcomponent "go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config/configtelemetry"
debugexporter "go.opentelemetry.io/collector/exporter/debugexporter"
otelextension "go.opentelemetry.io/collector/extension"
)

func init() {
component.Register(component.Registration{
Name: "otelcol.exporter.debug",
Args: Arguments{},
Exports: otelcol.ConsumerExports{},
Stability: featuregate.StabilityExperimental,

Build: func(opts component.Options, args component.Arguments) (component.Component, error) {
fact := debugexporter.NewFactory()
return exporter.New(opts, fact, args.(Arguments), exporter.TypeAll)
},
})
}

type Arguments struct {
Verbosity string `river:"verbosity,attr,optional"`
SamplingInitial int `river:"sampling_initial,attr,optional"`
SamplingThereafter int `river:"sampling_thereafter,attr,optional"`
}

func (args Arguments) convertVerbosity() (configtelemetry.Level, error) {
var verbosity configtelemetry.Level
switch args.Verbosity {
case "basic":
verbosity = configtelemetry.LevelBasic
case "normal":
verbosity = configtelemetry.LevelNormal
case "detailed":
verbosity = configtelemetry.LevelDetailed
default:
// Invalid verbosity
// debugexporter only supports basic, normal and detailed levels
return verbosity, fmt.Errorf("invalid verbosity %q", args.Verbosity)
}

return verbosity, nil
}

var _ exporter.Arguments = Arguments{}

// DefaultArguments holds default values for Arguments.
var DefaultArguments = Arguments{
Verbosity: "normal",
SamplingInitial: 2,
SamplingThereafter: 500,
}

// SetToDefault implements river.Defaulter.
func (args *Arguments) SetToDefault() {
*args = DefaultArguments
}

// Convert implements exporter.Arguments.
func (args Arguments) Convert() (otelcomponent.Config, error) {
verbosity, err := args.convertVerbosity()
if err != nil {
return nil, fmt.Errorf("error in conversion to config arguments, %v", err)
}

return &debugexporter.Config{
Verbosity: verbosity,
SamplingInitial: args.SamplingInitial,
SamplingThereafter: args.SamplingThereafter,
}, nil
}

// Extensions implements exporter.Arguments.
func (args Arguments) Extensions() map[otelcomponent.ID]otelextension.Extension {
return nil
}

// Exporters implements exporter.Arguments.
func (args Arguments) Exporters() map[otelcomponent.DataType]map[otelcomponent.ID]otelcomponent.Component {
return nil
}

// DebugMetricsConfig implements receiver.Arguments.
func (args Arguments) DebugMetricsConfig() otelcol.DebugMetricsArguments {
var debugMetrics otelcol.DebugMetricsArguments
return debugMetrics
}
79 changes: 79 additions & 0 deletions internal/component/otelcol/exporter/debug/debug_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package debug_test

import (
"fmt"
"testing"

"github.com/grafana/agent/internal/component/otelcol/exporter/debug"
"github.com/grafana/river"
"github.com/stretchr/testify/require"
otelcomponent "go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config/configtelemetry"
debugexporter "go.opentelemetry.io/collector/exporter/debugexporter"
)

func Test(t *testing.T) {
tests := []struct {
testName string
args string
expectedReturn debugexporter.Config
errorMsg string
}{
{
testName: "defaultConfig",
args: ``,
expectedReturn: debugexporter.Config{
Verbosity: configtelemetry.LevelNormal,
SamplingInitial: 2,
SamplingThereafter: 500,
},
},

{
testName: "validConfig",
args: `
verbosity = "detailed"
sampling_initial = 5
sampling_thereafter = 20
`,
expectedReturn: debugexporter.Config{
Verbosity: configtelemetry.LevelDetailed,
SamplingInitial: 5,
SamplingThereafter: 20,
},
},

{
testName: "invalidConfig",
args: `
verbosity = "test"
sampling_initial = 5
sampling_thereafter = 20
`,
errorMsg: "error in conversion to config arguments",
},
}

for _, tc := range tests {
t.Run(tc.testName, func(t *testing.T) {
var args debug.Arguments
err := river.Unmarshal([]byte(tc.args), &args)
require.NoError(t, err)

actualPtr, err := args.Convert()
if tc.errorMsg != "" {
require.ErrorContains(t, err, tc.errorMsg)
return
}

require.NoError(t, err)

actual := actualPtr.(*debugexporter.Config)
fmt.Printf("Passed conversion")

require.NoError(t, otelcomponent.ValidateConfig(actual))

require.Equal(t, tc.expectedReturn, *actual)
})
}
}

0 comments on commit e152752

Please sign in to comment.