opentelemetry-config 0.1.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +79 -1
- data/lib/opentelemetry/config/defaults.rb +38 -0
- data/lib/opentelemetry/config/env_substitution.rb +84 -0
- data/lib/opentelemetry/config/generated_constants.rb +32 -23
- data/lib/opentelemetry/config/logs.rb +127 -0
- data/lib/opentelemetry/config/resource.rb +16 -2
- data/lib/opentelemetry/config/trace.rb +32 -29
- data/lib/opentelemetry/config/version.rb +1 -1
- data/lib/opentelemetry/config.rb +21 -1
- metadata +9 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e6246820b0b2b5312be2c696c49f6def8f666425b3b5365a44e811fb455a3003
|
|
4
|
+
data.tar.gz: 38e2b961380f9394cdfa067590e40230e597436d5a349bbc28df3b8aaf58999c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2dbb1307ce50f1bc2390b1ed90741ae07f74499fade71f1de4540cf5ca930d09e6eca24eb34ca728723a930b3327d0fd9da9b799fb7ad63359e324c9773284cf
|
|
7
|
+
data.tar.gz: 7e0aa84b67fa17b591343b5cafb9ec58dc5cdff3507dcbbefbfe044bfcbc63f56b8d1603f08317221f759e9a8a0bbf71d2f8ddb93c73a81bd11235386d308d35
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Release History: opentelemetry-config
|
|
2
2
|
|
|
3
|
+
### v0.2.0 / 2026-10-20
|
|
4
|
+
|
|
5
|
+
* ADDED: Add declarative configuration for logger_provider (#2439)
|
|
6
|
+
* ADDED: Substitute environment variables in configuration files (#2468)
|
|
7
|
+
* FIXED: Correct schema_url unsupported warning (#2466)
|
|
8
|
+
* FIXED: Parse nullable objects without properties as present (#2465)
|
|
9
|
+
|
|
10
|
+
### v0.1.1 / 2026-10-13
|
|
11
|
+
|
|
12
|
+
* FIXED: Ignore SDK env defaults in declarative config (#2429)
|
|
13
|
+
|
|
3
14
|
### v0.1.0 / 2026-09-29
|
|
4
15
|
|
|
5
16
|
* ADDED: Declarative configuration for trace_provider (#2161)
|
data/README.md
CHANGED
|
@@ -17,12 +17,13 @@ It works with:
|
|
|
17
17
|
- `opentelemetry-sdk` — Traces
|
|
18
18
|
- `opentelemetry-exporter-otlp` — OTLP HTTP exporter
|
|
19
19
|
- `opentelemetry-instrumentation-all` — Instrumentation for gems
|
|
20
|
+
- `opentelemetry-logs-sdk` — Logs (optional, see [Logs](#logs))
|
|
21
|
+
- `opentelemetry-exporter-otlp-logs` — OTLP HTTP log exporter (optional)
|
|
20
22
|
|
|
21
23
|
This code is still under development and is not a complete implementation of the declarative configuration specification. Until the code becomes stable, declarative configuration functionality will live outside stable OpenTelemetry libraries.
|
|
22
24
|
|
|
23
25
|
Some features we still need to implement include:
|
|
24
26
|
|
|
25
|
-
- Configuration file precedence over environment variables
|
|
26
27
|
- Using declarative configuration without a call in your code
|
|
27
28
|
- Declarative configuration instrumentation API and SDK
|
|
28
29
|
|
|
@@ -65,6 +66,54 @@ If you have a config file path at hand, call `configure_from_file` instead:
|
|
|
65
66
|
sdk = OpenTelemetry::Config.configure_from_file('/path/to/otel-config.yaml')
|
|
66
67
|
```
|
|
67
68
|
|
|
69
|
+
### Environment variables and SDK-specific settings
|
|
70
|
+
|
|
71
|
+
File-based configuration uses the values in the YAML file and the schema defaults
|
|
72
|
+
for omitted settings. It does not inherit the SDK's `OTEL_*` environment-variable
|
|
73
|
+
defaults.
|
|
74
|
+
|
|
75
|
+
To use an environment variable in the file, reference it in a value as
|
|
76
|
+
`${NAME}`, `${env:NAME}`, or `${NAME:-default}`. The default applies when the
|
|
77
|
+
variable is unset or empty. Use `$$` for a literal `$`. Values are typed after
|
|
78
|
+
substitution, so quote a reference to keep it a string.
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
resource:
|
|
82
|
+
attributes:
|
|
83
|
+
- name: service.name
|
|
84
|
+
value: ${OTEL_SERVICE_NAME:-unknown_service}
|
|
85
|
+
tracer_provider:
|
|
86
|
+
processors:
|
|
87
|
+
- batch:
|
|
88
|
+
exporter:
|
|
89
|
+
otlp_http:
|
|
90
|
+
endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4318}/v1/traces
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Some Ruby-specific SDK settings have no equivalent in the configuration schema:
|
|
94
|
+
|
|
95
|
+
- `OTEL_RUBY_BSP_START_THREAD_ON_BOOT` is ignored. A configured batch span
|
|
96
|
+
processor starts its worker thread during construction. Applications that need
|
|
97
|
+
to delay worker startup should use programmatic SDK configuration instead.
|
|
98
|
+
- `OTEL_RUBY_EXPORTER_OTLP_SSL_VERIFY_NONE` and
|
|
99
|
+
`OTEL_RUBY_EXPORTER_OTLP_SSL_VERIFY_PEER` are ignored. The OTLP HTTP exporter
|
|
100
|
+
verifies the server certificate. For a private certificate authority, set
|
|
101
|
+
`tls.ca_file` rather than disabling verification. For mutual TLS, also set
|
|
102
|
+
`tls.cert_file` and `tls.key_file`.
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
tracer_provider:
|
|
106
|
+
processors:
|
|
107
|
+
- batch:
|
|
108
|
+
exporter:
|
|
109
|
+
otlp_http:
|
|
110
|
+
endpoint: https://collector.example.com:4318/v1/traces
|
|
111
|
+
tls:
|
|
112
|
+
ca_file: /path/to/ca.pem
|
|
113
|
+
cert_file: /path/to/client.pem
|
|
114
|
+
key_file: /path/to/client-key.pem
|
|
115
|
+
```
|
|
116
|
+
|
|
68
117
|
### Parse, create, and install
|
|
69
118
|
|
|
70
119
|
`configure` is a convenience wrapper around the three [SDK operations][sdk-operations]. Call them individually when you need to inspect the configuration model or delay installing the global state:
|
|
@@ -156,6 +205,35 @@ propagator:
|
|
|
156
205
|
|
|
157
206
|
Supported propagator names: `tracecontext`, `baggage`, `b3`, `b3multi`, `jaeger`, `ottrace`, `xray`, `google_cloud_trace_context`.
|
|
158
207
|
|
|
208
|
+
### Logs
|
|
209
|
+
|
|
210
|
+
Logs support is optional. Add `opentelemetry-logs-sdk` to your Gemfile, along with `opentelemetry-exporter-otlp-logs` if you use the `otlp_http` exporter, and require them before calling `configure`. If a required gem isn't loaded, the logger provider or processor that needs it is skipped with a warning.
|
|
211
|
+
|
|
212
|
+
```ruby
|
|
213
|
+
require 'opentelemetry-sdk'
|
|
214
|
+
require 'opentelemetry-logs-sdk'
|
|
215
|
+
require 'opentelemetry-exporter-otlp-logs'
|
|
216
|
+
require 'opentelemetry-config'
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The configured logger provider is installed as `OpenTelemetry.logger_provider`.
|
|
220
|
+
|
|
221
|
+
```yaml
|
|
222
|
+
logger_provider:
|
|
223
|
+
limits:
|
|
224
|
+
attribute_count_limit: 128
|
|
225
|
+
processors:
|
|
226
|
+
- batch:
|
|
227
|
+
exporter:
|
|
228
|
+
otlp_http:
|
|
229
|
+
endpoint: http://localhost:4318/v1/logs
|
|
230
|
+
- simple:
|
|
231
|
+
exporter:
|
|
232
|
+
console:
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Supported processors: `batch`, `simple`. Supported exporters: `console`, `otlp_http`.
|
|
236
|
+
|
|
159
237
|
## Examples
|
|
160
238
|
|
|
161
239
|
A runnable example application is available in the [`example/`][example-dir] directory. It demonstrates traces configured from YAML with console output.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright The OpenTelemetry Authors
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
|
|
7
|
+
module OpenTelemetry
|
|
8
|
+
module Config
|
|
9
|
+
# Schema defaults for omitted or null properties. Keys use schema names;
|
|
10
|
+
# durations are in milliseconds and are converted by the builders.
|
|
11
|
+
module Defaults
|
|
12
|
+
BATCH_SPAN_PROCESSOR = {
|
|
13
|
+
schedule_delay: 5_000,
|
|
14
|
+
export_timeout: 30_000,
|
|
15
|
+
max_queue_size: 2048,
|
|
16
|
+
max_export_batch_size: 512
|
|
17
|
+
}.freeze
|
|
18
|
+
|
|
19
|
+
SPAN_LIMITS = {
|
|
20
|
+
attribute_count_limit: 128,
|
|
21
|
+
attribute_value_length_limit: nil,
|
|
22
|
+
event_count_limit: 128,
|
|
23
|
+
link_count_limit: 128,
|
|
24
|
+
event_attribute_count_limit: 128,
|
|
25
|
+
link_attribute_count_limit: 128
|
|
26
|
+
}.freeze
|
|
27
|
+
|
|
28
|
+
OTLP_HTTP_EXPORTER = {
|
|
29
|
+
compression: 'none',
|
|
30
|
+
timeout: 10_000
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
OTLP_HTTP_TRACES_ENDPOINT = 'http://localhost:4318/v1/traces'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private_constant :Defaults
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright The OpenTelemetry Authors
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
|
|
7
|
+
module OpenTelemetry
|
|
8
|
+
module Config
|
|
9
|
+
# Loads configuration file YAML with environment variable substitution.
|
|
10
|
+
#
|
|
11
|
+
# References of the form +${NAME}+, +${env:NAME}+, and +${NAME:-default}+ are
|
|
12
|
+
# replaced in scalar values, and +$$+ escapes a literal +$+. Mapping keys are
|
|
13
|
+
# left untouched. Types are resolved after substitution, so a plain
|
|
14
|
+
# +${PORT}+ loads as an Integer while a quoted +"${PORT}"+ stays a String.
|
|
15
|
+
module EnvSubstitution
|
|
16
|
+
# Raised when a configuration file contains an invalid substitution reference.
|
|
17
|
+
class Error < StandardError; end
|
|
18
|
+
|
|
19
|
+
# A colon followed by "-" starts a default value, not a prefix.
|
|
20
|
+
REFERENCE = /\$\{(?:(?<prefix>[a-zA-Z][a-zA-Z0-9_]*):(?!-))?(?<content>[^}]+)\}/
|
|
21
|
+
ENV_REFERENCE = /\A(?<name>[a-zA-Z_][a-zA-Z0-9_]*)(?::-(?<default>[^\n]*))?\z/
|
|
22
|
+
PERMITTED_CLASSES = %w[Date Time].freeze
|
|
23
|
+
private_constant :REFERENCE, :ENV_REFERENCE, :PERMITTED_CLASSES
|
|
24
|
+
|
|
25
|
+
module_function
|
|
26
|
+
|
|
27
|
+
# Parses YAML and substitutes environment variables in its scalar values.
|
|
28
|
+
#
|
|
29
|
+
# @param content [String] YAML document
|
|
30
|
+
# @param env [Hash{String => String}] environment variables to substitute
|
|
31
|
+
# @return [Object, nil] the loaded document, or nil when it is empty
|
|
32
|
+
# @raise [Error] when a substitution reference is invalid
|
|
33
|
+
# @raise [Psych::Exception] when the YAML is invalid or uses a disallowed
|
|
34
|
+
# class or alias
|
|
35
|
+
def load(content, env = ENV)
|
|
36
|
+
document = Psych.parse(content)
|
|
37
|
+
return unless document
|
|
38
|
+
|
|
39
|
+
substitute_node(document, env)
|
|
40
|
+
|
|
41
|
+
class_loader = Psych::ClassLoader::Restricted.new(PERMITTED_CLASSES, [])
|
|
42
|
+
scanner = Psych::ScalarScanner.new(class_loader)
|
|
43
|
+
Psych::Visitors::NoAliasRuby.new(scanner, class_loader).accept(document)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Substitutes environment variable references in a string.
|
|
47
|
+
#
|
|
48
|
+
# @param value [String]
|
|
49
|
+
# @param env [Hash{String => String}] environment variables to substitute
|
|
50
|
+
# @return [String]
|
|
51
|
+
# @raise [Error] when a substitution reference is invalid
|
|
52
|
+
def substitute(value, env = ENV)
|
|
53
|
+
# Split on escapes first so a "$" they produce never starts a reference.
|
|
54
|
+
value.split('$$', -1).map do |segment|
|
|
55
|
+
segment.gsub(REFERENCE) { resolve(Regexp.last_match, env) }
|
|
56
|
+
end.join('$')
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Substitutes scalar values in a node tree, skipping mapping keys.
|
|
60
|
+
def substitute_node(node, env)
|
|
61
|
+
case node
|
|
62
|
+
when Psych::Nodes::Scalar
|
|
63
|
+
node.value = substitute(node.value, env)
|
|
64
|
+
when Psych::Nodes::Mapping
|
|
65
|
+
node.children.each_slice(2) { |_key, value| substitute_node(value, env) }
|
|
66
|
+
else
|
|
67
|
+
Array(node.children).each { |child| substitute_node(child, env) }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Returns the replacement for a matched reference.
|
|
72
|
+
def resolve(match, env)
|
|
73
|
+
reference = ENV_REFERENCE.match(match[:content]) if match[:prefix].nil? || match[:prefix] == 'env'
|
|
74
|
+
raise Error, "invalid substitution reference #{match[0]}" unless reference
|
|
75
|
+
|
|
76
|
+
value = env[reference[:name]]
|
|
77
|
+
return value unless value.nil? || value.empty?
|
|
78
|
+
|
|
79
|
+
reference[:default].to_s
|
|
80
|
+
end
|
|
81
|
+
private_class_method :substitute_node, :resolve
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -12,6 +12,15 @@ module OpenTelemetry
|
|
|
12
12
|
module Config
|
|
13
13
|
# Generated struct definitions mirroring the OpenTelemetry configuration schema.
|
|
14
14
|
module Model
|
|
15
|
+
# Parses the nullable object at +key+ with +klass+. An explicit null
|
|
16
|
+
# parses as an object with every property omitted.
|
|
17
|
+
def self.nullable_from_hash(klass, h, key)
|
|
18
|
+
return nil unless h.key?(key)
|
|
19
|
+
|
|
20
|
+
value = h[key]
|
|
21
|
+
klass.from_hash(value.nil? ? {} : value)
|
|
22
|
+
end
|
|
23
|
+
|
|
15
24
|
Aggregation = Struct.new(
|
|
16
25
|
:default,
|
|
17
26
|
:drop,
|
|
@@ -27,8 +36,8 @@ module OpenTelemetry
|
|
|
27
36
|
new(
|
|
28
37
|
default: h.key?('default'),
|
|
29
38
|
drop: h.key?('drop'),
|
|
30
|
-
explicit_bucket_histogram:
|
|
31
|
-
base2_exponential_bucket_histogram:
|
|
39
|
+
explicit_bucket_histogram: Model.nullable_from_hash(ExplicitBucketHistogramAggregation, h, 'explicit_bucket_histogram'),
|
|
40
|
+
base2_exponential_bucket_histogram: Model.nullable_from_hash(Base2ExponentialBucketHistogramAggregation, h, 'base2_exponential_bucket_histogram'),
|
|
32
41
|
last_value: h.key?('last_value'),
|
|
33
42
|
sum: h.key?('sum')
|
|
34
43
|
)
|
|
@@ -276,8 +285,8 @@ module OpenTelemetry
|
|
|
276
285
|
always_off: h.key?('always_off'),
|
|
277
286
|
always_on: h.key?('always_on'),
|
|
278
287
|
parent_threshold: ExperimentalComposableParentThresholdSampler.from_hash(h['parent_threshold']),
|
|
279
|
-
probability:
|
|
280
|
-
rule_based:
|
|
288
|
+
probability: Model.nullable_from_hash(ExperimentalComposableProbabilitySampler, h, 'probability'),
|
|
289
|
+
rule_based: Model.nullable_from_hash(ExperimentalComposableRuleBasedSampler, h, 'rule_based'),
|
|
281
290
|
additional_properties: h.except('always_off', 'always_on', 'parent_threshold', 'probability', 'rule_based')
|
|
282
291
|
)
|
|
283
292
|
end
|
|
@@ -736,9 +745,9 @@ module OpenTelemetry
|
|
|
736
745
|
return nil unless h.is_a?(Hash)
|
|
737
746
|
|
|
738
747
|
new(
|
|
739
|
-
otlp_http:
|
|
740
|
-
otlp_grpc:
|
|
741
|
-
otlp_file_development:
|
|
748
|
+
otlp_http: Model.nullable_from_hash(OtlpHttpExporter, h, 'otlp_http'),
|
|
749
|
+
otlp_grpc: Model.nullable_from_hash(OtlpGrpcExporter, h, 'otlp_grpc'),
|
|
750
|
+
otlp_file_development: Model.nullable_from_hash(ExperimentalOtlpFileExporter, h, 'otlp_file/development'),
|
|
742
751
|
console: h.key?('console'),
|
|
743
752
|
additional_properties: h.except('otlp_http', 'otlp_grpc', 'otlp_file/development', 'console')
|
|
744
753
|
)
|
|
@@ -907,7 +916,7 @@ module OpenTelemetry
|
|
|
907
916
|
|
|
908
917
|
new(
|
|
909
918
|
endpoint: h['endpoint'],
|
|
910
|
-
tls:
|
|
919
|
+
tls: Model.nullable_from_hash(GrpcTls, h, 'tls'),
|
|
911
920
|
headers: Array(h['headers']).filter_map { |e| NameStringValuePair.from_hash(e) },
|
|
912
921
|
headers_list: h['headers_list'],
|
|
913
922
|
compression: h['compression'],
|
|
@@ -932,7 +941,7 @@ module OpenTelemetry
|
|
|
932
941
|
|
|
933
942
|
new(
|
|
934
943
|
endpoint: h['endpoint'],
|
|
935
|
-
tls:
|
|
944
|
+
tls: Model.nullable_from_hash(GrpcTls, h, 'tls'),
|
|
936
945
|
headers: Array(h['headers']).filter_map { |e| NameStringValuePair.from_hash(e) },
|
|
937
946
|
headers_list: h['headers_list'],
|
|
938
947
|
compression: h['compression'],
|
|
@@ -958,7 +967,7 @@ module OpenTelemetry
|
|
|
958
967
|
|
|
959
968
|
new(
|
|
960
969
|
endpoint: h['endpoint'],
|
|
961
|
-
tls:
|
|
970
|
+
tls: Model.nullable_from_hash(HttpTls, h, 'tls'),
|
|
962
971
|
headers: Array(h['headers']).filter_map { |e| NameStringValuePair.from_hash(e) },
|
|
963
972
|
headers_list: h['headers_list'],
|
|
964
973
|
compression: h['compression'],
|
|
@@ -985,7 +994,7 @@ module OpenTelemetry
|
|
|
985
994
|
|
|
986
995
|
new(
|
|
987
996
|
endpoint: h['endpoint'],
|
|
988
|
-
tls:
|
|
997
|
+
tls: Model.nullable_from_hash(HttpTls, h, 'tls'),
|
|
989
998
|
headers: Array(h['headers']).filter_map { |e| NameStringValuePair.from_hash(e) },
|
|
990
999
|
headers_list: h['headers_list'],
|
|
991
1000
|
compression: h['compression'],
|
|
@@ -1063,7 +1072,7 @@ module OpenTelemetry
|
|
|
1063
1072
|
return nil unless h.is_a?(Hash)
|
|
1064
1073
|
|
|
1065
1074
|
new(
|
|
1066
|
-
prometheus_development:
|
|
1075
|
+
prometheus_development: Model.nullable_from_hash(ExperimentalPrometheusMetricExporter, h, 'prometheus/development'),
|
|
1067
1076
|
additional_properties: h.except('prometheus/development')
|
|
1068
1077
|
)
|
|
1069
1078
|
end
|
|
@@ -1098,10 +1107,10 @@ module OpenTelemetry
|
|
|
1098
1107
|
return nil unless h.is_a?(Hash)
|
|
1099
1108
|
|
|
1100
1109
|
new(
|
|
1101
|
-
otlp_http:
|
|
1102
|
-
otlp_grpc:
|
|
1103
|
-
otlp_file_development:
|
|
1104
|
-
console:
|
|
1110
|
+
otlp_http: Model.nullable_from_hash(OtlpHttpMetricExporter, h, 'otlp_http'),
|
|
1111
|
+
otlp_grpc: Model.nullable_from_hash(OtlpGrpcMetricExporter, h, 'otlp_grpc'),
|
|
1112
|
+
otlp_file_development: Model.nullable_from_hash(ExperimentalOtlpFileMetricExporter, h, 'otlp_file/development'),
|
|
1113
|
+
console: Model.nullable_from_hash(ConsoleMetricExporter, h, 'console'),
|
|
1105
1114
|
additional_properties: h.except('otlp_http', 'otlp_grpc', 'otlp_file/development', 'console')
|
|
1106
1115
|
)
|
|
1107
1116
|
end
|
|
@@ -1144,10 +1153,10 @@ module OpenTelemetry
|
|
|
1144
1153
|
always_off: h.key?('always_off'),
|
|
1145
1154
|
always_on: h.key?('always_on'),
|
|
1146
1155
|
composite_development: ExperimentalComposableSampler.from_hash(h['composite/development']),
|
|
1147
|
-
jaeger_remote_development:
|
|
1148
|
-
parent_based:
|
|
1149
|
-
probability_development:
|
|
1150
|
-
trace_id_ratio_based:
|
|
1156
|
+
jaeger_remote_development: Model.nullable_from_hash(ExperimentalJaegerRemoteSampler, h, 'jaeger_remote/development'),
|
|
1157
|
+
parent_based: Model.nullable_from_hash(ParentBasedSampler, h, 'parent_based'),
|
|
1158
|
+
probability_development: Model.nullable_from_hash(ExperimentalProbabilitySampler, h, 'probability/development'),
|
|
1159
|
+
trace_id_ratio_based: Model.nullable_from_hash(TraceIdRatioBasedSampler, h, 'trace_id_ratio_based'),
|
|
1151
1160
|
additional_properties: h.except('always_off', 'always_on', 'composite/development', 'jaeger_remote/development', 'parent_based', 'probability/development', 'trace_id_ratio_based')
|
|
1152
1161
|
)
|
|
1153
1162
|
end
|
|
@@ -1191,9 +1200,9 @@ module OpenTelemetry
|
|
|
1191
1200
|
return nil unless h.is_a?(Hash)
|
|
1192
1201
|
|
|
1193
1202
|
new(
|
|
1194
|
-
otlp_http:
|
|
1195
|
-
otlp_grpc:
|
|
1196
|
-
otlp_file_development:
|
|
1203
|
+
otlp_http: Model.nullable_from_hash(OtlpHttpExporter, h, 'otlp_http'),
|
|
1204
|
+
otlp_grpc: Model.nullable_from_hash(OtlpGrpcExporter, h, 'otlp_grpc'),
|
|
1205
|
+
otlp_file_development: Model.nullable_from_hash(ExperimentalOtlpFileExporter, h, 'otlp_file/development'),
|
|
1197
1206
|
console: h.key?('console'),
|
|
1198
1207
|
additional_properties: h.except('otlp_http', 'otlp_grpc', 'otlp_file/development', 'console')
|
|
1199
1208
|
)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright The OpenTelemetry Authors
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
module OpenTelemetry
|
|
7
|
+
module Config
|
|
8
|
+
# Logs component builder for configuring LoggerProvider from declarative config.
|
|
9
|
+
module Logs
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
# Builds a LoggerProvider from the parsed YAML logger_provider config.
|
|
13
|
+
# Returns nil if config is nil or opentelemetry-logs-sdk isn't loaded.
|
|
14
|
+
def build_logger_provider(config, resource)
|
|
15
|
+
return unless config
|
|
16
|
+
|
|
17
|
+
unless defined?(OpenTelemetry::SDK::Logs::LoggerProvider)
|
|
18
|
+
OpenTelemetry.logger.warn('logger_provider is configured but opentelemetry-logs-sdk is not loaded. ' \
|
|
19
|
+
'Add `gem "opentelemetry-logs-sdk"` to your Gemfile.')
|
|
20
|
+
return
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
lp = OpenTelemetry::SDK::Logs::LoggerProvider.new(
|
|
24
|
+
resource: resource,
|
|
25
|
+
log_record_limits: build_log_record_limits(config.limits)
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
Array(config.processors).each do |proc_cfg|
|
|
29
|
+
lp.add_log_record_processor(build_log_record_processor(proc_cfg))
|
|
30
|
+
rescue StandardError => e
|
|
31
|
+
OpenTelemetry.logger.warn("Failed to build log record processor: #{e.message}")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
lp
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Builds a log record processor (simple or batch) from config.
|
|
38
|
+
def build_log_record_processor(proc_cfg)
|
|
39
|
+
raise ArgumentError, 'must not specify multiple log record processor types' if proc_cfg.batch && proc_cfg.simple
|
|
40
|
+
|
|
41
|
+
if proc_cfg.batch
|
|
42
|
+
build_batch_log_record_processor(proc_cfg.batch)
|
|
43
|
+
elsif proc_cfg.simple
|
|
44
|
+
build_simple_log_record_processor(proc_cfg.simple)
|
|
45
|
+
else
|
|
46
|
+
raise ArgumentError, 'unsupported log record processor type, must be one of simple or batch'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Builds a BatchLogRecordProcessor with exporter and optional tuning options.
|
|
51
|
+
def build_batch_log_record_processor(cfg)
|
|
52
|
+
exporter = build_log_record_exporter(cfg.exporter)
|
|
53
|
+
opts = {
|
|
54
|
+
schedule_delay: cfg.schedule_delay&.to_f,
|
|
55
|
+
exporter_timeout: cfg.export_timeout&.to_f,
|
|
56
|
+
max_queue_size: cfg.max_queue_size&.to_i,
|
|
57
|
+
max_export_batch_size: cfg.max_export_batch_size&.to_i
|
|
58
|
+
}.compact
|
|
59
|
+
|
|
60
|
+
OpenTelemetry::SDK::Logs::Export::BatchLogRecordProcessor.new(exporter, **opts)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Builds a SimpleLogRecordProcessor wrapping the configured exporter.
|
|
64
|
+
def build_simple_log_record_processor(cfg)
|
|
65
|
+
OpenTelemetry::SDK::Logs::Export::SimpleLogRecordProcessor.new(build_log_record_exporter(cfg.exporter))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Builds a log record exporter from config; supports console and otlp_http.
|
|
69
|
+
def build_log_record_exporter(exp_cfg)
|
|
70
|
+
raise ArgumentError, 'no exporter config' unless exp_cfg
|
|
71
|
+
|
|
72
|
+
configured = 0
|
|
73
|
+
exporter = nil
|
|
74
|
+
|
|
75
|
+
if exp_cfg.console
|
|
76
|
+
configured += 1
|
|
77
|
+
exporter = OpenTelemetry::SDK::Logs::Export::ConsoleLogRecordExporter.new
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
if exp_cfg.otlp_http
|
|
81
|
+
configured += 1
|
|
82
|
+
exporter = build_otlp_http_log_record_exporter(exp_cfg.otlp_http)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
raise ArgumentError, 'must not specify multiple exporters' if configured > 1
|
|
86
|
+
raise ArgumentError, 'no valid log record exporter' if exporter.nil?
|
|
87
|
+
|
|
88
|
+
exporter
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Builds an OTLP HTTP log record exporter from the given endpoint, headers, and TLS config.
|
|
92
|
+
def build_otlp_http_log_record_exporter(cfg)
|
|
93
|
+
unless defined?(OpenTelemetry::Exporter::OTLP::Logs::LogsExporter)
|
|
94
|
+
raise ArgumentError, 'otlp_http requires opentelemetry-exporter-otlp-logs. ' \
|
|
95
|
+
'Add `gem "opentelemetry-exporter-otlp-logs"` to your Gemfile.'
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
headers = Trace.headers_to_hash(cfg)
|
|
99
|
+
opts = {
|
|
100
|
+
endpoint: cfg.endpoint,
|
|
101
|
+
certificate_file: cfg.tls&.ca_file,
|
|
102
|
+
client_certificate_file: cfg.tls&.cert_file,
|
|
103
|
+
client_key_file: cfg.tls&.key_file,
|
|
104
|
+
headers: headers.empty? ? nil : headers,
|
|
105
|
+
compression: cfg.compression,
|
|
106
|
+
timeout: cfg.timeout && (cfg.timeout / 1000.0)
|
|
107
|
+
}.compact
|
|
108
|
+
|
|
109
|
+
OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(**opts)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Builds LogRecordLimits from config; returns the SDK default when config is nil.
|
|
113
|
+
def build_log_record_limits(limits_cfg)
|
|
114
|
+
return OpenTelemetry::SDK::Logs::LogRecordLimits::DEFAULT unless limits_cfg
|
|
115
|
+
|
|
116
|
+
opts = {
|
|
117
|
+
attribute_count_limit: limits_cfg.attribute_count_limit,
|
|
118
|
+
attribute_length_limit: limits_cfg.attribute_value_length_limit
|
|
119
|
+
}.compact
|
|
120
|
+
|
|
121
|
+
OpenTelemetry::SDK::Logs::LogRecordLimits.new(**opts)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
private_constant :Logs
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -11,7 +11,7 @@ module OpenTelemetry
|
|
|
11
11
|
|
|
12
12
|
# Priority: attributes > attribute_list > detected > base
|
|
13
13
|
def build_resource(resource_cfg)
|
|
14
|
-
base =
|
|
14
|
+
base = default_resource
|
|
15
15
|
|
|
16
16
|
return base unless resource_cfg
|
|
17
17
|
|
|
@@ -31,13 +31,27 @@ module OpenTelemetry
|
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
OpenTelemetry.logger.warn('Config: schema_url is supported; ignoring.') if resource_cfg.schema_url
|
|
34
|
+
OpenTelemetry.logger.warn('Config: schema_url is not supported; ignoring.') if resource_cfg.schema_url
|
|
35
35
|
|
|
36
36
|
attrs = detected.merge(explicit)
|
|
37
37
|
custom = OpenTelemetry::SDK::Resources::Resource.create(attrs)
|
|
38
38
|
base.merge(custom)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
# Builds the intrinsic SDK resource without consulting OTEL_* environment
|
|
42
|
+
# variables. File-based configuration and environment configuration are
|
|
43
|
+
# intentionally separate sources.
|
|
44
|
+
def default_resource
|
|
45
|
+
resource_class = OpenTelemetry::SDK::Resources::Resource
|
|
46
|
+
|
|
47
|
+
resource_class.create(
|
|
48
|
+
OpenTelemetry::SemanticConventions::Resource::SERVICE_NAME => 'unknown_service',
|
|
49
|
+
OpenTelemetry::SemanticConventions::Resource::TELEMETRY_SDK_NAME => 'opentelemetry',
|
|
50
|
+
OpenTelemetry::SemanticConventions::Resource::TELEMETRY_SDK_LANGUAGE => 'ruby',
|
|
51
|
+
OpenTelemetry::SemanticConventions::Resource::TELEMETRY_SDK_VERSION => OpenTelemetry::SDK::VERSION
|
|
52
|
+
).merge(resource_class.process)
|
|
53
|
+
end
|
|
54
|
+
|
|
41
55
|
# type coercion
|
|
42
56
|
def coerce_attribute_value(value, type)
|
|
43
57
|
case type
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
# Copyright The OpenTelemetry Authors
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
|
|
6
|
+
require 'openssl'
|
|
7
|
+
|
|
6
8
|
module OpenTelemetry
|
|
7
9
|
module Config
|
|
8
10
|
# Trace component builder for configuring TracerProvider from declarative config.
|
|
@@ -46,15 +48,17 @@ module OpenTelemetry
|
|
|
46
48
|
end
|
|
47
49
|
end
|
|
48
50
|
|
|
49
|
-
# Builds a BatchSpanProcessor with exporter and
|
|
51
|
+
# Builds a BatchSpanProcessor with exporter and schema defaults. Passing
|
|
52
|
+
# environment-backed options explicitly prevents it from reading OTEL_*.
|
|
50
53
|
def build_batch_span_processor(cfg)
|
|
51
54
|
exporter = build_span_exporter(cfg.exporter)
|
|
52
55
|
opts = {
|
|
53
|
-
schedule_delay: cfg.schedule_delay
|
|
54
|
-
exporter_timeout: cfg.export_timeout
|
|
55
|
-
max_queue_size: cfg.max_queue_size
|
|
56
|
-
max_export_batch_size: cfg.max_export_batch_size
|
|
57
|
-
|
|
56
|
+
schedule_delay: (cfg.schedule_delay || Defaults::BATCH_SPAN_PROCESSOR[:schedule_delay]).to_f,
|
|
57
|
+
exporter_timeout: (cfg.export_timeout || Defaults::BATCH_SPAN_PROCESSOR[:export_timeout]).to_f,
|
|
58
|
+
max_queue_size: (cfg.max_queue_size || Defaults::BATCH_SPAN_PROCESSOR[:max_queue_size]).to_i,
|
|
59
|
+
max_export_batch_size: (cfg.max_export_batch_size || Defaults::BATCH_SPAN_PROCESSOR[:max_export_batch_size]).to_i,
|
|
60
|
+
start_thread_on_boot: true
|
|
61
|
+
}
|
|
58
62
|
|
|
59
63
|
OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(exporter, **opts)
|
|
60
64
|
end
|
|
@@ -88,17 +92,19 @@ module OpenTelemetry
|
|
|
88
92
|
exporter
|
|
89
93
|
end
|
|
90
94
|
|
|
91
|
-
# Builds an OTLP HTTP span exporter from
|
|
95
|
+
# Builds an OTLP HTTP span exporter from declarative values and schema
|
|
96
|
+
# defaults, without falling back to exporter environment variables.
|
|
92
97
|
def build_otlp_http_span_exporter(cfg)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
OpenTelemetry::Exporter::OTLP::Exporter.new(
|
|
99
|
+
endpoint: cfg.endpoint || Defaults::OTLP_HTTP_TRACES_ENDPOINT,
|
|
100
|
+
certificate_file: cfg.tls&.ca_file,
|
|
101
|
+
client_certificate_file: cfg.tls&.cert_file,
|
|
102
|
+
client_key_file: cfg.tls&.key_file,
|
|
103
|
+
ssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
|
|
104
|
+
headers: headers_to_hash(cfg),
|
|
105
|
+
compression: cfg.compression || Defaults::OTLP_HTTP_EXPORTER[:compression],
|
|
106
|
+
timeout: (cfg.timeout || Defaults::OTLP_HTTP_EXPORTER[:timeout]) / 1000.0
|
|
107
|
+
)
|
|
102
108
|
end
|
|
103
109
|
|
|
104
110
|
# Builds a sampler from config; defaults to ParentBased(ALWAYS_ON).
|
|
@@ -139,20 +145,17 @@ module OpenTelemetry
|
|
|
139
145
|
s.parent_based(**opts)
|
|
140
146
|
end
|
|
141
147
|
|
|
142
|
-
# Builds SpanLimits from
|
|
148
|
+
# Builds SpanLimits from declarative values and schema defaults.
|
|
143
149
|
def build_span_limits(limits_cfg)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}.compact
|
|
154
|
-
|
|
155
|
-
OpenTelemetry::SDK::Trace::SpanLimits.new(**opts)
|
|
150
|
+
OpenTelemetry::SDK::Trace::SpanLimits.new(
|
|
151
|
+
attribute_count_limit: limits_cfg&.attribute_count_limit || Defaults::SPAN_LIMITS[:attribute_count_limit],
|
|
152
|
+
attribute_length_limit: limits_cfg&.attribute_value_length_limit || Defaults::SPAN_LIMITS[:attribute_value_length_limit],
|
|
153
|
+
event_count_limit: limits_cfg&.event_count_limit || Defaults::SPAN_LIMITS[:event_count_limit],
|
|
154
|
+
link_count_limit: limits_cfg&.link_count_limit || Defaults::SPAN_LIMITS[:link_count_limit],
|
|
155
|
+
event_attribute_count_limit: limits_cfg&.event_attribute_count_limit || Defaults::SPAN_LIMITS[:event_attribute_count_limit],
|
|
156
|
+
event_attribute_length_limit: nil,
|
|
157
|
+
link_attribute_count_limit: limits_cfg&.link_attribute_count_limit || Defaults::SPAN_LIMITS[:link_attribute_count_limit]
|
|
158
|
+
)
|
|
156
159
|
end
|
|
157
160
|
|
|
158
161
|
# Converts the OTLP exporter headers (array of NameStringValuePair structs)
|
data/lib/opentelemetry/config.rb
CHANGED
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
require 'date'
|
|
7
7
|
require 'yaml'
|
|
8
8
|
|
|
9
|
+
require_relative 'config/defaults'
|
|
10
|
+
require_relative 'config/env_substitution'
|
|
11
|
+
require_relative 'config/logs'
|
|
9
12
|
require_relative 'config/propagation'
|
|
10
13
|
require_relative 'config/resource'
|
|
11
14
|
require_relative 'config/constants'
|
|
@@ -47,13 +50,16 @@ module OpenTelemetry
|
|
|
47
50
|
end
|
|
48
51
|
|
|
49
52
|
content = File.read(path)
|
|
50
|
-
OpenTelemetry::Config::Model::OpenTelemetryConfiguration.from_hash(
|
|
53
|
+
OpenTelemetry::Config::Model::OpenTelemetryConfiguration.from_hash(EnvSubstitution.load(content))
|
|
51
54
|
rescue Errno::ENOENT => e
|
|
52
55
|
OpenTelemetry.logger.error("Config file not found: #{e.message}")
|
|
53
56
|
nil
|
|
54
57
|
rescue Psych::SyntaxError => e
|
|
55
58
|
OpenTelemetry.logger.error("YAML parse error: #{e.message}")
|
|
56
59
|
nil
|
|
60
|
+
rescue EnvSubstitution::Error => e
|
|
61
|
+
OpenTelemetry.logger.error("Config file substitution error: #{e.message}")
|
|
62
|
+
nil
|
|
57
63
|
end
|
|
58
64
|
|
|
59
65
|
# Creates the components described by a configuration model without
|
|
@@ -80,11 +86,13 @@ module OpenTelemetry
|
|
|
80
86
|
|
|
81
87
|
# tracer_provider will be noop if opentelemetry-sdk is not installed
|
|
82
88
|
tracer_provider = Trace.build_tracer_provider(config.tracer_provider, resource)
|
|
89
|
+
logger_provider = Logs.build_logger_provider(config.logger_provider, resource)
|
|
83
90
|
|
|
84
91
|
propagators = configure_propagation(config.propagator)
|
|
85
92
|
|
|
86
93
|
RubySDK.new(
|
|
87
94
|
tracer_provider: tracer_provider,
|
|
95
|
+
logger_provider: logger_provider,
|
|
88
96
|
propagator: propagators,
|
|
89
97
|
resource: resource
|
|
90
98
|
)
|
|
@@ -99,9 +107,21 @@ module OpenTelemetry
|
|
|
99
107
|
return ruby_sdk if ruby_sdk.equal?(NOOP_SDK)
|
|
100
108
|
|
|
101
109
|
OpenTelemetry.tracer_provider = ruby_sdk.tracer_provider if ruby_sdk.tracer_provider
|
|
110
|
+
install_logger_provider(ruby_sdk.logger_provider) if ruby_sdk.logger_provider
|
|
102
111
|
OpenTelemetry.propagation = ruby_sdk.propagator if ruby_sdk.propagator
|
|
103
112
|
ruby_sdk
|
|
104
113
|
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
def install_logger_provider(provider)
|
|
118
|
+
if OpenTelemetry.respond_to?(:logger_provider=)
|
|
119
|
+
OpenTelemetry.logger_provider = provider
|
|
120
|
+
else
|
|
121
|
+
OpenTelemetry.logger.warn('Cannot install the configured logger provider: OpenTelemetry.logger_provider= ' \
|
|
122
|
+
'is not defined. Require opentelemetry-logs-sdk.')
|
|
123
|
+
end
|
|
124
|
+
end
|
|
105
125
|
end
|
|
106
126
|
end
|
|
107
127
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: opentelemetry-config
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- OpenTelemetry Authors
|
|
@@ -43,14 +43,14 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: 0.34
|
|
46
|
+
version: '0.34'
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 0.34
|
|
53
|
+
version: '0.34'
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: opentelemetry-sdk
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -78,7 +78,10 @@ files:
|
|
|
78
78
|
- lib/opentelemetry-config.rb
|
|
79
79
|
- lib/opentelemetry/config.rb
|
|
80
80
|
- lib/opentelemetry/config/constants.rb
|
|
81
|
+
- lib/opentelemetry/config/defaults.rb
|
|
82
|
+
- lib/opentelemetry/config/env_substitution.rb
|
|
81
83
|
- lib/opentelemetry/config/generated_constants.rb
|
|
84
|
+
- lib/opentelemetry/config/logs.rb
|
|
82
85
|
- lib/opentelemetry/config/propagation.rb
|
|
83
86
|
- lib/opentelemetry/config/resource.rb
|
|
84
87
|
- lib/opentelemetry/config/trace.rb
|
|
@@ -87,10 +90,10 @@ homepage: https://github.com/open-telemetry/opentelemetry-ruby
|
|
|
87
90
|
licenses:
|
|
88
91
|
- Apache-2.0
|
|
89
92
|
metadata:
|
|
90
|
-
changelog_uri: https://rubydoc.info/gems/opentelemetry-config/0.
|
|
91
|
-
source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/opentelemetry-config/v0.
|
|
93
|
+
changelog_uri: https://rubydoc.info/gems/opentelemetry-config/0.2.0/file/CHANGELOG.md
|
|
94
|
+
source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/opentelemetry-config/v0.2.0/config
|
|
92
95
|
bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby/issues
|
|
93
|
-
documentation_uri: https://rubydoc.info/gems/opentelemetry-config/0.
|
|
96
|
+
documentation_uri: https://rubydoc.info/gems/opentelemetry-config/0.2.0
|
|
94
97
|
rdoc_options: []
|
|
95
98
|
require_paths:
|
|
96
99
|
- lib
|