Skip to content

Commit 01559fb

Browse files
feat: add ability to filter and export markers (#27862)
**Description:** This add logic to filter logs based on log conditions and sent desired logs as event markers to the honeycomb marker api. **Link to tracking Issue:** #27666 **Testing:** Unit testing for log exporter and config. Added component testing to `otelcontribcol`. **Documentation:** README describing component usage Screenshot of exported markers showing up in Honeycomb <img width="1225" alt="Screenshot 2023-11-14 at 1 27 49 PM" src="https://github.com/open-telemetry/opentelemetry-collector-contrib/assets/35741033/128d689a-cf1e-4959-9df3-6c88248a7fdb"> --------- Co-authored-by: Tyler Helmuth <[email protected]>
1 parent c3d4d65 commit 01559fb

File tree

13 files changed

+551
-129
lines changed

13 files changed

+551
-129
lines changed

cmd/otelcontribcol/builder-config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ exporters:
5656
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/googlecloudexporter v0.89.0
5757
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/googlecloudpubsubexporter v0.89.0
5858
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/googlemanagedprometheusexporter v0.89.0
59+
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/honeycombmarkerexporter v0.89.0
5960
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/influxdbexporter v0.89.0
6061
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/instanaexporter v0.89.0
6162
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter v0.89.0
@@ -389,6 +390,7 @@ replaces:
389390
- github.com/open-telemetry/opentelemetry-collector-contrib/receiver/googlecloudpubsubreceiver => ../../receiver/googlecloudpubsubreceiver
390391
- github.com/open-telemetry/opentelemetry-collector-contrib/exporter/sumologicexporter => ../../exporter/sumologicexporter
391392
- github.com/open-telemetry/opentelemetry-collector-contrib/exporter/instanaexporter => ../../exporter/instanaexporter
393+
- github.com/open-telemetry/opentelemetry-collector-contrib/exporter/honeycombmarkerexporter => ../../exporter/honeycombmarkerexporter
392394
- github.com/open-telemetry/opentelemetry-collector-contrib/receiver/otlpjsonfilereceiver => ../../receiver/otlpjsonfilereceiver
393395
- github.com/open-telemetry/opentelemetry-collector-contrib/processor/redactionprocessor => ../../processor/redactionprocessor
394396
- github.com/open-telemetry/opentelemetry-collector-contrib/extension/jaegerremotesampling => ../../extension/jaegerremotesampling

cmd/otelcontribcol/components.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/otelcontribcol/exporters_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import (
4040
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/elasticsearchexporter"
4141
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/f5cloudexporter"
4242
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter"
43+
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/honeycombmarkerexporter"
4344
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/influxdbexporter"
4445
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/instanaexporter"
4546
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter"
@@ -421,6 +422,18 @@ func TestDefaultExporters(t *testing.T) {
421422
exporter: "googlecloudpubsub",
422423
skipLifecycle: true,
423424
},
425+
{
426+
exporter: "honeycombmarker",
427+
getConfigFn: func() component.Config {
428+
cfg := expFactories["honeycombmarker"].CreateDefaultConfig().(*honeycombmarkerexporter.Config)
429+
cfg.Endpoint = "http://" + endpoint
430+
// disable queue to validate passing the test data synchronously
431+
cfg.QueueSettings.Enabled = false
432+
cfg.RetrySettings.Enabled = false
433+
return cfg
434+
},
435+
expectConsumeErr: true,
436+
},
424437
{
425438
exporter: "influxdb",
426439
getConfigFn: func() component.Config {

cmd/otelcontribcol/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ require (
3232
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/googlecloudexporter v0.89.0
3333
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/googlecloudpubsubexporter v0.89.0
3434
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/googlemanagedprometheusexporter v0.89.0
35+
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/honeycombmarkerexporter v0.89.0
3536
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/influxdbexporter v0.89.0
3637
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/instanaexporter v0.89.0
3738
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter v0.89.0
@@ -1082,6 +1083,8 @@ replace github.com/open-telemetry/opentelemetry-collector-contrib/exporter/sumol
10821083

10831084
replace github.com/open-telemetry/opentelemetry-collector-contrib/exporter/instanaexporter => ../../exporter/instanaexporter
10841085

1086+
replace github.com/open-telemetry/opentelemetry-collector-contrib/exporter/honeycombmarkerexporter => ../../exporter/honeycombmarkerexporter
1087+
10851088
replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/otlpjsonfilereceiver => ../../receiver/otlpjsonfilereceiver
10861089

10871090
replace github.com/open-telemetry/opentelemetry-collector-contrib/processor/redactionprocessor => ../../processor/redactionprocessor

exporter/honeycombmarkerexporter/README.md

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,27 @@ This exporter allows creating markers, via the Honeycomb Markers API, based on t
55

66
The following configuration options are supported:
77

8-
* `api_key` (Required): This is the API key (also called Write Key) for your Honeycomb account.
9-
* `api_url` (Required): You can set the hostname to send marker data to.
10-
* `markers` (Required): This specifies the exact configuration to create an event marker.
11-
* `type`: Specifies the marker type. Markers with the same type will appear in the same color in Honeycomb. MarkerType or MarkerColor should be set.
12-
* `color`: Specifies the marker color. Will only be used if MarkerType is not set.
13-
* `messagefield`: This is the attribute that will be used as the message. If necessary the value will be converted to a string.
14-
* `urlfield`: This is the attribute that will be used as the url. If necessary the value will be converted to a string.
15-
* `rules`: This is a list of OTTL rules that determine when to create an event marker.
16-
* `resourceconditions`: A list of ottlresource conditions that determine a match
17-
* `logconditions`: A list of ottllog conditions that determine a match
8+
* `api_key` (Required): This is the API key for your Honeycomb account.
9+
* `api_url` (Required): This sets the hostname to send marker data to.
10+
* `markers` (Required): This is a list of configurations to create an event marker.
11+
* `type` (Required): Specifies the marker type.
12+
* `message_key`: This attribute will be used as the message. It describes the event marker. If necessary the value will be converted to a string.
13+
* `url_key`: This attribute will be used as the url. It can be accessed through the event marker in Honeycomb. If necessary the value will be converted to a string.
14+
* `rules` (Required): This is a list of OTTL rules that determine when to create an event marker.
15+
* `log_conditions` (Required): A list of ottllog conditions that determine a match
1816
Example:
1917

2018
```yaml
2119
exporters:
22-
honeycomb:
23-
api_key: "my-api-key"
24-
api_url: "https://api.testhost.io"
20+
honeycombmarker:
21+
api_key: "environment-api-key"
22+
api_url: "https://api.honeycomb.io"
2523
markers:
26-
- type: "fooType",
27-
messagefield: "test message",
28-
urlfield: "https://api.testhost.io",
24+
- type: "marker-type"
25+
message_key: "marker-message"
26+
url_key: "marker-url"
27+
dataset_slug: "__all__"
2928
rules:
30-
- resourceconditions:
31-
- IsMatch(attributes["test"], ".*")
32-
- logconditions:
33-
- body == "test"
34-
- color: "green",
35-
messagefield: "another test message",
36-
urlfield: "https://api.testhost.io",
37-
rules:
38-
- resourceconditions:
39-
- IsMatch(attributes["test"], ".*")
40-
- logconditions:
29+
- log_conditions:
4130
- body == "test"
4231
```

exporter/honeycombmarkerexporter/config.go

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@ import (
77
"fmt"
88

99
"go.opentelemetry.io/collector/component"
10+
"go.opentelemetry.io/collector/config/confighttp"
1011
"go.opentelemetry.io/collector/config/configopaque"
12+
"go.opentelemetry.io/collector/exporter/exporterhelper"
1113
"go.uber.org/zap"
1214

15+
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter/expr"
1316
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter/filterottl"
1417
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
18+
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/ottllog"
1519
)
1620

1721
// Config defines configuration for the Honeycomb Marker exporter.
@@ -24,58 +28,60 @@ type Config struct {
2428

2529
// Markers is the list of markers to create
2630
Markers []Marker `mapstructure:"markers"`
31+
32+
confighttp.HTTPClientSettings `mapstructure:",squash"`
33+
exporterhelper.QueueSettings `mapstructure:"sending_queue"`
34+
exporterhelper.RetrySettings `mapstructure:"retry_on_failure"`
2735
}
2836

2937
type Marker struct {
30-
// Type defines the type of Marker. Markers with the same type appear in Honeycomb with the same color
38+
// Type defines the type of Marker.
3139
Type string `mapstructure:"type"`
3240

33-
// Color is the color of the Marker. Will only be used if the Type does not already exist.
34-
Color string `mapstructure:"color"`
35-
36-
// MessageField is the attribute that will be used as the message.
41+
// MessageKey is the attribute that will be used as the message.
3742
// If necessary the value will be converted to a string.
38-
MessageField string `mapstructure:"message_field"`
43+
MessageKey string `mapstructure:"message_key"`
3944

40-
// URLField is the attribute that will be used as the url.
45+
// URLKey is the attribute that will be used as the url.
4146
// If necessary the value will be converted to a string.
42-
URLField string `mapstructure:"url_field"`
47+
URLKey string `mapstructure:"url_key"`
4348

4449
// Rules are the OTTL rules that determine when a piece of telemetry should be turned into a Marker
4550
Rules Rules `mapstructure:"rules"`
51+
52+
// DatasetSlug is the endpoint that specifies the Honeycomb environment
53+
DatasetSlug string `mapstructure:"dataset_slug"`
4654
}
4755

4856
type Rules struct {
49-
// ResourceConditions is the list of ottlresource conditions that determine a match
50-
ResourceConditions []string `mapstructure:"resource_conditions"`
51-
5257
// LogConditions is the list of ottllog conditions that determine a match
5358
LogConditions []string `mapstructure:"log_conditions"`
59+
60+
logBoolExpr expr.BoolExpr[ottllog.TransformContext]
5461
}
5562

56-
var defaultCfg = createDefaultConfig().(*Config)
63+
var _ component.Config = (*Config)(nil)
5764

5865
func (cfg *Config) Validate() error {
59-
if cfg == nil {
60-
cfg = defaultCfg
61-
}
62-
6366
if cfg.APIKey == "" {
6467
return fmt.Errorf("invalid API Key")
6568
}
6669

6770
if len(cfg.Markers) != 0 {
6871
for _, m := range cfg.Markers {
69-
if len(m.Rules.ResourceConditions) == 0 && len(m.Rules.LogConditions) == 0 {
70-
return fmt.Errorf("no rules supplied for Marker %v", m)
72+
if m.Type == "" {
73+
return fmt.Errorf("marker must have a type %v", m)
7174
}
7275

73-
_, err := filterottl.NewBoolExprForResource(m.Rules.ResourceConditions, filterottl.StandardResourceFuncs(), ottl.PropagateError, component.TelemetrySettings{Logger: zap.NewNop()})
74-
if err != nil {
75-
return err
76+
if m.DatasetSlug == "" {
77+
return fmt.Errorf("marker must have a dataset slug %v", m)
78+
}
79+
80+
if len(m.Rules.LogConditions) == 0 {
81+
return fmt.Errorf("marker must have rules %v", m)
7682
}
7783

78-
_, err = filterottl.NewBoolExprForLog(m.Rules.LogConditions, filterottl.StandardLogFuncs(), ottl.PropagateError, component.TelemetrySettings{Logger: zap.NewNop()})
84+
_, err := filterottl.NewBoolExprForLog(m.Rules.LogConditions, filterottl.StandardLogFuncs(), ottl.PropagateError, component.TelemetrySettings{Logger: zap.NewNop()})
7985
if err != nil {
8086
return err
8187
}

exporter/honeycombmarkerexporter/config_test.go

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/stretchr/testify/require"
1212
"go.opentelemetry.io/collector/component"
1313
"go.opentelemetry.io/collector/confmap/confmaptest"
14+
"go.opentelemetry.io/collector/exporter/exporterhelper"
1415

1516
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/honeycombmarkerexporter/internal/metadata"
1617
)
@@ -26,45 +27,23 @@ func TestLoadConfig(t *testing.T) {
2627
expected component.Config
2728
}{
2829
{
29-
id: component.NewIDWithName("honeycomb", ""),
30+
id: component.NewIDWithName(metadata.Type, ""),
3031
expected: &Config{
31-
APIKey: "test-apikey",
32-
APIURL: "https://api.testhost.io",
32+
QueueSettings: exporterhelper.NewDefaultQueueSettings(),
33+
RetrySettings: exporterhelper.NewDefaultRetrySettings(),
34+
APIKey: "test-apikey",
35+
APIURL: "https://api.testhost.io",
3336
Markers: []Marker{
3437
{
35-
Type: "fooType",
36-
MessageField: "test message",
37-
URLField: "https://api.testhost.io",
38+
Type: "fooType",
39+
MessageKey: "test message",
40+
URLKey: "https://api.testhost.io",
3841
Rules: Rules{
39-
ResourceConditions: []string{
40-
`IsMatch(attributes["test"], ".*")`,
41-
},
42-
LogConditions: []string{
43-
`body == "test"`,
44-
},
45-
},
46-
},
47-
},
48-
},
49-
},
50-
{
51-
id: component.NewIDWithName("honeycomb", "color_no_type"),
52-
expected: &Config{
53-
APIKey: "test-apikey",
54-
APIURL: "https://api.testhost.io",
55-
Markers: []Marker{
56-
{
57-
Color: "green",
58-
MessageField: "test message",
59-
URLField: "https://api.testhost.io",
60-
Rules: Rules{
61-
ResourceConditions: []string{
62-
`IsMatch(attributes["test"], ".*")`,
63-
},
6442
LogConditions: []string{
6543
`body == "test"`,
6644
},
6745
},
46+
DatasetSlug: "__all__",
6847
},
6948
},
7049
},
@@ -81,6 +60,9 @@ func TestLoadConfig(t *testing.T) {
8160
{
8261
id: component.NewIDWithName(metadata.Type, "no_markers_supplied"),
8362
},
63+
{
64+
id: component.NewIDWithName(metadata.Type, "no_dataset_slug"),
65+
},
8466
}
8567

8668
for _, tt := range tests {

exporter/honeycombmarkerexporter/factory.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,19 @@ func createLogsExporter(
3636
) (exporter.Logs, error) {
3737
cf := cfg.(*Config)
3838

39-
exporter := newLogsExporter(set.Logger, cf)
39+
logsExp, err := newHoneycombLogsExporter(set.TelemetrySettings, cf)
40+
if err != nil {
41+
return nil, err
42+
}
4043

4144
return exporterhelper.NewLogsExporter(
4245
ctx,
4346
set,
4447
cfg,
45-
exporter.exportLogs,
48+
logsExp.exportMarkers,
49+
exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}),
50+
exporterhelper.WithRetry(cf.RetrySettings),
51+
exporterhelper.WithQueue(cf.QueueSettings),
52+
exporterhelper.WithStart(logsExp.start),
4653
)
4754
}

exporter/honeycombmarkerexporter/go.mod

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.89.0
88
github.com/stretchr/testify v1.8.4
99
go.opentelemetry.io/collector/component v0.89.0
10+
go.opentelemetry.io/collector/config/confighttp v0.89.0
1011
go.opentelemetry.io/collector/config/configopaque v0.89.0
1112
go.opentelemetry.io/collector/confmap v0.89.0
1213
go.opentelemetry.io/collector/exporter v0.89.0
@@ -18,14 +19,20 @@ require (
1819
github.com/alecthomas/participle/v2 v2.1.0 // indirect
1920
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
2021
github.com/davecgh/go-spew v1.1.1 // indirect
22+
github.com/felixge/httpsnoop v1.0.3 // indirect
23+
github.com/fsnotify/fsnotify v1.7.0 // indirect
24+
github.com/go-logr/logr v1.3.0 // indirect
25+
github.com/go-logr/stdr v1.2.2 // indirect
2126
github.com/gobwas/glob v0.2.3 // indirect
2227
github.com/gogo/protobuf v1.3.2 // indirect
2328
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
2429
github.com/golang/protobuf v1.5.3 // indirect
30+
github.com/golang/snappy v0.0.4 // indirect
2531
github.com/google/uuid v1.4.0 // indirect
2632
github.com/hashicorp/go-version v1.6.0 // indirect
2733
github.com/iancoleman/strcase v0.3.0 // indirect
2834
github.com/json-iterator/go v1.1.12 // indirect
35+
github.com/klauspost/compress v1.17.2 // indirect
2936
github.com/knadh/koanf/maps v0.1.1 // indirect
3037
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
3138
github.com/knadh/koanf/v2 v2.0.1 // indirect
@@ -36,13 +43,20 @@ require (
3643
github.com/modern-go/reflect2 v1.0.2 // indirect
3744
github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.89.0 // indirect
3845
github.com/pmezard/go-difflib v1.0.0 // indirect
46+
github.com/rs/cors v1.10.1 // indirect
3947
go.opencensus.io v0.24.0 // indirect
4048
go.opentelemetry.io/collector v0.89.0 // indirect
49+
go.opentelemetry.io/collector/config/configauth v0.89.0 // indirect
50+
go.opentelemetry.io/collector/config/configcompression v0.89.0 // indirect
4151
go.opentelemetry.io/collector/config/configtelemetry v0.89.0 // indirect
52+
go.opentelemetry.io/collector/config/configtls v0.89.0 // indirect
53+
go.opentelemetry.io/collector/config/internal v0.89.0 // indirect
4254
go.opentelemetry.io/collector/consumer v0.89.0 // indirect
4355
go.opentelemetry.io/collector/extension v0.89.0 // indirect
56+
go.opentelemetry.io/collector/extension/auth v0.89.0 // indirect
4457
go.opentelemetry.io/collector/featuregate v1.0.0-rcv0018 // indirect
4558
go.opentelemetry.io/collector/receiver v0.89.0 // indirect
59+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect
4660
go.opentelemetry.io/otel v1.20.0 // indirect
4761
go.opentelemetry.io/otel/metric v1.20.0 // indirect
4862
go.opentelemetry.io/otel/trace v1.20.0 // indirect

0 commit comments

Comments
 (0)