opentelemetry-resource-detector-aws 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87bc3d87967be6d6ea2a1303f78fc3347c060983b0931a25ace5559b93abd86f
|
4
|
+
data.tar.gz: bd9b141d06677d4c47a7dc7d76ac91a6b16b9fe9a63077c8f831eb920f8c7421
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c3c596f86e3a8052efcfdd39fb22af027400db89117bf763c1e375420962f8923c1d1636fe1f9c0291204569f831fc946f5fe237ee5ba76d76588b9d22fd2b4
|
7
|
+
data.tar.gz: 6ff3808c917d91d77cb231dd0079f64ac89340bfcb40ac264357b427e8538066c67b04277ecd2a1fa5dc4fa94675a8b12717b27e3b369f8d7cc3f42646b60a5e
|
data/README.md
CHANGED
@@ -31,11 +31,12 @@ require 'opentelemetry/resource/detector'
|
|
31
31
|
|
32
32
|
OpenTelemetry::SDK.configure do |c|
|
33
33
|
# Specify which AWS resource detectors to use
|
34
|
-
c.resource = OpenTelemetry::Resource::Detector::AWS.detect([:ec2, :ecs, :lambda])
|
34
|
+
c.resource = OpenTelemetry::Resource::Detector::AWS.detect([:ec2, :ecs, :eks, :lambda])
|
35
35
|
|
36
36
|
# Or use just one detector
|
37
37
|
c.resource = OpenTelemetry::Resource::Detector::AWS.detect([:ec2])
|
38
38
|
c.resource = OpenTelemetry::Resource::Detector::AWS.detect([:ecs])
|
39
|
+
c.resource = OpenTelemetry::Resource::Detector::AWS.detect([:eks])
|
39
40
|
c.resource = OpenTelemetry::Resource::Detector::AWS.detect([:lambda])
|
40
41
|
end
|
41
42
|
```
|
@@ -76,6 +77,21 @@ Populates `cloud`, `container`, and AWS ECS-specific attributes for processes ru
|
|
76
77
|
| `aws.log.stream.names` | The CloudWatch log stream names (if awslogs driver is used) |
|
77
78
|
| `aws.log.stream.arns` | The CloudWatch log stream ARNs (if awslogs driver is used) |
|
78
79
|
|
80
|
+
### AWS EKS Detector
|
81
|
+
|
82
|
+
Populates `cloud`, `container`, and Kubernetes (k8s) attributes for processes running on Amazon EKS.
|
83
|
+
| Resource Attribute | Description |
|
84
|
+
|--------------------|-------------|
|
85
|
+
| `cloud.platform` | The cloud platform. In this context, it's always "aws_eks" |
|
86
|
+
| `cloud.provider` | The cloud provider. In this context, it's always "aws" |
|
87
|
+
| `container.id` | The container ID from the `/proc/self/cgroup` file |
|
88
|
+
| `k8s.cluster.name` | The name of the EKS cluster from the `cluster-info` config map in the `amazon-cloudwatch` namespace |
|
89
|
+
|
90
|
+
The EKS detector verifies that the process is running on EKS by checking:
|
91
|
+
1. Presence of Kubernetes service account token and certificate
|
92
|
+
2. Ability to access the `aws-auth` config map in the `kube-system` namespace
|
93
|
+
3. Availability of either cluster name or container ID
|
94
|
+
|
79
95
|
### AWS Lambda Detector
|
80
96
|
Populates `cloud` and `faas` (Function as a Service) attributes for processes running on AWS Lambda.
|
81
97
|
| Resource Attribute | Description |
|
@@ -88,8 +104,6 @@ Populates `cloud` and `faas` (Function as a Service) attributes for processes ru
|
|
88
104
|
| `faas.instance` | The Lambda function instance ID from the `AWS_LAMBDA_LOG_STREAM_NAME` environment variable |
|
89
105
|
| `faas.max_memory` | The Lambda function memory size in MB from the `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` environment variable |
|
90
106
|
|
91
|
-
Additional AWS platforms (EKS) will be supported in future versions.
|
92
|
-
|
93
107
|
## License
|
94
108
|
|
95
109
|
The `opentelemetry-resource-detector-aws` gem is distributed under the Apache 2.0 license. See LICENSE for more information.
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright The OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
require 'net/http'
|
8
|
+
require 'json'
|
9
|
+
require 'openssl'
|
10
|
+
require 'uri'
|
11
|
+
require 'opentelemetry/common'
|
12
|
+
require 'opentelemetry/semantic_conventions/resource'
|
13
|
+
|
14
|
+
module OpenTelemetry
|
15
|
+
module Resource
|
16
|
+
module Detector
|
17
|
+
module AWS
|
18
|
+
# EKS contains detect class method for determining EKS resource attributes
|
19
|
+
module EKS
|
20
|
+
extend self
|
21
|
+
|
22
|
+
# Container ID length from cgroup file
|
23
|
+
CONTAINER_ID_LENGTH = 64
|
24
|
+
|
25
|
+
# HTTP request timeout in seconds
|
26
|
+
HTTP_TIMEOUT = 5
|
27
|
+
|
28
|
+
# Kubernetes token and certificate paths
|
29
|
+
TOKEN_PATH = '/var/run/secrets/kubernetes.io/serviceaccount/token'
|
30
|
+
CERT_PATH = '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'
|
31
|
+
|
32
|
+
# Kubernetes API paths
|
33
|
+
AWS_AUTH_PATH = '/api/v1/namespaces/kube-system/configmaps/aws-auth'
|
34
|
+
CLUSTER_INFO_PATH = '/api/v1/namespaces/amazon-cloudwatch/configmaps/cluster-info'
|
35
|
+
|
36
|
+
# Create a constant for resource semantic conventions
|
37
|
+
RESOURCE = OpenTelemetry::SemanticConventions::Resource
|
38
|
+
|
39
|
+
def detect
|
40
|
+
# Return empty resource if not running on K8s
|
41
|
+
return OpenTelemetry::SDK::Resources::Resource.create({}) unless k8s?
|
42
|
+
|
43
|
+
resource_attributes = {}
|
44
|
+
|
45
|
+
begin
|
46
|
+
# Get K8s credentials
|
47
|
+
cred_value = k8s_cred_value
|
48
|
+
|
49
|
+
# Verify this is an EKS cluster
|
50
|
+
unless eks?(cred_value)
|
51
|
+
OpenTelemetry.logger.debug('Could not confirm process is running on EKS')
|
52
|
+
return OpenTelemetry::SDK::Resources::Resource.create({})
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get cluster name and container ID
|
56
|
+
cluster_name_val = cluster_name(cred_value)
|
57
|
+
container_id_val = container_id
|
58
|
+
|
59
|
+
if container_id_val.empty? && cluster_name_val.empty?
|
60
|
+
OpenTelemetry.logger.debug('Neither cluster name nor container ID found on EKS process')
|
61
|
+
return OpenTelemetry::SDK::Resources::Resource.create({})
|
62
|
+
end
|
63
|
+
|
64
|
+
# Set resource attributes
|
65
|
+
resource_attributes[RESOURCE::CLOUD_PROVIDER] = 'aws'
|
66
|
+
resource_attributes[RESOURCE::CLOUD_PLATFORM] = 'aws_eks'
|
67
|
+
resource_attributes[RESOURCE::K8S_CLUSTER_NAME] = cluster_name_val unless cluster_name_val.empty?
|
68
|
+
resource_attributes[RESOURCE::CONTAINER_ID] = container_id_val unless container_id_val.empty?
|
69
|
+
rescue StandardError => e
|
70
|
+
OpenTelemetry.logger.debug("EKS resource detection failed: #{e.message}")
|
71
|
+
return OpenTelemetry::SDK::Resources::Resource.create({})
|
72
|
+
end
|
73
|
+
|
74
|
+
resource_attributes.delete_if { |_key, value| value.nil? || value.empty? }
|
75
|
+
OpenTelemetry::SDK::Resources::Resource.create(resource_attributes)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# Check if running on K8s
|
81
|
+
#
|
82
|
+
# @return [Boolean] true if running on K8s
|
83
|
+
def k8s?
|
84
|
+
File.exist?(TOKEN_PATH) && File.exist?(CERT_PATH)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Get K8s token
|
88
|
+
#
|
89
|
+
# @return [String] K8s token
|
90
|
+
# @raise [StandardError] if token could not be read
|
91
|
+
def k8s_cred_value
|
92
|
+
token = File.read(TOKEN_PATH).strip
|
93
|
+
"Bearer #{token}"
|
94
|
+
rescue StandardError => e
|
95
|
+
OpenTelemetry.logger.debug("Failed to get k8s token: #{e.message}")
|
96
|
+
raise e
|
97
|
+
end
|
98
|
+
|
99
|
+
# Check if running on EKS
|
100
|
+
#
|
101
|
+
# @param cred_value [String] K8s credentials
|
102
|
+
# @return [Boolean] true if running on EKS
|
103
|
+
def eks?(cred_value)
|
104
|
+
# Just try to to access the aws-auth configmap
|
105
|
+
# If it exists and we can access it, we're on EKS
|
106
|
+
aws_http_request(AWS_AUTH_PATH, cred_value)
|
107
|
+
true
|
108
|
+
rescue StandardError
|
109
|
+
false
|
110
|
+
end
|
111
|
+
|
112
|
+
# Get EKS cluster name
|
113
|
+
#
|
114
|
+
# @param cred_value [String] K8s credentials
|
115
|
+
# @return [String] Cluster name or empty string if not found
|
116
|
+
def cluster_name(cred_value)
|
117
|
+
begin
|
118
|
+
response = aws_http_request(CLUSTER_INFO_PATH, cred_value)
|
119
|
+
cluster_info = JSON.parse(response)
|
120
|
+
return cluster_info['data']['cluster.name'] if cluster_info['data'] && cluster_info['data']['cluster.name']
|
121
|
+
rescue StandardError => e
|
122
|
+
OpenTelemetry.logger.debug("Cannot get cluster name on EKS: #{e.message}")
|
123
|
+
end
|
124
|
+
''
|
125
|
+
end
|
126
|
+
|
127
|
+
# Get container ID from cgroup file
|
128
|
+
#
|
129
|
+
# @return [String] Container ID or empty string if not found
|
130
|
+
def container_id
|
131
|
+
begin
|
132
|
+
File.open('/proc/self/cgroup', 'r') do |file|
|
133
|
+
file.each_line do |line|
|
134
|
+
line = line.strip
|
135
|
+
# Look for container ID (64 chars) at the end of the line
|
136
|
+
return line[-CONTAINER_ID_LENGTH..-1] if line.length > CONTAINER_ID_LENGTH
|
137
|
+
end
|
138
|
+
end
|
139
|
+
rescue StandardError => e
|
140
|
+
OpenTelemetry.logger.debug("Failed to get container ID on EKS: #{e.message}")
|
141
|
+
end
|
142
|
+
''
|
143
|
+
end
|
144
|
+
|
145
|
+
# Make HTTP GET request to K8s API
|
146
|
+
#
|
147
|
+
# @param path [String] API path
|
148
|
+
# @param cred_value [String] Authorization header value
|
149
|
+
# @return [String] Response body
|
150
|
+
# @raise [StandardError] if request fails
|
151
|
+
def aws_http_request(path, cred_value)
|
152
|
+
uri = URI.parse("https://kubernetes.default.svc#{path}")
|
153
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
154
|
+
http.use_ssl = true
|
155
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
156
|
+
http.ca_file = CERT_PATH
|
157
|
+
http.open_timeout = HTTP_TIMEOUT
|
158
|
+
http.read_timeout = HTTP_TIMEOUT
|
159
|
+
|
160
|
+
request = Net::HTTP::Get.new(uri)
|
161
|
+
request['Authorization'] = cred_value
|
162
|
+
|
163
|
+
OpenTelemetry::Common::Utilities.untraced do
|
164
|
+
response = http.request(request)
|
165
|
+
raise "HTTP request failed with status #{response.code}" unless response.is_a?(Net::HTTPSuccess)
|
166
|
+
|
167
|
+
response.body
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -7,6 +7,7 @@
|
|
7
7
|
require 'opentelemetry/resource/detector/aws/ec2'
|
8
8
|
require 'opentelemetry/resource/detector/aws/ecs'
|
9
9
|
require 'opentelemetry/resource/detector/aws/lambda'
|
10
|
+
require 'opentelemetry/resource/detector/aws/eks'
|
10
11
|
|
11
12
|
module OpenTelemetry
|
12
13
|
module Resource
|
@@ -30,6 +31,8 @@ module OpenTelemetry
|
|
30
31
|
EC2.detect
|
31
32
|
when :ecs
|
32
33
|
ECS.detect
|
34
|
+
when :eks
|
35
|
+
EKS.detect
|
33
36
|
when :lambda
|
34
37
|
Lambda.detect
|
35
38
|
else
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opentelemetry-resource-detector-aws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OpenTelemetry Authors
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opentelemetry-sdk
|
@@ -38,6 +38,7 @@ files:
|
|
38
38
|
- lib/opentelemetry/resource/detector/aws.rb
|
39
39
|
- lib/opentelemetry/resource/detector/aws/ec2.rb
|
40
40
|
- lib/opentelemetry/resource/detector/aws/ecs.rb
|
41
|
+
- lib/opentelemetry/resource/detector/aws/eks.rb
|
41
42
|
- lib/opentelemetry/resource/detector/aws/lambda.rb
|
42
43
|
- lib/opentelemetry/resource/detector/aws/version.rb
|
43
44
|
homepage: https://github.com/open-telemetry/opentelemetry-ruby-contrib
|