epsagon 0.0.12 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cfe4b588a7d3aeac7ea954338f6814c1b733cdacaab175b8ab63711a09adb849
4
- data.tar.gz: a18b237f3e75ff45e3866a4570ad4125951480366007f0700af412254e04fd5e
3
+ metadata.gz: cff5af42ab7df270fc1a9c645d5dc25558e03ba194e2d642694dbbeaa074ebf6
4
+ data.tar.gz: 75971b80361f7feefeb45af21074d2357eeb4cdeb82ce0bdad989493b3b1abc6
5
5
  SHA512:
6
- metadata.gz: 4b0e7b5e44f8941fe647e69cb4f59c86ce144eef01fe7c96a035652c8fede98d2b781d59f495a852e1c0919fa5af40fe6413e2ef2c6c2b9c3b4a013b5ebef5c0
7
- data.tar.gz: d67ce25f32683d501729e1715e6427881f7a89fc730030ade43ca3df05402c8277237df9fb1f38c9a4e460f21863a076903c2c8f011b715b50b56d4be3e2b549
6
+ metadata.gz: a71dffcee29e3039cd7be5a5bf7cd60661574b86b0cc45b1b1b55df5d1b8108f1f713ace4ccb173f5283638212798f2a7e0430fbc76f6d3f35eeec52c8008d0b
7
+ data.tar.gz: 18b465927c9dc8b8ea722b55cc8b9e896fc498b6aa02b7a6c2e628c848ffebfe3f637ae417a2361879e511311907f480bad565091e75bd94d488b1a7f90b4b51
data/lib/epsagon.rb CHANGED
@@ -12,18 +12,23 @@ require_relative 'instrumentation/faraday'
12
12
  require_relative 'instrumentation/aws_sdk'
13
13
  require_relative 'instrumentation/rails'
14
14
  require_relative 'util'
15
+ require_relative 'epsagon_constants'
15
16
 
16
17
  Bundler.require
17
18
 
18
19
  # Epsagon tracing main entry point
19
20
  module Epsagon
21
+
22
+ DEFAULT_BACKEND = 'opentelemetry.tc.epsagon.com:443/traces'
23
+
20
24
  @@epsagon_config = {
21
- metadata_only: ENV['EPSAGON_METADATA']&.to_s&.downcase != 'false',
22
- debug: ENV['EPSAGON_DEBUG']&.to_s&.downcase == 'true',
23
- token: ENV['EPSAGON_TOKEN'],
24
- app_name: ENV['EPSAGON_APP_NAME'],
25
- backend: ENV['EPSAGON_BACKEND'] || 'localhost:55681/v1/trace'
26
- }
25
+ metadata_only: ENV['EPSAGON_METADATA']&.to_s&.downcase != 'false',
26
+ debug: ENV['EPSAGON_DEBUG']&.to_s&.downcase == 'true',
27
+ token: ENV['EPSAGON_TOKEN'],
28
+ app_name: ENV['EPSAGON_APP_NAME'],
29
+ max_attribute_size: ENV['EPSAGON_MAX_ATTRIBUTE_SIZE'] || 5000,
30
+ backend: ENV['EPSAGON_BACKEND'] || DEFAULT_BACKEND
31
+ }
27
32
 
28
33
  module_function
29
34
 
@@ -32,11 +37,18 @@ module Epsagon
32
37
  OpenTelemetry::SDK.configure
33
38
  end
34
39
 
40
+ def get_config
41
+ @@epsagon_config
42
+ end
43
+
35
44
  # config opentelemetry with epsaon extensions:
36
45
 
37
46
  def epsagon_confs(configurator)
38
47
  configurator.resource = OpenTelemetry::SDK::Resources::Resource.telemetry_sdk.merge(
39
- OpenTelemetry::SDK::Resources::Resource.create({ 'application' => @@epsagon_config[:app_name] })
48
+ OpenTelemetry::SDK::Resources::Resource.create({
49
+ 'application' => @@epsagon_config[:app_name],
50
+ 'epsagon.version' => EpsagonConstants::VERSION
51
+ })
40
52
  )
41
53
  configurator.use 'EpsagonSinatraInstrumentation', { epsagon: @@epsagon_config }
42
54
  configurator.use 'EpsagonNetHTTPInstrumentation', { epsagon: @@epsagon_config }
@@ -47,10 +59,10 @@ module Epsagon
47
59
  if @@epsagon_config[:debug]
