Skip to content

Add log support to Splunk HEC exporter #875

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

Merged
merged 12 commits into from
Sep 29, 2020

Conversation

atoulme
Copy link
Contributor

@atoulme atoulme commented Sep 1, 2020

Description:
Adds log support to Splunk HEC exporter.

Testing:
Unit tests.

Documentation:
None.

@atoulme atoulme requested a review from a team September 1, 2020 08:07
@codecov
Copy link

codecov bot commented Sep 1, 2020

Codecov Report

Merging #875 into master will increase coverage by 0.23%.
The diff coverage is 95.68%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #875      +/-   ##
==========================================
+ Coverage   88.86%   89.09%   +0.23%     
==========================================
  Files         272      261      -11     
  Lines       13294    12520     -774     
==========================================
- Hits        11814    11155     -659     
+ Misses       1125     1014     -111     
+ Partials      355      351       -4     
Flag Coverage Δ
#integration 75.42% <ø> (?)
#unit 88.16% <95.68%> (-0.71%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
internal/common/splunk/common.go 100.00% <ø> (ø)
exporter/splunkhecexporter/logdata_to_splunk.go 93.67% <93.67%> (ø)
exporter/splunkhecexporter/client.go 90.00% <100.00%> (+6.27%) ⬆️
exporter/splunkhecexporter/exporter.go 100.00% <100.00%> (+2.17%) ⬆️
exporter/splunkhecexporter/factory.go 100.00% <100.00%> (ø)
exporter/splunkhecexporter/metricdata_to_splunk.go 57.14% <100.00%> (ø)
exporter/splunkhecexporter/tracedata_to_splunk.go 100.00% <100.00%> (ø)
extension/httpforwarder/extension.go 0.00% <0.00%> (-91.49%) ⬇️
...eiver/k8sclusterreceiver/collection/replicasets.go 0.00% <0.00%> (-80.00%) ⬇️
extension/httpforwarder/factory.go 88.23% <0.00%> (-11.77%) ⬇️
... and 32 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2789e90...25902df. Read the comment docs.

@atoulme atoulme force-pushed the splunkhecexporter_logs branch 2 times, most recently from 426076f to 54f2054 Compare September 1, 2020 16:24
@atoulme atoulme force-pushed the splunkhecexporter_logs branch 2 times, most recently from 80abacb to de17234 Compare September 1, 2020 17:21
@atoulme atoulme force-pushed the splunkhecexporter_logs branch from de17234 to 9f6af1c Compare September 1, 2020 19:56
@@ -17,8 +17,11 @@ package splunk
import "strings"

