stack-service-base 0.0.2 → 0.0.4
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/lib/stack-service-base/open_telemetry.rb +181 -0
- data/lib/stack-service-base.rb +12 -0
- data/lib/version.rb +1 -1
- metadata +45 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 340d3036dfae55df21ac629aea2f177b890257e29e8d51d7c7ec975bff57ee0b
|
4
|
+
data.tar.gz: 76ab84fb603376f3a8f29901c5987cd4bf664625dd6a9bd533f20e928716a775
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d99472369e7dae16f8cfd8526e785a6dee35727e4f7e7b48e81a3509a295c9712883c8060d177f76cb56022d42055868f1ce3ee7cabd27163635a66bb9154bb9
|
7
|
+
data.tar.gz: 3d86d30f6fbcbcb06339d2cdfe03afbf51a58696177d88c4d7fc81e404454093ba0c4e00ef80ac228ebc41140dbf6569f6c405577df0c1ca126ea00cc24360d3
|
@@ -0,0 +1,181 @@
|
|
1
|
+
ENV['OTEL_LOG_LEVEL'] ||= 'debug'
|
2
|
+
ENV['OTEL_TRACES_EXPORTER'] ||= 'console,otlp'
|
3
|
+
|
4
|
+
unless defined? OTEL_ENABLED
|
5
|
+
OTEL_ENABLED = !ENV['OTEL_EXPORTER_OTLP_ENDPOINT'].to_s.empty?
|
6
|
+
end
|
7
|
+
$stdout.puts "OTEL_ENABLED: #{OTEL_ENABLED}"
|
8
|
+
|
9
|
+
# require 'async'
|
10
|
+
# require 'grape'
|
11
|
+
|
12
|
+
if OTEL_ENABLED
|
13
|
+
STACK_NAME = ENV['STACK_NAME'] || 'undefined_stack'
|
14
|
+
SERVICE_NAME = ENV['STACK_SERVICE_NAME'] || 'undefined_service'
|
15
|
+
ENV['OTEL_RESOURCE_ATTRIBUTES'] ||= "deployment.environment=#{STACK_NAME},service.name=#{SERVICE_NAME}"
|
16
|
+
ENV.select{ |k,v| k =~ /OTEL/}.each { |k,v| $stdout.puts "#{k}: #{v}"}
|
17
|
+
|
18
|
+
require 'opentelemetry/sdk'
|
19
|
+
require 'opentelemetry/exporter/otlp'
|
20
|
+
require 'opentelemetry/instrumentation/all'
|
21
|
+
require 'opentelemetry-api'
|
22
|
+
end
|
23
|
+
|
24
|
+
if defined? Async::Task and OTEL_ENABLED
|
25
|
+
module AsyncTaskOTELPatch
|
26
|
+
def initialize(parent = Task.current?, finished: nil, **options, &block)
|
27
|
+
ctx_ = OpenTelemetry::Context.current
|
28
|
+
|
29
|
+
block_otl = ->(t, *arguments){
|
30
|
+
OpenTelemetry::Context.with_current(ctx_) do
|
31
|
+
block.call t, *arguments
|
32
|
+
end
|
33
|
+
}
|
34
|
+
super parent, finished: , **options, &block_otl
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Async::Task.prepend AsyncTaskOTELPatch
|
39
|
+
end
|
40
|
+
|
41
|
+
def flatten_hash(hash, path = [], result = {})
|
42
|
+
hash.each do |k, v|
|
43
|
+
path += [k]
|
44
|
+
result[path.join('.')] = v.to_s if v.is_a?(String) || v.is_a?(Numeric)
|
45
|
+
flatten_hash(v, path, result) if v.is_a?(Hash) || v.is_a?(Array)
|
46
|
+
path.pop
|
47
|
+
end
|
48
|
+
result
|
49
|
+
end
|
50
|
+
|
51
|
+
if defined? LOGGER and OTEL_ENABLED
|
52
|
+
OpenTelemetry.logger = LOGGER
|
53
|
+
end
|
54
|
+
|
55
|
+
def otel_initialize
|
56
|
+
$stderr.puts "otl_configure: OTEL_ENABLED: #{OTEL_ENABLED}"
|
57
|
+
return unless OTEL_ENABLED
|
58
|
+
|
59
|
+
OpenTelemetry::SDK.configure do |c|
|
60
|
+
# c.service_name = SERVICE_NAME
|
61
|
+
c.use_all # enables all instrumentation!
|
62
|
+
end
|
63
|
+
|
64
|
+
at_exit do
|
65
|
+
OpenTelemetry.tracer_provider.force_flush
|
66
|
+
OpenTelemetry.tracer_provider.shutdown
|
67
|
+
end
|
68
|
+
|
69
|
+
$tracer_ = OpenTelemetry.tracer_provider.tracer(SERVICE_NAME)
|
70
|
+
|
71
|
+
otl_span "#{SERVICE_NAME} start", {
|
72
|
+
'stack.name': ENV['STACK_NAME'],
|
73
|
+
'stack.service.name': ENV['STACK_SERVICE_NAME'],
|
74
|
+
'org.opencontainers.image.title': ENV['ORG_OPENCONTAINERS_IMAGE_TITLE'],
|
75
|
+
'org.opencontainers.image.url': ENV['ORG_OPENCONTAINERS_IMAGE_URL'],
|
76
|
+
'org.opencontainers.image.source': ENV['ORG_OPENCONTAINERS_IMAGE_SOURCE'],
|
77
|
+
'org.opencontainers.image.created': ENV['ORG_OPENCONTAINERS_IMAGE_CREATED'],
|
78
|
+
'com.gitlab.ci.commt.timestamp': ENV['COM_GITLAB_CI_COMMIT_TIMESTAMP'],
|
79
|
+
'com.gitlab.ci.tag': ENV['COM_GITLAB_CI_TAG'],
|
80
|
+
RACK_ENV: ENV['RACK_ENV'],
|
81
|
+
NODE_ENV: ENV['NODE_ENV'],
|
82
|
+
SERVER_ENV: ENV['SERVER_ENV'],
|
83
|
+
} do |span|
|
84
|
+
|
85
|
+
span.add_event("not-working in kibana APM", attributes:{
|
86
|
+
event: 'Success',
|
87
|
+
message: 'Get data from elastic Success'
|
88
|
+
}.transform_keys(&:to_s) )
|
89
|
+
# span.status = OpenTelemetry::Trace::Status.error("error message here!")
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
if defined? Sequel and OTEL_ENABLED
|
95
|
+
class Sequel::Database
|
96
|
+
alias old_test_connection test_connection
|
97
|
+
|
98
|
+
def test_connection(...)
|
99
|
+
OpenTelemetry::Common::Utilities.untraced do
|
100
|
+
old_test_connection(...)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
alias old_valid_connection? valid_connection?
|
105
|
+
def valid_connection?(...)
|
106
|
+
OpenTelemetry::Common::Utilities.untraced do
|
107
|
+
old_valid_connection?(...)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def otl_span(name, attributes = {})
|
114
|
+
# span_ = OpenTelemetry::Trace.current_span
|
115
|
+
return yield(nil) unless OTEL_ENABLED
|
116
|
+
|
117
|
+
return yield(nil) unless $tracer_
|
118
|
+
$tracer_&.in_span(name, attributes: flatten_hash(attributes.transform_keys(&:to_s).transform_values{_1 || 'n/a'}) ) do |span|
|
119
|
+
yield span
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def otl_current_span
|
124
|
+
return unless OTEL_ENABLED
|
125
|
+
yield OpenTelemetry::Trace.current_span
|
126
|
+
end
|
127
|
+
|
128
|
+
def otl_def(name)
|
129
|
+
original_method = self.respond_to?(:instance_method) ? instance_method(name) : method(name)
|
130
|
+
self.respond_to?(:remove_method) ? remove_method(name) : Object.send(:remove_method, name)
|
131
|
+
original_method = original_method.respond_to?(:unbind) ? original_method.unbind : original_method
|
132
|
+
|
133
|
+
define_method(name) do |*args, **kwargs, &block|
|
134
|
+
klass = self.respond_to?(:class_name) ? self.class_name : (self.respond_to?(:name) ? self.name : 'main')
|
135
|
+
otl_span("method: #{klass}.#{name}", {args: args.to_s, kwargs: kwargs.to_s}) do |span|
|
136
|
+
original_method.bind(self).call(*args, **kwargs, &block)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
if defined? OpenTelemetry::Instrumentation::Rack::Middlewares
|
142
|
+
OpenTelemetry::Instrumentation::Rack::Middlewares::TracerMiddleware.config[:url_quantization] = ->(path, env) {
|
143
|
+
"HTTP #{env['REQUEST_METHOD']} #{path}"
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
if OTEL_ENABLED
|
148
|
+
class OpenTelemetry::SDK::Trace::Span
|
149
|
+
alias add_attributes_old add_attributes
|
150
|
+
|
151
|
+
def add_attributes(attributes)
|
152
|
+
add_attributes_old flatten_hash attributes
|
153
|
+
.transform_keys(&:to_s)
|
154
|
+
.transform_values{ _1 || 'n/a' }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
if defined? Safrano::Request and OTEL_ENABLED
|
160
|
+
require 'odata/error'
|
161
|
+
|
162
|
+
class Safrano::Request
|
163
|
+
def process
|
164
|
+
begin
|
165
|
+
@response = Safrano::Response.new
|
166
|
+
before.tap_error { |err| dispatch_error(err) }
|
167
|
+
.tap_valid { |_res| dispatch }
|
168
|
+
|
169
|
+
rescue Sequel::Error => e
|
170
|
+
OpenTelemetry::Trace.current_span.tap do |span|
|
171
|
+
span.record_exception(e)
|
172
|
+
span.status = OpenTelemetry::Trace::Status.error("Unhandled exception of type: #{e.class}")
|
173
|
+
end
|
174
|
+
dispatch_error(Safrano::SequelExceptionError.new(e))
|
175
|
+
end
|
176
|
+
@response.finish
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
|
data/lib/stack-service-base.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
+
require 'stack-service-base/open_telemetry'
|
2
|
+
|
1
3
|
module StackServiceBase
|
2
4
|
class << self
|
3
5
|
def rack_setup app
|
6
|
+
# skip if called within Rspec task
|
7
|
+
# TODO: warn if called not within Rspec task but with a wrong app class
|
8
|
+
return unless app.respond_to? :use
|
9
|
+
|
4
10
|
app.instance_eval do
|
5
11
|
if ENV.fetch('PROMETHEUS_METRICS_EXPORT', 'true') == 'true'
|
6
12
|
require 'stack-service-base/prometheus'
|
@@ -9,6 +15,12 @@ module StackServiceBase
|
|
9
15
|
use Prometheus::Middleware::Collector
|
10
16
|
use Prometheus::Middleware::Exporter
|
11
17
|
end
|
18
|
+
|
19
|
+
if OTEL_ENABLED
|
20
|
+
otel_initialize
|
21
|
+
|
22
|
+
end
|
23
|
+
|
12
24
|
end
|
13
25
|
end
|
14
26
|
end
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stack-service-base
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ''
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-05-
|
11
|
+
date: 2025-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: prometheus-client
|
@@ -24,6 +24,48 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: opentelemetry-sdk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: opentelemetry-exporter-otlp
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: opentelemetry-instrumentation-all
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
27
69
|
- !ruby/object:Gem::Dependency
|
28
70
|
name: rake
|
29
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -115,6 +157,7 @@ extensions: []
|
|
115
157
|
extra_rdoc_files: []
|
116
158
|
files:
|
117
159
|
- lib/stack-service-base.rb
|
160
|
+
- lib/stack-service-base/open_telemetry.rb
|
118
161
|
- lib/stack-service-base/prometheus.rb
|
119
162
|
- lib/stack-service-base/prometheus_parser.rb
|
120
163
|
- lib/version.rb
|