diff --git a/.chloggen/36650.yaml b/.chloggen/36650.yaml index f138f41d3f23..5d9f53e4c088 100644 --- a/.chloggen/36650.yaml +++ b/.chloggen/36650.yaml @@ -1,7 +1,7 @@ # Use this changelog template to create an entry for release notes. # One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' -change_type: bug_fix +change_type: enhancement # The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) component: azureeventhubreceiver diff --git a/pkg/translator/azure/resourcelogs_to_logs.go b/pkg/translator/azure/resourcelogs_to_logs.go index ffda42034ec6..008c30fc59e9 100644 --- a/pkg/translator/azure/resourcelogs_to_logs.go +++ b/pkg/translator/azure/resourcelogs_to_logs.go @@ -38,12 +38,7 @@ const ( azureTenantID = "azure.tenant.id" ) -var ( - errMissingTimestamp = errors.New("missing timestamp") - errNotSupportedTimeFormat = errors.New("not supported time format") -) - -const ISO8601 = "iso8601" +var errMissingTimestamp = errors.New("missing timestamp") // azureRecords represents an array of Azure log records // as exported via an Azure Event Hub @@ -80,7 +75,6 @@ type ResourceLogsUnmarshaler struct { Version string Logger *zap.Logger TimeFormat []string - TimeOffset time.Duration } func (r ResourceLogsUnmarshaler) UnmarshalLogs(buf []byte) (plog.Logs, error) { @@ -113,7 +107,7 @@ func (r ResourceLogsUnmarshaler) UnmarshalLogs(buf []byte) (plog.Logs, error) { for i := 0; i < len(logs); i++ { log := logs[i] - nanos, err := getTimestamp(log, r.TimeFormat, r.TimeOffset) + nanos, err := getTimestamp(log, r.TimeFormat) if err != nil { r.Logger.Warn("Unable to convert timestamp from log", zap.String("timestamp", log.Time)) continue @@ -137,11 +131,11 @@ func (r ResourceLogsUnmarshaler) UnmarshalLogs(buf []byte) (plog.Logs, error) { return l, nil } -func getTimestamp(record azureLogRecord, format []string, offset time.Duration) (pcommon.Timestamp, error) { +func getTimestamp(record azureLogRecord, format []string) (pcommon.Timestamp, error) { if record.Time != "" { - return asTimestamp(record.Time, format, offset) + return asTimestamp(record.Time, format) } else if record.Timestamp != "" { - return asTimestamp(record.Timestamp, format, offset) + return asTimestamp(record.Timestamp, format) } return 0, errMissingTimestamp @@ -150,33 +144,21 @@ func getTimestamp(record azureLogRecord, format []string, offset time.Duration) // asTimestamp will parse an ISO8601 string into an OpenTelemetry // nanosecond timestamp. If the string cannot be parsed, it will // return zero and the error. -func asTimestamp(s string, format []string, offset time.Duration) (pcommon.Timestamp, error) { +func asTimestamp(s string, formats []string) (pcommon.Timestamp, error) { var err error var t time.Time - if format != nil { - for _, v := range format { - if v == ISO8601 { - t, err = iso8601.ParseString(s) - } else { - t, err = time.Parse(v, s) - } - if err == nil { - break - } + // Try parsing with provided formats first + for _, format := range formats { + if t, err = time.Parse(format, s); err == nil { + return pcommon.Timestamp(t.UnixNano()), nil } - if t == (time.Time{}) { - err = errNotSupportedTimeFormat - } - } else { - t, err = iso8601.ParseString(s) - } - if err != nil { - return 0, err } - timestamp := t.Add(offset * time.Hour).UnixNano() - - return pcommon.Timestamp(timestamp), nil + // Fallback to ISO 8601 parsing if no format matches + if t, err = iso8601.ParseString(s); err == nil { + return pcommon.Timestamp(t.UnixNano()), nil + } + return 0, err } // asSeverity converts the Azure log level to equivalent diff --git a/pkg/translator/azure/resourcelogs_to_logs_test.go b/pkg/translator/azure/resourcelogs_to_logs_test.go index be630c9aaa9c..b30e41fb1247 100644 --- a/pkg/translator/azure/resourcelogs_to_logs_test.go +++ b/pkg/translator/azure/resourcelogs_to_logs_test.go @@ -27,7 +27,7 @@ var testBuildInfo = component.BuildInfo{ var minimumLogRecord = func() plog.LogRecord { lr := plog.NewLogs().ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() - ts, _ := asTimestamp("2022-11-11T04:48:27.6767145Z", nil, 0) + ts, _ := asTimestamp("2022-11-11T04:48:27.6767145Z", nil) lr.SetTimestamp(ts) lr.Attributes().PutStr(azureOperationName, "SecretGet") lr.Attributes().PutStr(azureCategory, "AuditEvent") @@ -38,7 +38,7 @@ var minimumLogRecord = func() plog.LogRecord { var maximumLogRecord1 = func() plog.LogRecord { lr := plog.NewLogs().ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() - ts, _ := asTimestamp("2022-11-11T04:48:27.6767145Z", nil, 0) + ts, _ := asTimestamp("2022-11-11T04:48:27.6767145Z", nil) lr.SetTimestamp(ts) lr.SetSeverityNumber(plog.SeverityNumberWarn) lr.SetSeverityText("Warning") @@ -72,7 +72,7 @@ var maximumLogRecord2 = func() []plog.LogRecord { lr := sl.LogRecords().AppendEmpty() lr2 := sl.LogRecords().AppendEmpty() - ts, _ := asTimestamp("2022-11-11T04:48:29.6767145Z", nil, 0) + ts, _ := asTimestamp("2022-11-11T04:48:29.6767145Z", nil) lr.SetTimestamp(ts) lr.SetSeverityNumber(plog.SeverityNumberWarn) lr.SetSeverityText("Warning") @@ -98,7 +98,7 @@ var maximumLogRecord2 = func() []plog.LogRecord { m.PutDouble("float", 41.3) m.PutBool("bool", true) - ts, _ = asTimestamp("2022-11-11T04:48:31.6767145Z", nil, 0) + ts, _ = asTimestamp("2022-11-11T04:48:31.6767145Z", nil) lr2.SetTimestamp(ts) lr2.SetSeverityNumber(plog.SeverityNumberWarn) lr2.SetSeverityText("Warning") @@ -131,7 +131,7 @@ var maximumLogRecord2 = func() []plog.LogRecord { var badLevelLogRecord = func() plog.LogRecord { lr := plog.NewLogs().ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() - ts, _ := asTimestamp("2023-10-26T14:22:43.3416357Z", nil, 0) + ts, _ := asTimestamp("2023-10-26T14:22:43.3416357Z", nil) lr.SetTimestamp(ts) lr.SetSeverityNumber(plog.SeverityNumberTrace4) lr.SetSeverityText("4") @@ -171,7 +171,7 @@ var badLevelLogRecord = func() plog.LogRecord { var badTimeLogRecord = func() plog.LogRecord { lr := plog.NewLogs().ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() - ts, _ := asTimestamp("2021-10-14T22:17:11+00:00", nil, 0) + ts, _ := asTimestamp("2021-10-14T22:17:11+00:00", nil) lr.SetTimestamp(ts) lr.Attributes().PutStr(azureOperationName, "ApplicationGatewayAccess") @@ -213,12 +213,29 @@ var badTimeLogRecord = func() plog.LogRecord { func TestAsTimestamp(t *testing.T) { timestamp := "2022-11-11T04:48:27.6767145Z" - nanos, err := asTimestamp(timestamp, nil, 0) + nanos, err := asTimestamp(timestamp, nil) assert.NoError(t, err) assert.Less(t, pcommon.Timestamp(0), nanos) + timestamp = "11/20/2024 13:57:18" + nanos, err = asTimestamp(timestamp, []string{"01/02/2006 15:04:05"}) + assert.NoError(t, err) + assert.Less(t, pcommon.Timestamp(0), nanos) + + // time_format set, but fallback to iso8601 and succeeded to parse + timestamp = "2022-11-11T04:48:27.6767145Z" + nanos, err = asTimestamp(timestamp, []string{"01/02/2006 15:04:05"}) + assert.NoError(t, err) + assert.Less(t, pcommon.Timestamp(0), nanos) + + // time_format set, but all failed to parse + timestamp = "11/20/2024 13:57:18" + nanos, err = asTimestamp(timestamp, []string{"2006-01-02 15:04:05"}) + assert.Error(t, err) + assert.Equal(t, pcommon.Timestamp(0), nanos) + timestamp = "invalid-time" - nanos, err = asTimestamp(timestamp, nil, 0) + nanos, err = asTimestamp(timestamp, nil) assert.Error(t, err) assert.Equal(t, pcommon.Timestamp(0), nanos) } diff --git a/pkg/translator/azure/resources_to_traces.go b/pkg/translator/azure/resources_to_traces.go index 8a93e9e8f2d3..9f8feb240722 100644 --- a/pkg/translator/azure/resources_to_traces.go +++ b/pkg/translator/azure/resources_to_traces.go @@ -7,7 +7,6 @@ import ( "bytes" "encoding/hex" "net/url" - "time" jsoniter "github.com/json-iterator/go" "go.opentelemetry.io/collector/pdata/pcommon" @@ -66,7 +65,6 @@ type TracesUnmarshaler struct { Version string Logger *zap.Logger TimeFormat []string - TimeOffset time.Duration } func (r TracesUnmarshaler) UnmarshalTraces(buf []byte) (ptrace.Traces, error) { @@ -98,7 +96,7 @@ func (r TracesUnmarshaler) UnmarshalTraces(buf []byte) (ptrace.Traces, error) { resource.Attributes().PutStr("service.name", azureTrace.AppRoleName) - nanos, err := asTimestamp(azureTrace.Time, r.TimeFormat, r.TimeOffset) + nanos, err := asTimestamp(azureTrace.Time, r.TimeFormat) if err != nil { r.Logger.Warn("Invalid Timestamp", zap.String("time", azureTrace.Time)) continue diff --git a/pkg/translator/azurelogs/resourcelogs_to_logs.go b/pkg/translator/azurelogs/resourcelogs_to_logs.go index b23202934a73..4e45d5c6500e 100644 --- a/pkg/translator/azurelogs/resourcelogs_to_logs.go +++ b/pkg/translator/azurelogs/resourcelogs_to_logs.go @@ -43,12 +43,7 @@ const ( azureTenantID = "tenant.id" ) -var ( - errMissingTimestamp = errors.New("missing timestamp") - errNotSupportedTimeFormat = errors.New("not supported time format") -) - -const ISO8601 = "iso8601" // azureRecords represents an array of Azure log records +var errMissingTimestamp = errors.New("missing timestamp") // as exported via an Azure Event Hub type azureRecords struct { @@ -84,7 +79,6 @@ type ResourceLogsUnmarshaler struct { Version string Logger *zap.Logger TimeFormat []string - TimeOffset time.Duration } func (r ResourceLogsUnmarshaler) UnmarshalLogs(buf []byte) (plog.Logs, error) { @@ -116,7 +110,7 @@ func (r ResourceLogsUnmarshaler) UnmarshalLogs(buf []byte) (plog.Logs, error) { for i := 0; i < len(logs); i++ { log := logs[i] - nanos, err := getTimestamp(log, r.TimeFormat, r.TimeOffset) + nanos, err := getTimestamp(log, r.TimeFormat) if err != nil { r.Logger.Warn("Unable to convert timestamp from log", zap.String("timestamp", log.Time)) continue @@ -144,11 +138,11 @@ func (r ResourceLogsUnmarshaler) UnmarshalLogs(buf []byte) (plog.Logs, error) { return l, nil } -func getTimestamp(record azureLogRecord, format []string, offset time.Duration) (pcommon.Timestamp, error) { +func getTimestamp(record azureLogRecord, formats []string) (pcommon.Timestamp, error) { if record.Time != "" { - return asTimestamp(record.Time, format, offset) + return asTimestamp(record.Time, formats) } else if record.Timestamp != "" { - return asTimestamp(record.Timestamp, format, offset) + return asTimestamp(record.Timestamp, formats) } return 0, errMissingTimestamp @@ -157,33 +151,21 @@ func getTimestamp(record azureLogRecord, format []string, offset time.Duration) // asTimestamp will parse an ISO8601 string into an OpenTelemetry // nanosecond timestamp. If the string cannot be parsed, it will // return zero and the error. -func asTimestamp(s string, format []string, offset time.Duration) (pcommon.Timestamp, error) { +func asTimestamp(s string, formats []string) (pcommon.Timestamp, error) { var err error var t time.Time - if format != nil { - for _, v := range format { - if v == ISO8601 { - t, err = iso8601.ParseString(s) - } else { - t, err = time.Parse(v, s) - } - if err == nil { - break - } + // Try parsing with provided formats first + for _, format := range formats { + if t, err = time.Parse(format, s); err == nil { + return pcommon.Timestamp(t.UnixNano()), nil } - if t == (time.Time{}) { - err = errNotSupportedTimeFormat - } - } else { - t, err = iso8601.ParseString(s) - } - if err != nil { - return 0, err } - timestamp := t.Add(offset * time.Hour).UnixNano() - - return pcommon.Timestamp(timestamp), nil + // Fallback to ISO 8601 parsing if no format matches + if t, err = iso8601.ParseString(s); err == nil { + return pcommon.Timestamp(t.UnixNano()), nil + } + return 0, err } // asSeverity converts the Azure log level to equivalent diff --git a/pkg/translator/azurelogs/resourcelogs_to_logs_test.go b/pkg/translator/azurelogs/resourcelogs_to_logs_test.go index 243955412d68..6da186cb81b1 100644 --- a/pkg/translator/azurelogs/resourcelogs_to_logs_test.go +++ b/pkg/translator/azurelogs/resourcelogs_to_logs_test.go @@ -27,7 +27,7 @@ var testBuildInfo = component.BuildInfo{ var minimumLogRecord = func() plog.LogRecord { lr := plog.NewLogs().ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() - ts, _ := asTimestamp("2022-11-11T04:48:27.6767145Z", nil, 0) + ts, _ := asTimestamp("2022-11-11T04:48:27.6767145Z", nil) lr.SetTimestamp(ts) lr.Attributes().PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure) lr.Attributes().PutStr(conventions.AttributeCloudResourceID, "/RESOURCE_ID") @@ -44,7 +44,7 @@ var minimumLogRecord = func() plog.LogRecord { var maximumLogRecord1 = func() plog.LogRecord { lr := plog.NewLogs().ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() - ts, _ := asTimestamp("2022-11-11T04:48:27.6767145Z", nil, 0) + ts, _ := asTimestamp("2022-11-11T04:48:27.6767145Z", nil) lr.SetTimestamp(ts) lr.SetSeverityNumber(plog.SeverityNumberWarn) lr.SetSeverityText("Warning") @@ -82,7 +82,7 @@ var maximumLogRecord2 = func() []plog.LogRecord { lr := sl.LogRecords().AppendEmpty() lr2 := sl.LogRecords().AppendEmpty() - ts, _ := asTimestamp("2022-11-11T04:48:29.6767145Z", nil, 0) + ts, _ := asTimestamp("2022-11-11T04:48:29.6767145Z", nil) lr.SetTimestamp(ts) lr.SetSeverityNumber(plog.SeverityNumberWarn) lr.SetSeverityText("Warning") @@ -112,7 +112,7 @@ var maximumLogRecord2 = func() []plog.LogRecord { properties.PutDouble("float", 41.3) properties.PutBool("bool", true) - ts, _ = asTimestamp("2022-11-11T04:48:31.6767145Z", nil, 0) + ts, _ = asTimestamp("2022-11-11T04:48:31.6767145Z", nil) lr2.SetTimestamp(ts) lr2.SetSeverityNumber(plog.SeverityNumberWarn) lr2.SetSeverityText("Warning") @@ -149,7 +149,7 @@ var maximumLogRecord2 = func() []plog.LogRecord { var badLevelLogRecord = func() plog.LogRecord { lr := plog.NewLogs().ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() - ts, _ := asTimestamp("2023-10-26T14:22:43.3416357Z", nil, 0) + ts, _ := asTimestamp("2023-10-26T14:22:43.3416357Z", nil) lr.SetTimestamp(ts) lr.SetSeverityNumber(plog.SeverityNumberTrace4) lr.SetSeverityText("4") @@ -193,7 +193,7 @@ var badLevelLogRecord = func() plog.LogRecord { var badTimeLogRecord = func() plog.LogRecord { lr := plog.NewLogs().ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() - ts, _ := asTimestamp("2021-10-14T22:17:11+00:00", nil, 0) + ts, _ := asTimestamp("2021-10-14T22:17:11+00:00", nil) lr.SetTimestamp(ts) lr.Attributes().PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure) @@ -239,17 +239,29 @@ var badTimeLogRecord = func() plog.LogRecord { func TestAsTimestamp(t *testing.T) { timestamp := "2022-11-11T04:48:27.6767145Z" - nanos, err := asTimestamp(timestamp, nil, 0) + nanos, err := asTimestamp(timestamp, nil) assert.NoError(t, err) assert.Less(t, pcommon.Timestamp(0), nanos) timestamp = "11/20/2024 13:57:18" - nanos, err = asTimestamp(timestamp, []string{"01/02/2006 15:04:05"}, 0) + nanos, err = asTimestamp(timestamp, []string{"01/02/2006 15:04:05"}) assert.NoError(t, err) assert.Less(t, pcommon.Timestamp(0), nanos) + // time_format set, but fallback to iso8601 and succeeded to parse + timestamp = "2022-11-11T04:48:27.6767145Z" + nanos, err = asTimestamp(timestamp, []string{"01/02/2006 15:04:05"}) + assert.NoError(t, err) + assert.Less(t, pcommon.Timestamp(0), nanos) + + // time_format set, but all failed to parse + timestamp = "11/20/2024 13:57:18" + nanos, err = asTimestamp(timestamp, []string{"2006-01-02 15:04:05"}) + assert.Error(t, err) + assert.Equal(t, pcommon.Timestamp(0), nanos) + timestamp = "invalid-time" - nanos, err = asTimestamp(timestamp, nil, 0) + nanos, err = asTimestamp(timestamp, nil) assert.Error(t, err) assert.Equal(t, pcommon.Timestamp(0), nanos) } diff --git a/receiver/azureeventhubreceiver/README.md b/receiver/azureeventhubreceiver/README.md index 4a23ff12f53a..79dfc9479529 100644 --- a/receiver/azureeventhubreceiver/README.md +++ b/receiver/azureeventhubreceiver/README.md @@ -52,7 +52,7 @@ Default: `false` (semantic conventions are not applied) ### time_format (optional) -All supported time format for logs, metrics and traces. Default is empty string array, which means using the current iso8601 parser. The format is based on https://pkg.go.dev/time#Layout. If no time-zone info, will use UTC time. +All supported time format for logs, metrics and traces. Default is `nil` (unset), which means using the current iso8601 parser. The format is based on https://pkg.go.dev/time#Layout. If no time-zone info, will use UTC time. If all failed, it will use iso8601 format to parse. Default: `nil` @@ -76,14 +76,7 @@ receivers: time_format: # All supported time format. Default is empty string array, which means using the current iso8601 parser. The format is based on https://pkg.go.dev/time#Layout. If no time-zone info, will use UTC time. logs: ["01/02/2006 15:04:05","2006-01-02 15:04:05","2006-01-02T15:04:05Z07:00"] - metrics: [""] - traces: [""] - # optional - time_offset: - # The offset hours to parsed time. Mainly for cases when there's no time-zone info in time string. default is 0. - logs: -8 - metrics: +8 - traces: -8 + metrics: ["01/02/2006 15:04:05"] ``` This component can persist its state using the [storage extension]. diff --git a/receiver/azureeventhubreceiver/azureresourcelogs_unmarshaler.go b/receiver/azureeventhubreceiver/azureresourcelogs_unmarshaler.go index 1a81bd011d49..8a3db44b0c1a 100644 --- a/receiver/azureeventhubreceiver/azureresourcelogs_unmarshaler.go +++ b/receiver/azureeventhubreceiver/azureresourcelogs_unmarshaler.go @@ -4,8 +4,6 @@ package azureeventhubreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/azureeventhubreceiver" import ( - "time" - eventhub "github.com/Azure/azure-event-hubs-go/v3" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/pdata/plog" @@ -23,14 +21,13 @@ type AzureResourceLogsEventUnmarshaler struct { unmarshaler logsUnmarshaler } -func newAzureResourceLogsUnmarshaler(buildInfo component.BuildInfo, logger *zap.Logger, applySemanticConventions bool, timeFormat []string, timeOffset time.Duration) eventLogsUnmarshaler { +func newAzureResourceLogsUnmarshaler(buildInfo component.BuildInfo, logger *zap.Logger, applySemanticConventions bool, timeFormat []string) eventLogsUnmarshaler { if applySemanticConventions { return AzureResourceLogsEventUnmarshaler{ unmarshaler: &azurelogs.ResourceLogsUnmarshaler{ Version: buildInfo.Version, Logger: logger, TimeFormat: timeFormat, - TimeOffset: timeOffset, }, } } @@ -39,7 +36,6 @@ func newAzureResourceLogsUnmarshaler(buildInfo component.BuildInfo, logger *zap. Version: buildInfo.Version, Logger: logger, TimeFormat: timeFormat, - TimeOffset: timeOffset, }, } } diff --git a/receiver/azureeventhubreceiver/azureresourcemetrics_unmarshaler.go b/receiver/azureeventhubreceiver/azureresourcemetrics_unmarshaler.go index 9c00136f4b94..cce62e907fbf 100644 --- a/receiver/azureeventhubreceiver/azureresourcemetrics_unmarshaler.go +++ b/receiver/azureeventhubreceiver/azureresourcemetrics_unmarshaler.go @@ -5,7 +5,6 @@ package azureeventhubreceiver // import "github.com/open-telemetry/opentelemetry import ( "bytes" - "errors" "fmt" "strings" "time" @@ -22,18 +21,12 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/azureeventhubreceiver/internal/metadata" ) -const ( - azureResourceID = "azure.resource.id" - ISO8601 = "iso8601" -) - -var errNotSupportedTimeFormat = errors.New("not supported time format") +const azureResourceID = "azure.resource.id" type azureResourceMetricsUnmarshaler struct { buildInfo component.BuildInfo logger *zap.Logger TimeFormat []string - TimeOffset time.Duration } // azureMetricRecords represents an array of Azure metric records @@ -56,12 +49,11 @@ type azureMetricRecord struct { Average float64 `json:"average"` } -func newAzureResourceMetricsUnmarshaler(buildInfo component.BuildInfo, logger *zap.Logger, timeFormat []string, timeOffset time.Duration) eventMetricsUnmarshaler { +func newAzureResourceMetricsUnmarshaler(buildInfo component.BuildInfo, logger *zap.Logger, timeFormat []string) eventMetricsUnmarshaler { return azureResourceMetricsUnmarshaler{ buildInfo: buildInfo, logger: logger, TimeFormat: timeFormat, - TimeOffset: timeOffset, } } @@ -98,7 +90,7 @@ func (r azureResourceMetricsUnmarshaler) UnmarshalMetrics(event *eventhub.Event) resourceID = azureMetric.ResourceID } - nanos, err := asTimestamp(azureMetric.Time, r.TimeFormat, r.TimeOffset) + nanos, err := asTimestamp(azureMetric.Time, r.TimeFormat) if err != nil { r.logger.Warn("Invalid Timestamp", zap.String("time", azureMetric.Time)) continue @@ -160,31 +152,19 @@ func (r azureResourceMetricsUnmarshaler) UnmarshalMetrics(event *eventhub.Event) // asTimestamp will parse an ISO8601 string into an OpenTelemetry // nanosecond timestamp. If the string cannot be parsed, it will // return zero and the error. -func asTimestamp(s string, format []string, offset time.Duration) (pcommon.Timestamp, error) { +func asTimestamp(s string, formats []string) (pcommon.Timestamp, error) { var err error var t time.Time - if format != nil { - for _, v := range format { - if v == ISO8601 { - t, err = iso8601.ParseString(s) - } else { - t, err = time.Parse(v, s) - } - if err == nil { - break - } + // Try parsing with provided formats first + for _, format := range formats { + if t, err = time.Parse(format, s); err == nil { + return pcommon.Timestamp(t.UnixNano()), nil } - if t == (time.Time{}) { - err = errNotSupportedTimeFormat - } - } else { - t, err = iso8601.ParseString(s) - } - if err != nil { - return 0, err } - timestamp := t.Add(offset * time.Hour).UnixNano() - - return pcommon.Timestamp(timestamp), nil + // Fallback to ISO 8601 parsing if no format matches + if t, err = iso8601.ParseString(s); err == nil { + return pcommon.Timestamp(t.UnixNano()), nil + } + return 0, err } diff --git a/receiver/azureeventhubreceiver/azureresourcetraces_unmarshaler.go b/receiver/azureeventhubreceiver/azureresourcetraces_unmarshaler.go index bcdd1904e82a..815817fa162e 100755 --- a/receiver/azureeventhubreceiver/azureresourcetraces_unmarshaler.go +++ b/receiver/azureeventhubreceiver/azureresourcetraces_unmarshaler.go @@ -4,8 +4,6 @@ package azureeventhubreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/azureeventhubreceiver" import ( - "time" - eventhub "github.com/Azure/azure-event-hubs-go/v3" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/pdata/ptrace" @@ -18,13 +16,12 @@ type azureTracesEventUnmarshaler struct { unmarshaler *azure.TracesUnmarshaler } -func newAzureTracesUnmarshaler(buildInfo component.BuildInfo, logger *zap.Logger, timeFormat []string, timeOffset time.Duration) eventTracesUnmarshaler { +func newAzureTracesUnmarshaler(buildInfo component.BuildInfo, logger *zap.Logger, timeFormat []string) eventTracesUnmarshaler { return azureTracesEventUnmarshaler{ unmarshaler: &azure.TracesUnmarshaler{ Version: buildInfo.Version, Logger: logger, TimeFormat: timeFormat, - TimeOffset: timeOffset, }, } } diff --git a/receiver/azureeventhubreceiver/config.go b/receiver/azureeventhubreceiver/config.go index 9e8d94450881..09cc02c7e31c 100644 --- a/receiver/azureeventhubreceiver/config.go +++ b/receiver/azureeventhubreceiver/config.go @@ -6,7 +6,6 @@ package azureeventhubreceiver // import "github.com/open-telemetry/opentelemetry import ( "errors" "fmt" - "time" "github.com/Azure/azure-amqp-common-go/v4/conn" "go.opentelemetry.io/collector/component" @@ -34,7 +33,6 @@ type Config struct { ConsumerGroup string `mapstructure:"group"` ApplySemanticConventions bool `mapstructure:"apply_semantic_conventions"` TimeFormat TimeFormat `mapstructure:"time_format"` - TimeOffset TimeOffset `mapstructure:"time_offset"` } type TimeFormat struct { @@ -43,12 +41,6 @@ type TimeFormat struct { Traces []string `mapstructure:"traces"` } -type TimeOffset struct { - Logs time.Duration `mapstructure:"logs"` - Metrics time.Duration `mapstructure:"metrics"` - Traces time.Duration `mapstructure:"traces"` -} - func isValidFormat(format string) bool { for _, validFormat := range validFormats { if logFormat(format) == validFormat { diff --git a/receiver/azureeventhubreceiver/factory.go b/receiver/azureeventhubreceiver/factory.go index 433003dc3b68..7e858e4353ee 100644 --- a/receiver/azureeventhubreceiver/factory.go +++ b/receiver/azureeventhubreceiver/factory.go @@ -110,21 +110,21 @@ func (f *eventhubReceiverFactory) getReceiver( if logFormat(receiverConfig.Format) == rawLogFormat { logsUnmarshaler = newRawLogsUnmarshaler(settings.Logger) } else { - logsUnmarshaler = newAzureResourceLogsUnmarshaler(settings.BuildInfo, settings.Logger, receiverConfig.ApplySemanticConventions, receiverConfig.TimeFormat.Logs, receiverConfig.TimeOffset.Logs) + logsUnmarshaler = newAzureResourceLogsUnmarshaler(settings.BuildInfo, settings.Logger, receiverConfig.ApplySemanticConventions, receiverConfig.TimeFormat.Logs) } case pipeline.SignalMetrics: if logFormat(receiverConfig.Format) == rawLogFormat { metricsUnmarshaler = nil err = errors.New("raw format not supported for Metrics") } else { - metricsUnmarshaler = newAzureResourceMetricsUnmarshaler(settings.BuildInfo, settings.Logger, receiverConfig.TimeFormat.Metrics, receiverConfig.TimeOffset.Metrics) + metricsUnmarshaler = newAzureResourceMetricsUnmarshaler(settings.BuildInfo, settings.Logger, receiverConfig.TimeFormat.Metrics) } case pipeline.SignalTraces: if logFormat(receiverConfig.Format) == rawLogFormat { tracesUnmarshaler = nil err = errors.New("raw format not supported for Traces") } else { - tracesUnmarshaler = newAzureTracesUnmarshaler(settings.BuildInfo, settings.Logger, receiverConfig.TimeFormat.Traces, receiverConfig.TimeOffset.Traces) + tracesUnmarshaler = newAzureTracesUnmarshaler(settings.BuildInfo, settings.Logger, receiverConfig.TimeFormat.Traces) } }