48
60
  configurator.add_span_processor OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(
49
61
  OpenTelemetry::Exporter::OTLP::Exporter.new(headers: {
50
- 'x-epsagon-token' => @@epsagon_config[:token]
51
- },
52
- endpoint: @@epsagon_config[:backend],
53
- insecure: @@epsagon_config[:insecure] || false)
62
+ 'x-epsagon-token' => @@epsagon_config[:token]
63
+ },
64
+ endpoint: @@epsagon_config[:backend],
65
+ insecure: @@epsagon_config[:insecure] || false)
54
66
  )
55
67
 
56
68
  configurator.add_span_processor OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(
@@ -66,7 +78,29 @@ module Epsagon
66
78
  )
67
79
  end
68
80
  end
81
+ end
69
82
 
83
+
84
+ module SpanExtension
85
+
86
+ BLANKS = [nil, [], '']
87
+
88
+ def set_attribute(key, value)
89
+ unless BLANKS.include?(value)
90
+ value = Util.trim_attr(value, Epsagon.get_config[:max_attribute_size])
91
+ super(key, value)
92
+ end
93
+ end
94
+
95
+ def initialize(*args)
96
+ super(*args)
97
+ if @attributes
98
+ @attributes = Hash[@attributes.map { |k,v|
99
+ [k, Util.trim_attr(v, Epsagon.get_config[:max_attribute_size])]
100
+ }]
101
+ end
102
+
103
+ end
70
104
  end
71
105
 
72
106
  # monkey patch to include epsagon confs
@@ -79,5 +113,11 @@ module OpenTelemetry
79
113
  Epsagon.epsagon_confs c
80
114
  end
81
115
  end
116
+
117
+ module Trace
118
+ class Span
119
+ prepend SpanExtension
120
+ end
121
+ end
82
122
  end
83
123
  end
@@ -0,0 +1,3 @@
1
+ module EpsagonConstants
2
+ VERSION = '0.0.17'
3
+ end
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../util'
4
+ require_relative '../epsagon_constants'
4
5
 
5
6
  # AWS SDK epsagon instrumentation
6
7
  class EpsagonAwsSdkInstrumentation < OpenTelemetry::Instrumentation::Base
