-
Notifications
You must be signed in to change notification settings - Fork 6
/
source.go
160 lines (138 loc) · 5.54 KB
/
source.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package attributes
import (
"go.opentelemetry.io/collector/pdata/pcommon"
conventions "go.opentelemetry.io/collector/semconv/v1.6.1"
"github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes/azure"
"github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes/ec2"
"github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes/gcp"
"github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes/source"
)
const (
// AttributeDatadogHostname the datadog host name attribute
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"
)
func getClusterName(attrs pcommon.Map) (string, bool) {
if k8sClusterName, ok := attrs.Get(conventions.AttributeK8SClusterName); ok {
return k8sClusterName.Str(), true
}
cloudProvider, ok := attrs.Get(conventions.AttributeCloudProvider)
if ok && cloudProvider.Str() == conventions.AttributeCloudProviderAzure {
return azure.ClusterNameFromAttributes(attrs)
} else if ok && cloudProvider.Str() == conventions.AttributeCloudProviderAWS {
return ec2.ClusterNameFromAttributes(attrs)
}
return "", false
}
// hostnameFromAttributes tries to get a valid hostname from attributes by checking, in order:
//
// 1. the "host" attribute to avoid double tagging if present.
//
// 2. a custom Datadog hostname provided by the "datadog.host.name" attribute
//
// 3. cloud provider specific hostname for AWS, Azure or GCP,
//
// 4. the Kubernetes node name (and cluster name if available),
//
// 5. the cloud provider host ID and
//
// 6. the host.name attribute.
//
// It returns a boolean value indicated if any name was found
func hostnameFromAttributes(attrs pcommon.Map) (string, bool) {
// Check if the host is localhost or 0.0.0.0, if so discard it.
// We don't do the more strict validation done for metadata,
// to avoid breaking users existing invalid-but-accepted hostnames.
var invalidHosts = map[string]struct{}{
"0.0.0.0": {},
"127.0.0.1": {},
"localhost": {},
"localhost.localdomain": {},
"localhost6.localdomain6": {},
"ip6-localhost": {},
}
candidateHost, ok := unsanitizedHostnameFromAttributes(attrs)
if _, invalid := invalidHosts[candidateHost]; invalid {
return "", false
}
return candidateHost, ok
}
func k8sHostnameFromAttributes(attrs pcommon.Map) (string, bool) {
node, ok := attrs.Get(AttributeK8sNodeName)
if !ok {
return "", false
}
if cluster, ok := getClusterName(attrs); ok {
return node.Str() + "-" + cluster, true
}
return node.Str(), true
}
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
}
if launchType, ok := attrs.Get(conventions.AttributeAWSECSLaunchtype); ok && launchType.Str() == conventions.AttributeAWSECSLaunchtypeFargate {
// If on AWS ECS Fargate, we don't have a hostname
return "", false
}
cloudProvider, ok := attrs.Get(conventions.AttributeCloudProvider)
switch {
case ok && cloudProvider.Str() == conventions.AttributeCloudProviderAWS:
return ec2.HostnameFromAttrs(attrs)
case ok && cloudProvider.Str() == conventions.AttributeCloudProviderGCP:
return gcp.HostnameFromAttrs(attrs)
case ok && cloudProvider.Str() == conventions.AttributeCloudProviderAzure:
return azure.HostnameFromAttrs(attrs)
}
// Kubernetes: node-cluster if cluster name is available, else node
k8sName, k8sOk := k8sHostnameFromAttributes(attrs)
if k8sOk {
return k8sName, true
}
// host id from cloud provider
if hostID, ok := attrs.Get(conventions.AttributeHostID); ok {
return hostID.Str(), true
}
// hostname from cloud provider or OS
if hostName, ok := attrs.Get(conventions.AttributeHostName); ok {
return hostName.Str(), true
}
return "", false
}
// SourceFromAttrs gets a telemetry signal source from its attributes.
// Deprecated: Use Translator.ResourceToSource or Translator.AttributesToSource instead.
func SourceFromAttrs(attrs pcommon.Map) (source.Source, bool) {
if launchType, ok := attrs.Get(conventions.AttributeAWSECSLaunchtype); ok && launchType.Str() == conventions.AttributeAWSECSLaunchtypeFargate {
if taskARN, ok := attrs.Get(conventions.AttributeAWSECSTaskARN); ok {
return source.Source{Kind: source.AWSECSFargateKind, Identifier: taskARN.Str()}, true
}
}
if host, ok := hostnameFromAttributes(attrs); ok {
return source.Source{Kind: source.HostnameKind, Identifier: host}, true
}
return source.Source{}, false
}