const (
HostnameLabel = "host.hostname"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized these are the same as in this file https://github.com/open-telemetry/opentelemetry-collector/blob/master/translator/conventions/opentelemetry.go#L20. If they are actually referring to the same thing then you can just refer to that package instead of redefining them here. Looks like source.type isn't there but the other two are.

@keitwb
Copy link
Contributor

keitwb commented Sep 2, 2020

I thought I could push to this to update it but I can't. Anyway I made some updates for when you get back from leave:

diff --git a/exporter/splunkhecexporter/client_test.go b/exporter/splunkhecexporter/client_test.go
index d736ccb..d1c0431 100644
--- a/exporter/splunkhecexporter/client_test.go
+++ b/exporter/splunkhecexporter/client_test.go
@@ -36,6 +36,7 @@ import (
 	"go.opentelemetry.io/collector/consumer/pdata"
 	"go.opentelemetry.io/collector/consumer/pdatautil"
 	"go.opentelemetry.io/collector/testutil/metricstestutil"
+	"go.opentelemetry.io/collector/translator/conventions"
 	"go.opentelemetry.io/collector/translator/internaldata"
 	"go.uber.org/zap"
 	"google.golang.org/protobuf/types/known/timestamppb"
@@ -118,9 +119,9 @@ func createLogData(numberOfLogs int) pdata.Logs {
 		logRecord := pdata.NewLogRecord()
 		logRecord.InitEmpty()
 		logRecord.Body().SetStringVal("mylog")
-		logRecord.Attributes().InsertString(splunk.SourceLabel, "myapp")
+		logRecord.Attributes().InsertString(conventions.AttributeServiceName, "myapp")
 		logRecord.Attributes().InsertString(splunk.SourcetypeLabel, "myapp-type")
-		logRecord.Attributes().InsertString(splunk.HostnameLabel, "myhost")
+		logRecord.Attributes().InsertString(conventions.AttributeHostHostname, "myhost")
 		logRecord.Attributes().InsertString("custom", "custom")
 		logRecord.SetTimestamp(ts)
 		ill.Logs().Append(&logRecord)
diff --git a/exporter/splunkhecexporter/exporter_test.go b/exporter/splunkhecexporter/exporter_test.go
index 7291399..a48f7d0 100644
--- a/exporter/splunkhecexporter/exporter_test.go
+++ b/exporter/splunkhecexporter/exporter_test.go
@@ -36,6 +36,7 @@ import (
 	"go.opentelemetry.io/collector/consumer/pdata"
 	"go.opentelemetry.io/collector/consumer/pdatautil"
 	"go.opentelemetry.io/collector/testutil/metricstestutil"
+	"go.opentelemetry.io/collector/translator/conventions"
 	"go.uber.org/zap"
 
 	"github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/splunk"
@@ -205,9 +206,9 @@ func generateLargeLogsBatch(t *testing.T) pdata.Logs {
 		logRecord := pdata.NewLogRecord()
 		logRecord.InitEmpty()
 		logRecord.Body().SetStringVal("mylog")
-		logRecord.Attributes().InsertString(splunk.SourceLabel, "myapp")
+		logRecord.Attributes().InsertString(conventions.AttributeServiceName, "myapp")
 		logRecord.Attributes().InsertString(splunk.SourcetypeLabel, "myapp-type")
-		logRecord.Attributes().InsertString(splunk.HostnameLabel, "myhost")
+		logRecord.Attributes().InsertString(conventions.AttributeHostHostname, "myhost")
 		logRecord.Attributes().InsertString("custom", "custom")
 		logRecord.SetTimestamp(ts)
 	}
@@ -219,7 +220,7 @@ func TestConsumeLogsData(t *testing.T) {
 	logRecord := pdata.NewLogRecord()
 	logRecord.InitEmpty()
 	logRecord.Body().SetStringVal("mylog")
-	logRecord.Attributes().InsertString(splunk.HostnameLabel, "myhost")
+	logRecord.Attributes().InsertString(conventions.AttributeHostHostname, "myhost")
 	logRecord.Attributes().InsertString("custom", "custom")
 	logRecord.SetTimestamp(123)
 	smallBatch := makeLog(logRecord)
diff --git a/exporter/splunkhecexporter/logdata_to_splunk.go b/exporter/splunkhecexporter/logdata_to_splunk.go
index ba1ddae..3ab201c 100644
--- a/exporter/splunkhecexporter/logdata_to_splunk.go
+++ b/exporter/splunkhecexporter/logdata_to_splunk.go
@@ -15,9 +15,10 @@
 package splunkhecexporter
 
 import (
-	"math"
+	"time"
 
 	"go.opentelemetry.io/collector/consumer/pdata"
+	"go.opentelemetry.io/collector/translator/conventions"
 	"go.uber.org/zap"
 
 	"github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/splunk"
@@ -68,9 +69,9 @@ func mapLogRecordToSplunkEvent(lr pdata.LogRecord, config *Config) *splunkEvent
 	var sourcetype string
 	fields := map[string]string{}
 	lr.Attributes().ForEach(func(k string, v pdata.AttributeValue) {
-		if k == splunk.HostnameLabel {
+		if k == conventions.AttributeHostHostname {
 			host = v.StringVal()
-		} else if k == splunk.SourceLabel {
+		} else if k == conventions.AttributeServiceName {
 			source = v.StringVal()
 		} else if k == splunk.SourcetypeLabel {
 			sourcetype = v.StringVal()
@@ -104,5 +105,5 @@ func mapLogRecordToSplunkEvent(lr pdata.LogRecord, config *Config) *splunkEvent
 
 // nanoTimestampToEpochMilliseconds transforms nanoseconds into <sec>.<ms>. For example, 1433188255.500 indicates 1433188255 seconds and 500 milliseconds after epoch.
 func nanoTimestampToEpochMilliseconds(ts pdata.TimestampUnixNano) float64 {
-	return float64(ts/1e9) + math.Round(float64(ts%1e9)/1e6)/1e3
+	return time.Duration(ts).Round(time.Millisecond).Seconds()
 }
diff --git a/exporter/splunkhecexporter/logdata_to_splunk_test.go b/exporter/splunkhecexporter/logdata_to_splunk_test.go
index edd28d7..bf8cc61 100644
--- a/exporter/splunkhecexporter/logdata_to_splunk_test.go
+++ b/exporter/splunkhecexporter/logdata_to_splunk_test.go
@@ -20,6 +20,7 @@ import (
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"go.opentelemetry.io/collector/consumer/pdata"
+	"go.opentelemetry.io/collector/translator/conventions"
 	"go.uber.org/zap"
 
 	"github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/splunk"
@@ -42,9 +43,9 @@ func Test_logDataToSplunk(t *testing.T) {
 				logRecord := pdata.NewLogRecord()
 				logRecord.InitEmpty()
 				logRecord.Body().SetStringVal("mylog")
-				logRecord.Attributes().InsertString(splunk.SourceLabel, "myapp")
+				logRecord.Attributes().InsertString(conventions.AttributeServiceName, "myapp")
 				logRecord.Attributes().InsertString(splunk.SourcetypeLabel, "myapp-type")
-				logRecord.Attributes().InsertString(splunk.HostnameLabel, "myhost")
+				logRecord.Attributes().InsertString(conventions.AttributeHostHostname, "myhost")
 				logRecord.Attributes().InsertString("custom", "custom")
 				logRecord.SetTimestamp(ts)
 				return makeLog(logRecord)
diff --git a/exporter/splunkhecexporter/metricdata_to_splunk.go b/exporter/splunkhecexporter/metricdata_to_splunk.go
index 6ae70df..886330b 100644
--- a/exporter/splunkhecexporter/metricdata_to_splunk.go
+++ b/exporter/splunkhecexporter/metricdata_to_splunk.go
@@ -23,6 +23,7 @@ import (
 	metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
 	"go.opentelemetry.io/collector/consumer/pdata"
 	"go.opentelemetry.io/collector/consumer/pdatautil"
+	"go.opentelemetry.io/collector/translator/conventions"
 	"go.uber.org/zap"
 	"google.golang.org/protobuf/types/known/timestamppb"
 
@@ -62,7 +63,7 @@ func metricDataToSplunk(logger *zap.Logger, data pdata.Metrics, config *Config)
 	for _, ocmd := range ocmds {
 		var host string
 		if ocmd.Resource != nil {
-			host = ocmd.Resource.Labels[splunk.HostnameLabel]
+			host = ocmd.Resource.Labels[conventions.AttributeHostHostname]
 		}
 		if host == "" {
 			host = unknownHostName
diff --git a/exporter/splunkhecexporter/tracedata_to_splunk.go b/exporter/splunkhecexporter/tracedata_to_splunk.go
index 4322671..251deb5 100644
--- a/exporter/splunkhecexporter/tracedata_to_splunk.go
+++ b/exporter/splunkhecexporter/tracedata_to_splunk.go
@@ -16,10 +16,9 @@ package splunkhecexporter
 
 import (
 	"go.opentelemetry.io/collector/consumer/pdata"
+	"go.opentelemetry.io/collector/translator/conventions"
 	"go.opentelemetry.io/collector/translator/internaldata"
 	"go.uber.org/zap"
-
-	"github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/splunk"
 )
 
 type splunkEvent struct {
@@ -39,7 +38,7 @@ func traceDataToSplunk(logger *zap.Logger, data pdata.Traces, config *Config) ([
 	for _, octd := range octds {
 		var host string
 		if octd.Resource != nil {
-			host = octd.Resource.Labels[splunk.HostnameLabel]
+			host = octd.Resource.Labels[conventions.AttributeHostHostname]
 		}
 		if host == "" {
 			host = unknownHostName
diff --git a/internal/common/go.sum b/internal/common/go.sum
index 680aae0..c888df6 100644
--- a/internal/common/go.sum
+++ b/internal/common/go.sum
@@ -41,6 +41,7 @@ github.com/containerd/containerd v1.3.6 h1:SMfcKoQyWhaRsYq7290ioC6XFcHDNcHvcEMjF
 github.com/containerd/containerd v1.3.6/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
@@ -148,6 +149,7 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -161,6 +163,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
diff --git a/internal/common/splunk/common.go b/internal/common/splunk/common.go
index 1c340f6..1cb394f 100644
--- a/internal/common/splunk/common.go
+++ b/internal/common/splunk/common.go
@@ -17,10 +17,8 @@ package splunk
 import "strings"
 
 const (
-	HostnameLabel        = "host.hostname"
 	SFxAccessTokenHeader = "X-Sf-Token"
 	SFxAccessTokenLabel  = "com.splunk.signalfx.access_token"
-	SourceLabel          = "service.name"
 	SourcetypeLabel      = "source.type"
 )

@atoulme
Copy link
Contributor Author

atoulme commented Sep 2, 2020

🙇 thank you Ben!

Copy link
Contributor

@keitwb keitwb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@@ -21,6 +21,7 @@ const (
SFxAccessTokenLabel = "com.splunk.signalfx.access_token"
SFxEventCategoryKey = "com.splunk.signalfx.event_category"
SFxEventPropertiesKey = "com.splunk.signalfx.event_properties"
SourcetypeLabel = "source.type"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use "com.splunk.sourcetype" instead?

Copy link
Contributor Author

@atoulme atoulme Sep 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case we cannot - "source.type" is a field that is part of the Splunk log payload. It is defined here:
https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/logs/data-model.md#splunk-hec

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the definition in the spec is incorrect. I wrote it before Otel introduced guidelines for conventions which say companies need to use reverse domain name as a prefix: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/common/common.md#recommendations-for-application-developers

The name is specific to your company and may be possibly used outside the company as well. To avoid clashes with names introduced by other companies (in a distributed system that uses applications from multiple vendors) it is recommended to prefix the new name by your company's reverse domain name, e.g. com.acme.shopname.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, making the change.

@tigrannajaryan
Copy link
Member

@atoulme please resolve the conflict.

@tigrannajaryan
Copy link
Member

@atoulme Thank you.

@tigrannajaryan tigrannajaryan merged commit 42fbb3e into open-telemetry:master Sep 29, 2020
dyladan referenced this pull request in dynatrace-oss-contrib/opentelemetry-collector-contrib Jan 29, 2021
@atoulme atoulme deleted the splunkhecexporter_logs branch September 5, 2023 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants