Skip to content

Commit

Permalink
[exporter/awsemf] Fix possible panic when using stdout output_destina…
Browse files Browse the repository at this point in the history
…tion (#26250)

**Description:** It is possible for the awsemf exporter to panic when
using the `awsemf.output_destination:stdout` configuration option. I was
not able to replicate this in the unit tests. I tried several different
metric setups but was not able to find a configuration that caused the
translations to to result in a nil message body.

After reviewing the translation code I found one possible area where an
error was not being returned and a nil `cwlogs.Event` object was
returned. I have updated that function signature to return an error in
the case where a json marshal error occurs also.

**Link to tracking Issue:** none. See stack trace below
```
2023-08-25 16:00:06 panic: runtime error: invalid memory address or nil pointer dereference
2023-08-25 16:00:06 [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x13765d7]
2023-08-25 16:00:06 
2023-08-25 16:00:06 goroutine 74 [running]:
2023-08-25 16:00:06 github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsemfexporter.(*emfExporter).pushMetricsData(0xc000e50000, {0xc00061d4b0?, 0x53794a?}, {0x4de5a20?})
2023-08-25 16:00:06     github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsemfexporter@v0.82.0/emf_exporter.go:108 +0x417
2023-08-25 16:00:06 go.opentelemetry.io/collector/exporter/exporterhelper.(*metricsRequest).Export(0x4de5a20?, {0x4de59e8?, 0xc00089fb90?})
2023-08-25 16:00:06     go.opentelemetry.io/collector/exporter@v0.82.0/exporterhelper/metrics.go:54 +0x34
2023-08-25 16:00:06 go.opentelemetry.io/collector/exporter/exporterhelper.(*timeoutSender).send(0xc0008ea428, {0x4df9778, 0xc00089fa40})
2023-08-25 16:00:06     go.opentelemetry.io/collector/exporter@v0.82.0/exporterhelper/common.go:197 +0x96
2023-08-25 16:00:06 go.opentelemetry.io/collector/exporter/exporterhelper.(*retrySender).send(0xc0007ee640, {0x4df9778?, 0xc00089fa40?})
2023-08-25 16:00:06     go.opentelemetry.io/collector/exporter@v0.82.0/exporterhelper/queued_retry.go:355 +0x190
2023-08-25 16:00:06 go.opentelemetry.io/collector/exporter/exporterhelper.(*metricsSenderWithObservability).send(0xc000ae50c8, {0x4df9778, 0xc00089fa40})
2023-08-25 16:00:06     go.opentelemetry.io/collector/exporter@v0.82.0/exporterhelper/metrics.go:125 +0x88
2023-08-25 16:00:06 go.opentelemetry.io/collector/exporter/exporterhelper.(*queuedRetrySender).send(0xc000315880, {0x4df9778, 0xc00089fa40})
2023-08-25 16:00:06     go.opentelemetry.io/collector/exporter@v0.82.0/exporterhelper/queued_retry.go:291 +0x44c
2023-08-25 16:00:06 go.opentelemetry.io/collector/exporter/exporterhelper.NewMetricsExporter.func2({0x4de5a20?, 0xc000e4a5a0}, {0xc000118570?})
2023-08-25 16:00:06     go.opentelemetry.io/collector/exporter@v0.82.0/exporterhelper/metrics.go:105 +0xca
2023-08-25 16:00:06 go.opentelemetry.io/collector/consumer.ConsumeMetricsFunc.ConsumeMetrics(...)
2023-08-25 16:00:06     go.opentelemetry.io/collector/consumer@v0.82.0/metrics.go:25
2023-08-25 16:00:06 go.opentelemetry.io/collector/internal/fanoutconsumer.(*metricsConsumer).ConsumeMetrics(0xc000e4a4e0, {0x4de5a20, 0xc000e4a5a0}, {0x0?})
2023-08-25 16:00:06     go.opentelemetry.io/collector@v0.82.0/internal/fanoutconsumer/metrics.go:69 +0x147
2023-08-25 16:00:06 go.opentelemetry.io/collector/processor/batchprocessor.(*batchMetrics).export(0xc000e4a5d0, {0x4de5a20, 0xc000e4a5a0}, 0x2?, 0x1)
2023-08-25 16:00:06     go.opentelemetry.io/collector/processor/batchprocessor@v0.82.0/batch_processor.go:442 +0x117
2023-08-25 16:00:06 go.opentelemetry.io/collector/processor/batchprocessor.(*shard).sendItems(0xc000e50480, 0xc00011873c?)
2023-08-25 16:00:06     go.opentelemetry.io/collector/processor/batchprocessor@v0.82.0/batch_processor.go:256 +0x5f
2023-08-25 16:00:06 go.opentelemetry.io/collector/processor/batchprocessor.(*shard).start(0xc000e50480)
2023-08-25 16:00:06     go.opentelemetry.io/collector/processor/batchprocessor@v0.82.0/batch_processor.go:218 +0x1bc
2023-08-25 16:00:06 created by go.opentelemetry.io/collector/processor/batchprocessor.(*batchProcessor).newShard
2023-08-25 16:00:06     go.opentelemetry.io/collector/processor/batchprocessor@v0.82.0/batch_processor.go:160 +0x1cb
```
  • Loading branch information
bryan-aguilar authored Sep 7, 2023
1 parent b056ac2 commit d722dae
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 7 deletions.
27 changes: 27 additions & 0 deletions .chloggen/awsemf_stdoutpanic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: bug_fix

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

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Fix possible panic in when configuration option `awsemf.output_destination:stdout` is set

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [26250]

# (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:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
11 changes: 9 additions & 2 deletions exporter/awsemfexporter/emf_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,17 @@ func (emf *emfExporter) pushMetricsData(_ context.Context, md pmetric.Metrics) e

for _, groupedMetric := range groupedMetrics {
cWMetric := translateGroupedMetricToCWMetric(groupedMetric, emf.config)
putLogEvent := translateCWMetricToEMF(cWMetric, emf.config)
putLogEvent, err := translateCWMetricToEMF(cWMetric, emf.config)
if err != nil {
return err
}
// Currently we only support two options for "OutputDestination".
if strings.EqualFold(outputDestination, outputDestinationStdout) {
fmt.Println(*putLogEvent.InputLogEvent.Message)
if putLogEvent != nil &&
putLogEvent.InputLogEvent != nil &&
putLogEvent.InputLogEvent.Message != nil {
fmt.Println(*putLogEvent.InputLogEvent.Message)
}
} else if strings.EqualFold(outputDestination, outputDestinationCloudWatch) {
logGroup := groupedMetric.metadata.logGroup
logStream := groupedMetric.metadata.logStream
Expand Down
6 changes: 3 additions & 3 deletions exporter/awsemfexporter/metric_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ func groupedMetricToCWMeasurementsWithFilters(groupedMetric *groupedMetric, conf
}

// translateCWMetricToEMF converts CloudWatch Metric format to EMF.
func translateCWMetricToEMF(cWMetric *cWMetrics, config *Config) *cwlogs.Event {
func translateCWMetricToEMF(cWMetric *cWMetrics, config *Config) (*cwlogs.Event, error) {
// convert CWMetric into map format for compatible with PLE input
fieldMap := cWMetric.fields

Expand Down Expand Up @@ -433,7 +433,7 @@ func translateCWMetricToEMF(cWMetric *cWMetrics, config *Config) *cwlogs.Event {

pleMsg, err := json.Marshal(fieldMap)
if err != nil {
return nil
return nil, err
}

metricCreationTime := cWMetric.timestampMs
Expand All @@ -443,5 +443,5 @@ func translateCWMetricToEMF(cWMetric *cWMetrics, config *Config) *cwlogs.Event {
)
logEvent.GeneratedTime = time.Unix(0, metricCreationTime*int64(time.Millisecond))

return logEvent
return logEvent, nil
}
6 changes: 4 additions & 2 deletions exporter/awsemfexporter/metric_translator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,8 @@ func TestTranslateCWMetricToEMF(t *testing.T) {
measurements: tc.measurements,
}

emfLogEvent := translateCWMetricToEMF(cloudwatchMetric, config)
emfLogEvent, err := translateCWMetricToEMF(cloudwatchMetric, config)
require.NoError(t, err)

assert.Equal(t, tc.expectedEMFLogEvent, *emfLogEvent.InputLogEvent.Message)
})
Expand Down Expand Up @@ -2174,7 +2175,8 @@ func BenchmarkTranslateCWMetricToEMF(b *testing.B) {

b.ResetTimer()
for n := 0; n < b.N; n++ {
translateCWMetricToEMF(met, &Config{})
_, err := translateCWMetricToEMF(met, &Config{})
require.NoError(b, err)
}
}

Expand Down

0 comments on commit d722dae

Please sign in to comment.