stack-service-base 0.0.3 → 0.0.5

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: 8bba98b01bd4c3b322fe9ccef0ae2fd8fa910e19f67d6d42c8d8c8f472e1f739
4
- data.tar.gz: 063cdf24707f9523bf8892677826a31713b850021d6bda4b31b3e6922e7f7f7f
3
+ metadata.gz: fa21c7280d1fea0d4989a72123bb927756c126d8ab0dda9d155392e70a78d113
4
+ data.tar.gz: 8bdb53ae89c3bf2480bfb89ac3c056d744678a25f04fef31a50ef524d4c40cfe
5
5
  SHA512:
6
- metadata.gz: a300526788946d772dc4241132a1ccffc311c70a6f004ffd91b41f79f8bf26f176845abe56becbc208b40dcece8c319a582bd1ee645aedffd07ae797def6abed
7
- data.tar.gz: 50822031975f44ac1871ba31dd616bab4d657ba4cdd7ae17a7de7153540a2c2878a3308f4693327b9f51cfb0cc198d1a7a0121ed467e2073650f137646665b38
6
+ metadata.gz: 79cf73453d710651ad3c8f9da19b1e29af8edd9b5af0097bf68b77fcd3a755ca4116c0a01d980783e9023c71b8c3d20b1836a792074985cc44e3ee487540f65e
7
+ data.tar.gz: 4a14e9d3b7ca39ebeb02e8aaef4d5d3a83988ba4b5d46471dd6484640bd8970da5f487c1ca5e121591a23d407b716a3205e80405634b4679c81298a12e7224da
@@ -0,0 +1,141 @@
1
+ require 'console'
2
+ require 'fiber'
3
+
4
+ QUIET = ENV.fetch('CONSOLE_LEVEL', 'false') == 'true'
5
+ PERFORMANCE = ENV.fetch('PERFORMANCE', 'false') == 'true'
6
+
7
+ ENV['CONSOLE_LEVEL'] ||= 'all' unless QUIET || PERFORMANCE
8
+
9
+ CONSOLE_LOGGER = Class.new {
10
+ def <<(...) = Console.logger.info(...)
11
+ def info(...) = Console.logger.info(...)
12
+ def debug(...) = Console.logger.debug(...)
13
+ def debug1(...) = Console.logger.debug(...)
14
+ def debug2(...) = Console.logger.debug(...)
15
+ def debug3(...) = Console.logger.debug(...)
16
+ def warn(...) = Console.logger.warn(...)
17
+ def error(...) = Console.logger.error(...)
18
+ def fatal(...) = Console.logger.fatal(...)
19
+ }.new
20
+
21
+ if QUIET
22
+ ENV['CONSOLE_LEVEL'] = 'error'
23
+ LOGGER = CONSOLE_LOGGER
24
+
25
+ # LOGGER = Class.new {
26
+ # def <<(...) = nil
27
+ # def info(...) = nil
28
+ # def debug(...) = nil
29
+ # def debug1(...) = nil
30
+ # def debug2(...) = nil
31
+ # def debug3(...) = nil
32
+ # def warn(...) = nil
33
+ # def error(...) = nil
34
+ # def fatal(...) = nil
35
+ # }.new
36
+ else
37
+ $stdout.sync = true
38
+ $stderr.sync = true
39
+ # class Fiber
40
+ # alias_method :old_init, :initialize
41
+ # attr_reader :parent
42
+ #
43
+ # def initialize(&)
44
+ # @parent = Fiber.current
45
+ # old_init(&)
46
+ # end
47
+ #
48
+ # def parents
49
+ # list = [@parent]
50
+ # list << list.last.parent while list.last.respond_to?(:parent) && !list.last.parent.nil?
51
+ # list
52
+ # end
53
+ # end
54
+
55
+ # https://socketry.github.io/traces/guides/getting-started/index.html
56
+ # OpenTelemetry / Datadog
57
+ # https://socketry.github.io/console/guides/getting-started/index.html
58
+ # ENV['TRACES_BACKEND'] = 'traces/backend/console'
59
+ # ENV['CONSOLE_LEVEL'] = 'all'
60
+ # ENV['CONSOLE_OUTPUT'] = 'XTerm' # JSON,Text,XTerm,Default
61
+ # TRACE_METHODS = true
62
+ TRACE_METHODS ||= !PERFORMANCE unless defined? TRACE_METHODS
63
+ if TRACE_METHODS
64
+ trace = TracePoint.new(:call, :return, :b_call, :b_return) { |tp| # :thread_begin, :thread_end
65
+ call_stack = Thread.current[:call_stack] ||= {}
66
+ call_stack_fiber = call_stack[Fiber.current.__id__] ||= []
67
+ call_stack_fiber << [tp.defined_class, tp.method_id] if [:call, :b_call].include? tp.event
68
+ call_stack_fiber.pop if [:return, :b_return].include? tp.event
69
+ }
70
+ trace.enable
71
+ end
72
+ # the_method
73
+ # trace.disable
74
+ LOG_DEPTH ||= 10 unless defined? LOG_DEPTH
75
+ LOGGER = Class.new {
76
+ def initialize = @context_list ||= {}
77
+
78
+ def add_context(name)
79
+ task = Async::Task.current?
80
+ @context_list[task.__id__] = name
81
+ end
82
+
83
+ def find_context
84
+ return '' unless Thread.current[:async_task]
85
+
86
+ t_stack = [Async::Task.current]
87
+ t_stack << t_stack.last.parent while t_stack.last.parent
88
+ task = t_stack.find { @context_list[_1.__id__] }
89
+
90
+ task ? " [#{@context_list[task.__id__]}] " : ''
91
+ end
92
+
93
+ def <<(...) = do_log(:info, ...)
94
+
95
+ def info(...) = do_log(:info, ...)
96
+
97
+ def debug(...) = do_log(:debug, ...)
98
+
99
+ def debug1(...) = do_log(:debug1, ...)
100
+
101
+ def debug2(...) = do_log(:debug2, ...)
102
+
103
+ def debug3(...) = do_log(:debug3, ...)
104
+
105
+ def warn(...) = do_log(:warn, ...)
106
+
107
+ def error(...) = do_log(:error, ...)
108
+
109
+ def fatal(...) = do_log(:fatal, ...)
110
+
111
+ def do_log(name, *args)
112
+ debug_level = name[/(\d+)/, 1].to_i
113
+ unless debug_level > LOG_DEPTH
114
+ if TRACE_METHODS
115
+ call_stack = Thread.current[:call_stack] ||= {}
116
+ call_stack_fiber = call_stack[Fiber.current.__id__] ||= []
117
+ last = call_stack_fiber[-3] ? call_stack_fiber[-3].join('.').gsub('Class:', '').gsub(/[#<>]/, '') : ''
118
+ last += find_context
119
+ msg = "\e[33m#{last}:\e[0m \e[38;5;254m" + args.flatten.map(&:inspect).join(', ')
120
+ else
121
+ msg = args.flatten.map(&:inspect).join(', ')
122
+ end
123
+ _name = name.to_s.gsub(/\d/, '')
124
+ _name = 'info' if _name == '<<'
125
+ Console.logger.send _name.to_s.gsub(/\d/, ''), msg
126
+ end
127
+ end
128
+ }.new
129
+
130
+ end
131
+
132
+ LOGGER_GRAPE = Class.new {
133
+ def method_missing(name, d)
134
+ Console.logger.send name, "REST_API: #{d[:method]} #{d[:path]} #{d[:params]} - #{d[:status]} host:#{d[:host]} time:#{d[:time]}"
135
+ end
136
+ }.new
137
+
138
+ $stdout.puts "QUIET: #{QUIET}"
139
+ $stdout.puts "PERFORMANCE: #{PERFORMANCE}"
140
+
141
+ ENV.select{ |k,v| k =~ /CONSOLE_/}.each { |k,v| $stdout.puts "#{k}: #{v}"}
@@ -0,0 +1,182 @@
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(app)
56
+ $stdout.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
+ app.use OTELTraceInfo
93
+ end
94
+
95
+ if defined? Sequel and OTEL_ENABLED
96
+ class Sequel::Database
97
+ alias old_test_connection test_connection
98
+
99
+ def test_connection(...)
100
+ OpenTelemetry::Common::Utilities.untraced do
101
+ old_test_connection(...)
102
+ end
103
+ end
104
+
105
+ alias old_valid_connection? valid_connection?
106
+ def valid_connection?(...)
107
+ OpenTelemetry::Common::Utilities.untraced do
108
+ old_valid_connection?(...)
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ def otl_span(name, attributes = {})
115
+ # span_ = OpenTelemetry::Trace.current_span
116
+ return yield(nil) unless OTEL_ENABLED
117
+
118
+ return yield(nil) unless $tracer_
119
+ $tracer_&.in_span(name, attributes: flatten_hash(attributes.transform_keys(&:to_s).transform_values{_1 || 'n/a'}) ) do |span|
120
+ yield span
121
+ end
122
+ end
123
+
124
+ def otl_current_span
125
+ return unless OTEL_ENABLED
126
+ yield OpenTelemetry::Trace.current_span
127
+ end
128
+
129
+ def otl_def(name)
130
+ original_method = self.respond_to?(:instance_method) ? instance_method(name) : method(name)
131
+ self.respond_to?(:remove_method) ? remove_method(name) : Object.send(:remove_method, name)
132
+ original_method = original_method.respond_to?(:unbind) ? original_method.unbind : original_method
133
+
134
+ define_method(name) do |*args, **kwargs, &block|
135
+ klass = self.respond_to?(:class_name) ? self.class_name : (self.respond_to?(:name) ? self.name : 'main')
136
+ otl_span("method: #{klass}.#{name}", {args: args.to_s, kwargs: kwargs.to_s}) do |span|
137
+ original_method.bind(self).call(*args, **kwargs, &block)
138
+ end
139
+ end
140
+ end
141
+
142
+ if defined? OpenTelemetry::Instrumentation::Rack::Middlewares
143
+ OpenTelemetry::Instrumentation::Rack::Middlewares::TracerMiddleware.config[:url_quantization] = ->(path, env) {
144
+ "HTTP #{env['REQUEST_METHOD']} #{path}"
145
+ }
146
+ end
147
+
148
+ if OTEL_ENABLED
149
+ class OpenTelemetry::SDK::Trace::Span
150
+ alias add_attributes_old add_attributes
151
+
152
+ def add_attributes(attributes)
153
+ add_attributes_old flatten_hash attributes
154
+ .transform_keys(&:to_s)
155
+ .transform_values{ _1 || 'n/a' }
156
+ end
157
+ end
158
+ end
159
+
160
+ if defined? Safrano::Request and OTEL_ENABLED
161
+ require 'odata/error'
162
+
163
+ class Safrano::Request
164
+ def process
165
+ begin
166
+ @response = Safrano::Response.new
167
+ before.tap_error { |err| dispatch_error(err) }
168
+ .tap_valid { |_res| dispatch }
169
+
170
+ rescue Sequel::Error => e
171
+ OpenTelemetry::Trace.current_span.tap do |span|
172
+ span.record_exception(e)
173
+ span.status = OpenTelemetry::Trace::Status.error("Unhandled exception of type: #{e.class}")
174
+ end
175
+ dispatch_error(Safrano::SequelExceptionError.new(e))
176
+ end
177
+ @response.finish
178
+ end
179
+ end
180
+ end
181
+
182
+
@@ -0,0 +1,185 @@
1
+ module RackHelpers
2
+ def Rack.middleware_klass(&block)
3
+ Class.new do
4
+ define_method(:initialize) do |app, *opts, &block2|; @app = app; @opts = opts; @block = block2 || block end
5
+ def call(env) = @block.call env, @app, @opts
6
+ end
7
+ end
8
+
9
+ def Rack.define_middleware(name, &block)
10
+ Object.const_set name, Rack.middleware_klass(&block)
11
+ end
12
+
13
+ Rack.define_middleware :Authentication do |env, app|
14
+ token = env['HTTP_AUTHORIZATION'][/Bearer (.*)/, 1] rescue nil # Authorization: Bearer token
15
+ token ||= env['HTTP_AUTH'][/Bearer (.*)/, 1] rescue nil # AUTH: Bearer token
16
+ token ||= Rack::Request.new(env).cookies['token']
17
+ token_h = JWT.decode token, '', false, algorithm: 'RS256' rescue nil
18
+ token_h ||= [{}]
19
+
20
+ if defined? OpenTelemetry::Trace
21
+ OpenTelemetry::Trace.current_span.add_attributes'TOKEN' => token_h[0].to_json,
22
+ 'username' => (token_h[0]['username'] || '')
23
+ end
24
+ Async::Task.current.define_singleton_method :token, &-> { token_h[0] }
25
+
26
+ app.call env
27
+ end
28
+
29
+ # TODO:
30
+ # - Only required for cross-thread context transfer
31
+ #
32
+ # Rack.define_middleware :AsyncDBConnectionOT do |env, app|
33
+ # context_ = OpenTelemetry::Context.current
34
+ # OpenTelemetry::Context.with_current(context_) do
35
+ # OpenTelemetry::Trace.with_span(OpenTelemetry::Trace.current_span) do
36
+ # app.call env
37
+ # end
38
+ # end
39
+ # end
40
+
41
+ # Rack.define_middleware :SwaggerUI do |env, app, opts|
42
+ # # url = opts[:swagger]
43
+ # @static ||= Rack::Static.new app, urls: [''], root: "#{__dir__}/../swagger_ui/", index: 'index.html', cascade: true
44
+ # env['REQUEST_METHOD'] == 'GET' ? @static.call(env) : app.call(env)
45
+ # end
46
+
47
+ #
48
+
49
+ Rack.define_middleware :OTELTraceInfo do |env, app, opts|
50
+ status, headers, body = app.call env
51
+ if status.to_i >= 500
52
+ otl_current_span{
53
+ span_context = OpenTelemetry::Trace.current_span.context
54
+ trace_id = span_context.trace_id.unpack1('H*')
55
+
56
+ begin
57
+ bj = JSON.parse(body.join)
58
+ bj[:trace_id] = trace_id
59
+ body = [bj.to_json]
60
+ rescue =>e
61
+ body = [body.join + "\ntrace_id: #{trace_id}"]
62
+ end
63
+ }
64
+ end
65
+
66
+ [status, headers, body]
67
+ end
68
+
69
+ Rack.define_middleware :NoCache do |env, app, opts|
70
+ status, headers, body = app.call env
71
+ headers['Cache-Control'] = 'private,max-age=0,must-revalidate,no-store'
72
+ [status, headers, body]
73
+ end
74
+
75
+ # PATCH: for the Grape
76
+ class Rack::Lint::Wrapper::InputWrapper
77
+ def rewind = @input.rewind
78
+ end if defined? Rack::Lint::Wrapper::InputWrapper
79
+
80
+ class Rack::Lint
81
+ def call(env = nil) = @app.call(env)
82
+ end if defined? Rack::Lint
83
+
84
+ class Rack::CommonLogger
85
+ def log(env, status, header, began_at) = ()
86
+ end
87
+ # require 'rack/request'
88
+ # # sinatra was resolved to 3.0.2, which depends on
89
+ # # rack (~> 2.2, >= 2.2.4)
90
+ # # /home/user/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/rack-2.2.4/lib/rack/request.rb
91
+ # module Rack::Request::Helpers
92
+ # alias old_post POST
93
+ # def POST = get_header(Rack::RACK_INPUT).empty? ? {} : old_post
94
+ # end
95
+
96
+ Rack.define_middleware :HeadersLogger do |env, app, opts|
97
+ LOGGER.info env.select { _1 =~ /HTTP/ }.transform_keys { _1.gsub 'HTTP_', '' }
98
+ status, headers, body =app.call env
99
+
100
+ if status.to_i / 100 == 5
101
+ _body = body.to_s # each(&:to_s).join
102
+ LOGGER.error [status, headers, _body]
103
+ OpenTelemetry::Trace.current_span.tap do |span|
104
+ event_attributes = { 'exception.type' => "HTTP #{status.to_i}", 'exception.message' => _body, 'exception.stacktrace' => '' }
105
+ span.add_event('exception', attributes: event_attributes)
106
+ span.status = OpenTelemetry::Trace::Status.error("Request error: #{status.to_i}")
107
+ end
108
+ end
109
+
110
+ LOGGER.info headers
111
+ [status, headers, body]
112
+ end
113
+
114
+ Rack.define_middleware :RequestProfile do |env, app, opts|
115
+ start = Time.now
116
+ LOGGER.debug "start:#{start}"
117
+ status, headers, body = app.call env
118
+ LOGGER.debug "#{Time.now - start} sec - end (fiber id: #{Fiber.current.__id__}, async task: #{Async::Task.current})"
119
+ headers['x-runtime'] = "#{Time.now - start}"
120
+ # if headers['Content-Type'] =~ /html/
121
+ # headers['Set-Cookie'] = "Runtime=#{Time.now - start} sec;expires=Sat, 01-Jan-3000 00:00:00 GMT;path=/;"
122
+ # end
123
+ [status, headers, body]
124
+ end
125
+
126
+ class << self
127
+ def rack_setup(app)
128
+ # PATCH: for the Grape Swagger
129
+ # https://github.com/ruby-grape/grape-swagger/pull/905
130
+ # https://github.com/ruby-grape/grape-swagger/issues/904
131
+ GrapeSwagger::DocMethods::ParseParams.instance_eval do
132
+ def parse_enum_or_range_values(values)
133
+ case values
134
+ when Proc
135
+ parse_enum_or_range_values(values.call) if values.parameters.empty?
136
+ when Range
137
+ parse_range_values(values) # if values.first.is_a?(Integer) TODO
138
+ when Array
139
+ { enum: values }
140
+ else
141
+ { enum: [values] } if values
142
+ end
143
+ end
144
+ end if defined? GrapeSwagger::DocMethods::ParseParams
145
+
146
+ app.use Rack.middleware_klass do |env, app|
147
+ # env['REQUEST_PATH'] == '/healthcheck' ? [200, {}, ['Healthy']] : app.call(env)
148
+ env['PATH_INFO'] == '/healthcheck' ? [200, {'Content-Type' =>'application/json'}, [{ Status: 'Healthy' }.to_json ]] : app.call(env)
149
+ end
150
+
151
+ if defined? OpenTelemetry::Instrumentation::Rack::Middlewares::TracerMiddleware
152
+ use OpenTelemetry::Instrumentation::Rack::Middlewares::TracerMiddleware
153
+ end
154
+ app.use Rack::Deflater
155
+ app.use OTELTraceInfo
156
+
157
+ unless defined?(PERFORMANCE) && PERFORMANCE
158
+ app.use RequestProfile
159
+ app.use HeadersLogger
160
+
161
+ if defined? Rack::ODataCommonLogger
162
+ app.use Rack::ODataCommonLogger, LOGGER # or use Rack::CommonLogger, LOGGER
163
+ end
164
+ end
165
+
166
+ app.use Rack.middleware_klass do |env, app|
167
+ code, headers, body = env['REQUEST_METHOD'] == 'OPTIONS' ? [200, {}, []] : app.call(env)
168
+
169
+ # scheme = env['rack.url_scheme']
170
+ # referer = URI.parse env['HTTP_REFERER']
171
+ headers.merge!(
172
+ # 'Access-Control-Allow-Origin' => "#{referer.scheme}://#{referer.host}",
173
+ 'Access-Control-Allow-Origin' => '*',
174
+ 'Access-Control-Allow-Methods' => 'GET, PUT, POST, DELETE, HEAD, OPTIONS',
175
+ 'Access-Control-Allow-Headers' => '*',
176
+ 'Access-Control-Allow-Credentials' => 'true')
177
+ [code, headers, body]
178
+ end
179
+
180
+ # unless @run
181
+ # run ->(_env) { [200, {'Content-Type' => 'text/plain'}, ['OK!?']] }
182
+ # end
183
+ end
184
+ end
185
+ end
@@ -1,3 +1,7 @@
1
+ require 'stack-service-base/logging'
2
+ require 'stack-service-base/rack_helpers'
3
+ require 'stack-service-base/open_telemetry'
4
+
1
5
  module StackServiceBase
2
6
  class << self
3
7
  def rack_setup app
@@ -6,6 +10,7 @@ module StackServiceBase
6
10
  return unless app.respond_to? :use
7
11
 
8
12
  app.instance_eval do
13
+ RackHelpers.rack_setup app
9
14
  if ENV.fetch('PROMETHEUS_METRICS_EXPORT', 'true') == 'true'
10
15
  require 'stack-service-base/prometheus'
11
16
 
@@ -13,6 +18,11 @@ module StackServiceBase
13
18
  use Prometheus::Middleware::Collector
14
19
  use Prometheus::Middleware::Exporter
15
20
  end
21
+
22
+ if OTEL_ENABLED
23
+ otel_initialize app
24
+ end
25
+
16
26
  end
17
27
  end
18
28
  end
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module StackServiceBase
2
2
  class Base
3
- VERSION = '0.0.3'
3
+ VERSION = '0.0.5'
4
4
  end
5
5
  end
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.3
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-02 00:00:00.000000000 Z
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,8 +157,11 @@ extensions: []
115
157
  extra_rdoc_files: []
116
158
  files:
117
159
  - lib/stack-service-base.rb
160
+ - lib/stack-service-base/logging.rb
161
+ - lib/stack-service-base/open_telemetry.rb
118
162
  - lib/stack-service-base/prometheus.rb
119
163
  - lib/stack-service-base/prometheus_parser.rb
164
+ - lib/stack-service-base/rack_helpers.rb
120
165
  - lib/version.rb
121
166
  homepage:
122
167
  licenses: []