Skip to content
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

[pkg/otlp/attributes] Handle literal 'host' tag #65

Merged
merged 1 commit into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .chloggen/mx-psi_literal-host.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: bug_fix

# The name of the component (e.g. pkg/quantile)
component: pkg/otlp/attributes

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Handle literal 'host' attribute to avoid double tagging.

# The PR related to this change
issues: []

# (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: This avoids double tagging when using `metrics::resource_attributes_as_tags` metrics, or in all cases for traces/logs.
gbbr marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 17 additions & 5 deletions pkg/otlp/attributes/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const (
AttributeDatadogHostname = "datadog.host.name"
// AttributeK8sNodeName the datadog k8s node name attribute
AttributeK8sNodeName = "k8s.node.name"
// Attribute host is a literal host tag.
// We check for this to avoid double tagging.
AttributeHost = "host"
Copy link
Member

Choose a reason for hiding this comment

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

IMO it is very confusing that we treat host, host.name and datadog.host.name in subtly different order. This has led to several customer issues.

(Not suggesting to fix it in this PR, but something that needs better documentation)

Copy link
Member Author

Choose a reason for hiding this comment

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

That's fair, I think some subtlety is required here but maybe we can do better. For this PR, I am convinced that host needs to go first, since otherwise you get double tagging in some cases, so I will merge, but we should discuss how to improve the situation for the rest.

)

func getClusterName(attrs pcommon.Map) (string, bool) {
Expand All @@ -48,15 +51,17 @@ func getClusterName(attrs pcommon.Map) (string, bool) {

// hostnameFromAttributes tries to get a valid hostname from attributes by checking, in order:
//
// 1. a custom Datadog hostname provided by the "datadog.host.name" attribute
// 1. the "host" attribute to avoid double tagging if present.
//
// 2. cloud provider specific hostname for AWS, Azure or GCP,
// 2. a custom Datadog hostname provided by the "datadog.host.name" attribute
//
// 3. the Kubernetes node name (and cluster name if available),
// 3. cloud provider specific hostname for AWS, Azure or GCP,
//
// 4. the cloud provider host ID and
// 4. the Kubernetes node name (and cluster name if available),
//
// 5. the host.name attribute.
// 5. the cloud provider host ID and
//
// 6. the host.name attribute.
Comment on lines -51 to +64
Copy link
Member Author

Choose a reason for hiding this comment

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

This is just adding the top line and bumping the numbers on the rest of items, but the resulting diff is not very readable

//
// It returns a boolean value indicated if any name was found
func hostnameFromAttributes(attrs pcommon.Map) (string, bool) {
Expand Down Expand Up @@ -92,6 +97,13 @@ func k8sHostnameFromAttributes(attrs pcommon.Map) (string, bool) {
}

func unsanitizedHostnameFromAttributes(attrs pcommon.Map) (string, bool) {
// Literal 'host' tag. Check and use to avoid double tagging.
if literalHost, ok := attrs.Get(AttributeHost); ok {
// Use even if not a string, so that we avoid double tagging if
// `resource_attributes_as_tags` is true and 'host' has a non-string value.
return literalHost.AsString(), true
}

// Custom hostname: useful for overriding in k8s/cloud envs
if customHostname, ok := attrs.Get(AttributeDatadogHostname); ok {
return customHostname.Str(), true
Expand Down
23 changes: 23 additions & 0 deletions pkg/otlp/attributes/source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
)

const (
testLiteralHost = "literal-host"
testHostID = "example-host-id"
testHostName = "example-host-name"
testContainerID = "example-container-id"
Expand All @@ -46,6 +47,20 @@ func TestSourceFromAttrs(t *testing.T) {
ok bool
src source.Source
}{
{
name: "literal 'host' tag",
attrs: testutils.NewAttributeMap(map[string]string{
AttributeHost: testLiteralHost,
AttributeDatadogHostname: testCustomName,
AttributeK8sNodeName: testNodeName,
conventions.AttributeK8SClusterName: testClusterName,
conventions.AttributeContainerID: testContainerID,
conventions.AttributeHostID: testHostID,
conventions.AttributeHostName: testHostName,
}),
ok: true,
src: source.Source{Kind: source.HostnameKind, Identifier: testLiteralHost},
},
{
name: "custom hostname",
attrs: testutils.NewAttributeMap(map[string]string{
Expand Down Expand Up @@ -148,6 +163,14 @@ func TestSourceFromAttrs(t *testing.T) {
}
}

func TestLiteralHostNonString(t *testing.T) {
attrs := pcommon.NewMap()
attrs.PutInt(AttributeHost, 1000)
src, ok := SourceFromAttrs(attrs)
assert.True(t, ok)
assert.Equal(t, source.Source{Kind: source.HostnameKind, Identifier: "1000"}, src)
}

func TestGetClusterName(t *testing.T) {
// OpenTelemetry convention
attrs := testutils.NewAttributeMap(map[string]string{
Expand Down