7
- VERSION = '0.0.0'
8
+ VERSION = EpsagonConstants::VERSION
8
9
  SERVICES = %w[
9
10
  ACM
10
11
  APIGateway
@@ -1,10 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'aws-sdk-core'
2
4
  require 'opentelemetry/common'
3
5
  require 'opentelemetry/sdk'
4
6
 
5
- def untraced
6
- OpenTelemetry::Trace.with_span(OpenTelemetry::Trace::Span.new) { yield }
7
+ def untraced(&block)
8
+ OpenTelemetry::Trace.with_span(OpenTelemetry::Trace::Span.new, &block)
7
9
  end
10
+
8
11
  # AWS SDK plugin for epsagon instrumentation
9
12
  class EpsagonAwsPlugin < Seahorse::Client::Plugin
10
13
  def add_handlers(handlers, _)
@@ -15,19 +18,19 @@ end
15
18
  # Generates Spans for all uses of AWS SDK
16
19
  class EpsagonAwsHandler < Seahorse::Client::Handler
17
20
  def call(context)
18
- tracer.in_span('') do |span|
21
+ tracer.in_span('', kind: :client) do |span|
19
22
  untraced do
20
23
  @handler.call(context).tap do
21
24
  span.set_attribute('aws.service', context.client.class.to_s.split('::')[1].downcase)
22
- span.set_attribute('aws.aws.operation', context.operation.name)
25
+ span.set_attribute('aws.operation', context.operation.name)
23
26
  span.set_attribute('aws.region', context.client.config.region)
24
- span.set_attribute('aws.status_code', context.http_response.status_code)
27
+ span.set_attribute('http.status_code', context.http_response.status_code)
25
28
  end
26
29
  end
27
30
  end
28
31
  end
29
32
 
30
33
  def tracer
31
- EpsagonAwsSdkInstrumentation.instance.tracer
34
+ EpsagonAwsSdkInstrumentation.instance.tracer()
32
35
  end
33
- end
36
+ end
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  require_relative '../util'
4
+ require_relative '../epsagon_constants'
5
+
3
6
  require 'faraday'
4
7
 
5
8
  # Faraday middleware for epsagon instrumentaton
@@ -1,41 +1,42 @@
1
- require 'opentelemetry/trace/status'
1
+ # frozen_string_literal: true
2
2
 
3
+ require 'opentelemetry/trace/status'
3
4
 
4
5
  module QueueTime
5
- REQUEST_START = 'HTTP_X_REQUEST_START'
6
- QUEUE_START = 'HTTP_X_QUEUE_START'
7
- MINIMUM_ACCEPTABLE_TIME_VALUE = 1_000_000_000
8
-
9
- module_function
10
-
11
- def get_request_start(env, now = nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
12
- header = env[REQUEST_START] || env[QUEUE_START]
13
- return unless header
14
-
15
- # nginx header is seconds in the format "t=1512379167.574"
16
- # apache header is microseconds in the format "t=1570633834463123"
17
- # heroku header is milliseconds in the format "1570634024294"
18
- time_string = header.to_s.delete('^0-9')
19
- return if time_string.nil?
20
-
21
- # Return nil if the time is clearly invalid
22
- time_value = "#{time_string[0, 10]}.#{time_string[10, 6]}".to_f
23
- return if time_value.zero? || time_value < MINIMUM_ACCEPTABLE_TIME_VALUE
24
-
25
- # return the request_start only if it's lesser than
26
- # current time, to avoid significant clock skew
27
- request_start = Time.at(time_value)
28
- now ||= Time.now.utc
29
- request_start.utc > now ? nil : request_start
30
- rescue StandardError => e
31
- # in case of an Exception we don't create a
32
- # `request.queuing` span
33
- OpenTelemetry.logger.debug("[rack] unable to parse request queue headers: #{e}")
34
- nil
35
- end
6
+ REQUEST_START = 'HTTP_X_REQUEST_START'
7
+ QUEUE_START = 'HTTP_X_QUEUE_START'
8
+ MINIMUM_ACCEPTABLE_TIME_VALUE = 1_000_000_000
9
+
10
+ module_function
11
+
12
+ def get_request_start(env, now = nil) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
13
+ header = env[REQUEST_START] || env[QUEUE_START]
14
+ return unless header
15
+
16
+ # nginx header is seconds in the format "t=1512379167.574"
17
+ # apache header is microseconds in the format "t=1570633834463123"
18
+ # heroku header is milliseconds in the format "1570634024294"
19
+ time_string = header.to_s.delete('^0-9')
20
+ return if time_string.nil?
21
+
22
+ # Return nil if the time is clearly invalid
23
+ time_value = "#{time_string[0, 10]}.#{time_string[10, 6]}".to_f
24
+ return if time_value.zero? || time_value < MINIMUM_ACCEPTABLE_TIME_VALUE
25
+
26
+ # return the request_start only if it's lesser than
27
+ # current time, to avoid significant clock skew
28
+ request_start = Time.at(time_value)
29
+ now ||= Time.now.utc
30
+ request_start.utc > now ? nil : request_start
31
+ rescue StandardError => e
32
+ # in case of an Exception we don't create a
33
+ # `request.queuing` span
34
+ OpenTelemetry.logger.debug("[rack] unable to parse request queue headers: #{e}")
35
+ nil
36
+ end
36
37
  end
37
38
 
38
- class EpsagonRackMiddleware # rubocop:disable Metrics/ClassLength
39
+ class EpsagonRackMiddleware
39
40
  class << self
40
41
  def allowed_rack_request_headers
41
42
  @allowed_rack_request_headers ||= Array(config[:allowed_request_headers]).each_with_object({}) do |header, memo|
@@ -72,7 +73,7 @@ class EpsagonRackMiddleware # rubocop:disable Metrics/ClassLength
72
73
  @app = app
73
74
  end
74
75
 
75
- def call(env) # rubocop:disable Metrics/AbcSize
76
+ def call(env)
76
77
  original_env = env.dup
77
78
  extracted_context = OpenTelemetry.propagation.http.extract(env)
78
79
  frontend_context = create_frontend_span(env, extracted_context)
@@ -84,7 +85,11 @@ class EpsagonRackMiddleware # rubocop:disable Metrics/ClassLength
84
85
  attributes: request_span_attributes(env: env),
85
86
  kind: :server) do |http_span|
86
87
  RackExtension.with_span(http_span) do
87
- tracer.in_span('rails') do |framework_span|
88
+ tracer.in_span(
89
+ env['HTTP_HOST'],
90
+ kind: :server,
91
+ attributes: {type: 'rails'}
92
+ ) do |framework_span|
88
93
  @app.call(env).tap do |status, headers, response|
89
94
  set_attributes_after_request(http_span, framework_span, status, headers, response)
90
95
  end
@@ -134,7 +139,7 @@ class EpsagonRackMiddleware # rubocop:disable Metrics/ClassLength
134
139
  attributes = {
135
140
  'operation' => env['REQUEST_METHOD'],
136
141
  'type' => 'http',
137
- 'http.scheme' => env['PATH_INFO'],
142
+ 'http.scheme' => env['rack.url_scheme'],
138
143
  'http.request.path' => path,
139
144
  'http.request.headers' => request_headers
140
145
  }
@@ -181,7 +186,7 @@ class EpsagonRackMiddleware # rubocop:disable Metrics/ClassLength
181
186
  end
182
187
  end
183
188
 
184
- def set_attributes_after_request(http_span, framework_span, status, headers, response)
189
+ def set_attributes_after_request(http_span, _framework_span, status, headers, response)
185
190
  unless config[:epsagon][:metadata_only]
186
191
  http_span.set_attribute('http.response.headers', JSON.generate(headers))
187
192
  http_span.set_attribute('http.response.body', response.join)
@@ -269,7 +274,6 @@ end
269
274
  # end
270
275
  # end
271
276
 
272
-
273
277
  class EpsagonRailtie < ::Rails::Railtie
274
278
  config.before_initialize do |app|
275
279
  # EpsagonRackInstrumentation.instance.install({})
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Patch faraday to include middleware
3
4
  module EpsagonFaradayPatch
4
5
  def adapter(*args)
@@ -12,7 +13,7 @@ end
12
13
 
13
14
  # Faraday epsagon instrumentaton
14
15
  class EpsagonFaradayInstrumentation < OpenTelemetry::Instrumentation::Base
15
- VERSION = '0.0.0'
16
+ VERSION = EpsagonConstants::VERSION
16
17
 
17
18
  install do |_config|
18
19
  require_relative 'epsagon_faraday_middleware'
@@ -3,6 +3,7 @@
3
3
  require 'opentelemetry'
4
4
 
5
5
  require_relative '../util'
6
+ require_relative '../epsagon_constants'
6
7
 
7
8
  # Net::HTTP patch for epsagon instrumentaton
8
9
  module EpsagonNetHTTPExtension
@@ -40,7 +41,7 @@ module EpsagonNetHTTPExtension
40
41
  tracer.in_span(
41
42
  @address,
42
43
  attributes: attributes,
43
- kind: :Client
44
+ kind: :client
44
45
  ) do |span|
45
46
  OpenTelemetry.propagation.http.inject(req)
46
47
 
@@ -74,7 +75,7 @@ end
74
75
 
75
76
  # Net::HTTP epsagon instrumentaton
76
77
  class EpsagonNetHTTPInstrumentation < OpenTelemetry::Instrumentation::Base
77
- VERSION = '0.0.0'
78
+ VERSION = EpsagonConstants::VERSION
78
79
 
79
80
  install do |_|
80
81
  ::Net::HTTP.prepend(EpsagonNetHTTPExtension)
@@ -1,12 +1,15 @@
1
-
1
+ # frozen_string_literal: true
2
+
2
3
  require 'opentelemetry'
3
4
  require 'rails'
4
- require "action_controller/railtie"
5
+ require 'action_controller/railtie'
5
6
 
6
7
  require_relative '../util'
8
+ require_relative '../epsagon_constants'
9
+
7
10
 
8
11
  module RackExtension
9
- extend self
12
+ module_function
10
13
 
11
14
  CURRENT_SPAN_KEY = OpenTelemetry::Context.create_key('current-span')
12
15
 
@@ -41,7 +44,7 @@ module RackExtension
41
44
  OpenTelemetry::Context.with_value(CURRENT_SPAN_KEY, span) { |c, s| yield s, c }
42
45
  end
43
46
  end
44
-
47
+
45
48
  module MetalPatch
46
49
  def dispatch(name, request, response)
47
50
  rack_span = RackExtension.current_span
@@ -50,15 +53,13 @@ module MetalPatch
50
53
  end
51
54
  end
52
55
 
53
-
54
-
55
56
  class EpsagonRailsInstrumentation < OpenTelemetry::Instrumentation::Base
56
- install do |_config|
57
- require_relative 'epsagon_rails_middleware'
58
- ::ActionController::Metal.prepend(MetalPatch)
59
- end
57
+ install do |_config|
58
+ require_relative 'epsagon_rails_middleware'
59
+ ::ActionController::Metal.prepend(MetalPatch)
60
+ end
60
61
 
61
- present do
62
- defined?(::Rails)
63
- end
64
- end
62
+ present do
63
+ defined?(::Rails)
64
+ end
65
+ end
@@ -3,6 +3,7 @@
3
3
  require 'opentelemetry'
4
4
 
5
5
  require_relative '../util'
6
+ require_relative '../epsagon_constants'
6
7
 
7
8
  # Sinatra middleware for epsagon instrumentation
8
9
  class EpsagonTracerMiddleware
@@ -26,7 +27,7 @@ class EpsagonTracerMiddleware
26
27
  attributes = {
27
28
  'operation' => env['REQUEST_METHOD'],
28
29
  'type' => 'http',
29
- 'http.scheme' => env['PATH_INFO'],
30
+ 'http.scheme' => env['rack.url_scheme'],
30
31
  'http.request.path' => path,
31
32
  'http.request.headers' => request_headers
32
33
  }
@@ -51,7 +52,11 @@ class EpsagonTracerMiddleware
51
52
  kind: :server,
52
53
  with_parent: parent_context(env)
53
54
  ) do |http_span|
54
- tracer.in_span('sinatra') do |framework_span|
55
+ tracer.in_span(
56
+ env['HTTP_HOST'],
57
+ kind: :server,
58
+ attributes: { type: 'sinatra' }
59
+ ) do |framework_span|
55
60
  app.call(env).tap { |resp| trace_response(http_span, framework_span, env, resp) }
56
61
  end
57
62
  end
@@ -78,7 +83,7 @@ class EpsagonTracerMiddleware
78
83
  end
79
84
 
80
85
  http_span.set_attribute('http.status_code', status)
81
- framework_span.set_attribute('http.route', env['sinatra.route'].split.last) if env['sinatra.route']
86
+ http_span.set_attribute('http.route', env['sinatra.route'].split.last) if env['sinatra.route']
82
87
  http_span.status = OpenTelemetry::Trace::Status.http_to_status(status)
83
88
  end
84
89
  end
@@ -107,7 +112,7 @@ end
107
112
 
108
113
  # Sinatra epsagon instrumentation
109
114
  class EpsagonSinatraInstrumentation < OpenTelemetry::Instrumentation::Base
110
- VERSION = '0.0.0'
115
+ VERSION = EpsagonConstants::VERSION
111
116
 
112
117
  install do |_|
113
118
  ::Sinatra::Base.register EpsagonTracerExtension
File without changes
data/lib/util.rb CHANGED
@@ -11,4 +11,23 @@ module Util
11
11
  { 'http.request.query' => query_string }
12
12
  end
13
13
  end
14
+
15
+ def self.trim_attr(value, max_size)
16
+ if value.instance_of? Array then
17
+ current_size = 2
18
+ value.each_with_index do |el, i|
19
+ el_size = el.to_s.size + (i==0 ? 0 : 2)
20
+ if current_size + el_size > max_size then
21
+ return value[0,i] + [Util.trim_attr(el, max_size - current_size)]
22
+ else
23
+ current_size += el_size
24
+ end
25
+ end
26
+ return value
27
+ elsif value.instance_of? String then
28
+ value[0, max_size]
29
+ else
30
+ value
31
+ end
32
+ end
14
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: epsagon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Epsagon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-13 00:00:00.000000000 Z
11
+ date: 2021-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opentelemetry-api
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.11.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: opentelemetry-sdk
28
+ name: opentelemetry-exporter-otlp
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.11.1
33
+ version: 0.11.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.11.1
40
+ version: 0.11.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: opentelemetry-instrumentation-sinatra
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,19 +53,19 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.11.0
55
55
  - !ruby/object:Gem::Dependency
56
- name: opentelemetry-exporter-otlp
56
+ name: opentelemetry-sdk
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.11.0
61
+ version: 0.11.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.11.0
68
+ version: 0.11.1
69
69
  description: 'Epsagon provides tracing to Ruby applications for the collection of
70
70
  distributed tracing and performance metrics to simplify complex architectures, eliminate
71
71
  manual work, visualize and correlate data to identify and fix problems fast.
@@ -77,6 +77,7 @@ extensions: []
77
77
  extra_rdoc_files: []
78
78
  files:
79
79
  - lib/epsagon.rb
80
+ - lib/epsagon_constants.rb
80
81
  - lib/instrumentation/aws_sdk.rb
81
82
  - lib/instrumentation/aws_sdk_plugin.rb
82
83
  - lib/instrumentation/epsagon_faraday_middleware.rb
@@ -85,6 +86,7 @@ files:
85
86
  - lib/instrumentation/net_http.rb
86
87
  - lib/instrumentation/rails.rb
87
88
  - lib/instrumentation/sinatra.rb
89
+ - lib/instrumentation/version.rb
88
90
  - lib/util.rb
89
91
  homepage: https://github.com/epsagon/epsagon-ruby
90
92
  licenses: