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: 5a8ec0b68eb13782494f65cdafeed9f75447bb1762202bbbcde32cf795f4f3bb
4
- data.tar.gz: 5039cfbeb483722204a6e7410881a675cbe7f8326c603a543e7ec233244616af
3
+ metadata.gz: 87bc3d87967be6d6ea2a1303f78fc3347c060983b0931a25ace5559b93abd86f
4
+ data.tar.gz: bd9b141d06677d4c47a7dc7d76ac91a6b16b9fe9a63077c8f831eb920f8c7421
5
5
  SHA512:
6
- metadata.gz: 0b0171c2e36d1c4c7ff95259b49699e5af069dd0fc34b8ec079682fb75b989190af36c5792e25e2f875499f50f4107c5461c45532a057cffadc283ce1c47dec3
7
- data.tar.gz: 99ba3b6378c03a344f119329821c576cb78408bfa0e937dccb01f89e9503a79c02cd723e97e371789135f02529dd201720406f3c7f5697d119f904bdad6cc2c2
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
@@ -8,7 +8,7 @@ module OpenTelemetry
8
8
  module Resource
9
9
  module Detector
10
10
  module AWS
11
- VERSION = '0.3.0'
11
+ VERSION = '0.4.0'
12
12
  end
13
13
  end
14
14
  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.3.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-05-07 00:00:00.000000000 Z
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