highlight_io 0.3.1 → 0.5.0

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: 8ac88fa49d586b18a7e1be34e4f2bbda4cdd574fcbeb83ffc97b75c0101d5b43
4
- data.tar.gz: 59840de16d8b5d3839c18aac425b7ea47aa76942a3ff4e539e8e2af623f1797b
3
+ metadata.gz: c3efa0af1bc68bbe32f441a34004f6c8091c45ac39cdb29eab0c8e998ec81b83
4
+ data.tar.gz: c7a0b835e16dc117987dd5907aa296ce43b8d63712f78a0c10eeb187aff719ca
5
5
  SHA512:
6
- metadata.gz: 834eeda394658f10de79c9102cb18415a0b2918030957a105cc6ba7505fe2e20d8ad63d28c4ca6ebe6dce7091207060343661c305a67844fc41c2cdc0e00446b
7
- data.tar.gz: 5723050e4cc62d07d4c53dfb6a1d34fb3771c622833643a0cacc7a5a5f6987ae432de560f16bb000e81631a8c8fdbad296cd79972811162a60dd303b2b1ad5ed
6
+ metadata.gz: c252eedb2907918abb3baa9101ddde61a76ca73ccdc95a0c7fb9dfb58b6c097ca599f23b6ef2130b888456fb6227db7e38284efd1a5a91ef1a54edf14c0c0f1f
7
+ data.tar.gz: 756d3dd965066c45329269fcaf185bb2dc80f3df90bbc35f90175ba3ebee227811d29550c5f03507728446422ecd9c3b1d6c09814fef0eb618506ae6b1f22b04
data/.rubocop.yml CHANGED
@@ -1,5 +1,21 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 3.0
3
+ EnabledByDefault: true
4
+
5
+ Bundler/GemComment:
6
+ Enabled: false
7
+
8
+ Bundler/GemVersion:
9
+ Enabled: false
10
+
11
+ Lint/ConstantResolution:
12
+ Enabled: false
13
+
14
+ Style/ConstantVisibility:
15
+ Enabled: false
16
+
17
+ Style/Copyright:
18
+ Enabled: false
3
19
 
4
20
  Style/FrozenStringLiteralComment:
5
21
  Enabled: false
@@ -7,11 +23,29 @@ Style/FrozenStringLiteralComment:
7
23
  Style/Documentation:
8
24
  Enabled: false
9
25
 
26
+ Style/DocumentationMethod:
27
+ Enabled: false
28
+
29
+ Style/ImplicitRuntimeError:
30
+ Enabled: false
31
+
32
+ Style/InlineComment:
33
+ Enabled: false
34
+
35
+ Style/MissingElse:
36
+ Enabled: false
37
+
38
+ Style/StringHashKeys:
39
+ Enabled: false
40
+
10
41
  Metrics/MethodLength:
11
42
  Enabled: false
12
43
 
13
44
  Metrics/CyclomaticComplexity:
14
- Max: 8
45
+ Enabled: false
46
+
47
+ Metrics/PerceivedComplexity:
48
+ Enabled: false
15
49
 
16
50
  Naming/MethodParameterName:
17
51
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,21 +1,35 @@
1
- ## 0.1.2
1
+ ## 0.5.0
2
2
 
3
- - Add ability to set `service_name` and `service_version`
3
+ - Fix bug with SDK initialization
4
+ - Fix bug with `service.name` and `deployment.environment` not being set
5
+ - Adds `telemetry.distro.*` attributes as resource spans
6
+ - Add `highlight_traceparent_meta` Rails tag helper
7
+ - Fixes up the Rubocop configs and addresses new issues reported
4
8
 
5
- ## 0.1.4
9
+ ## 0.4.0
6
10
 
7
- - Tune settings of opentelemetry SDK to reduce memory usage.
8
- - Enable GZIP compression of exported data.
11
+ - Add `H.init` alias
12
+ - Auto instrument Rails requests and eliminate need for `around_action`
13
+ - Fix warning about incompatibility with `ActiveSupport::LoggerSilence`
14
+
15
+ ## 0.2.2
16
+
17
+ - Fix duplicate errors recorded on traces.
18
+
19
+ ## 0.2.1
20
+
21
+ - Ensure `message` on logs is always a string.
9
22
 
10
23
  ## 0.2.0
11
24
 
12
25
  - Support setting `environment` attribute to SDK initialization.
13
26
  - `otlp_endpoint` updated to keyword parameter when initializing.
14
27
 
15
- ## 0.2.1
28
+ ## 0.1.4
16
29
 
17
- - Ensure `message` on logs is always a string.
30
+ - Tune settings of opentelemetry SDK to reduce memory usage.
31
+ - Enable GZIP compression of exported data.
18
32
 
19
- ## 0.2.2
33
+ ## 0.1.2
20
34
 
21
- - Fix duplicate errors recorded on traces.
35
+ - Add ability to set `service_name` and `service_version`
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- highlight_io (0.3.1)
5
- grpc (~> 1.65)
4
+ highlight_io (0.5.0)
5
+ grpc (~> 1.66)
6
6
  opentelemetry-exporter-otlp (~> 0.28.1)
7
7
  opentelemetry-instrumentation-all (~> 0.62.1)
8
8
  opentelemetry-sdk (~> 1.5.0)
@@ -12,20 +12,20 @@ GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
14
  ast (2.4.2)
15
- google-protobuf (3.25.3-arm64-darwin)
16
- google-protobuf (3.25.3-x86_64-linux)
15
+ google-protobuf (3.25.4-arm64-darwin)
16
+ google-protobuf (3.25.4-x86_64-linux)
17
17
  googleapis-common-protos-types (1.15.0)
18
18
  google-protobuf (>= 3.18, < 5.a)
19
- grpc (1.65.2-arm64-darwin)
19
+ grpc (1.66.0-arm64-darwin)
20
20
  google-protobuf (>= 3.25, < 5.0)
21
21
  googleapis-common-protos-types (~> 1.0)
22
- grpc (1.65.2-x86_64-linux)
22
+ grpc (1.66.0-x86_64-linux)
23
23
  google-protobuf (>= 3.25, < 5.0)
24
24
  googleapis-common-protos-types (~> 1.0)
25
25
  json (2.6.3)
26
26
  language_server-protocol (3.17.0.3)
27
27
  minitest (5.18.0)
28
- opentelemetry-api (1.3.0)
28
+ opentelemetry-api (1.4.0)
29
29
  opentelemetry-common (0.21.0)
30
30
  opentelemetry-api (~> 1.0)
31
31
  opentelemetry-exporter-otlp (0.28.1)
@@ -48,17 +48,17 @@ GEM
48
48
  opentelemetry-api (~> 1.0)
49
49
  opentelemetry-instrumentation-base (~> 0.22.1)
50
50
  opentelemetry-instrumentation-rack (~> 0.21)
51
- opentelemetry-instrumentation-action_view (0.7.1)
51
+ opentelemetry-instrumentation-action_view (0.7.3)
52
52
  opentelemetry-api (~> 1.0)
53
- opentelemetry-instrumentation-active_support (~> 0.1)
53
+ opentelemetry-instrumentation-active_support (~> 0.6)
54
54
  opentelemetry-instrumentation-base (~> 0.22.1)
55
- opentelemetry-instrumentation-active_job (0.7.4)
55
+ opentelemetry-instrumentation-active_job (0.7.7)
56
56
  opentelemetry-api (~> 1.0)
57
57
  opentelemetry-instrumentation-base (~> 0.22.1)
58
58
  opentelemetry-instrumentation-active_model_serializers (0.20.2)
59
59
  opentelemetry-api (~> 1.0)
60
60
  opentelemetry-instrumentation-base (~> 0.22.1)
61
- opentelemetry-instrumentation-active_record (0.7.2)
61
+ opentelemetry-instrumentation-active_record (0.7.4)
62
62
  opentelemetry-api (~> 1.0)
63
63
  opentelemetry-instrumentation-base (~> 0.22.1)
64
64
  opentelemetry-instrumentation-active_support (0.6.0)
@@ -105,7 +105,7 @@ GEM
105
105
  opentelemetry-instrumentation-aws_sdk (0.5.4)
106
106
  opentelemetry-api (~> 1.0)
107
107
  opentelemetry-instrumentation-base (~> 0.22.1)
108
- opentelemetry-instrumentation-base (0.22.5)
108
+ opentelemetry-instrumentation-base (0.22.6)
109
109
  opentelemetry-api (~> 1.0)
110
110
  opentelemetry-common (~> 0.21)
111
111
  opentelemetry-registry (~> 0.1)
@@ -176,7 +176,7 @@ GEM
176
176
  opentelemetry-instrumentation-rack (0.24.6)
177
177
  opentelemetry-api (~> 1.0)
178
178
  opentelemetry-instrumentation-base (~> 0.22.1)
179
- opentelemetry-instrumentation-rails (0.31.1)
179
+ opentelemetry-instrumentation-rails (0.31.2)
180
180
  opentelemetry-api (~> 1.0)
181
181
  opentelemetry-instrumentation-action_mailer (~> 0.1.0)
182
182
  opentelemetry-instrumentation-action_pack (~> 0.9.0)
data/highlight.gemspec CHANGED
@@ -15,16 +15,18 @@ Gem::Specification.new do |spec|
15
15
 
16
16
  # Specify which files should be added to the gem when it is released.
17
17
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
- end
18
+ spec.files =
19
+ Dir.chdir(File.expand_path(__dir__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
21
22
  spec.bindir = 'exe'
22
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
24
  spec.require_paths = ['lib']
24
25
 
25
- spec.add_runtime_dependency 'grpc', '~> 1.65'
26
- spec.add_runtime_dependency 'opentelemetry-exporter-otlp', '~> 0.28.1'
27
- spec.add_runtime_dependency 'opentelemetry-instrumentation-all', '~> 0.62.1'
28
- spec.add_runtime_dependency 'opentelemetry-sdk', '~> 1.5.0'
29
- spec.add_runtime_dependency 'opentelemetry-semantic_conventions', '~> 1.10.1'
26
+ spec.add_dependency('grpc', '~> 1.66')
27
+ spec.add_dependency('opentelemetry-exporter-otlp', '~> 0.28.1')
28
+ spec.add_dependency('opentelemetry-instrumentation-all', '~> 0.62.1')
29
+ spec.add_dependency('opentelemetry-sdk', '~> 1.5.0')
30
+ spec.add_dependency('opentelemetry-semantic_conventions', '~> 1.10.1')
31
+ spec.metadata['rubygems_mfa_required'] = 'true'
30
32
  end
@@ -1,3 +1,3 @@
1
1
  module Highlight
2
- VERSION = '0.3.1'.freeze
2
+ VERSION = '0.5.0'.freeze
3
3
  end
data/lib/highlight.rb CHANGED
@@ -1,10 +1,10 @@
1
- require 'opentelemetry/sdk'
2
- require 'opentelemetry/exporter/otlp'
3
- require 'opentelemetry/instrumentation/all'
4
- require 'opentelemetry/semantic_conventions'
5
1
  require 'date'
6
2
  require 'json'
7
3
  require 'logger'
4
+ require 'opentelemetry/exporter/otlp'
5
+ require 'opentelemetry/instrumentation/all'
6
+ require 'opentelemetry/sdk'
7
+ require 'opentelemetry/semantic_conventions'
8
8
  require 'securerandom'
9
9
 
10
10
  module Highlight
@@ -18,29 +18,58 @@ module Highlight
18
18
  end
19
19
  end
20
20
 
21
+ def self.init(project_id, environment: '', otlp_endpoint: H::OTLP_HTTP, &block)
22
+ H.new(project_id, environment: environment, otlp_endpoint: otlp_endpoint, &block)
23
+ end
24
+
21
25
  def self.start_span(name, attrs = {}, &block)
22
- if block_given?
26
+ if H.initialized?
23
27
  H.instance.start_span(name, attrs, &block)
24
- else
25
- H.instance.start_span(name, attrs) { |_| }
28
+ elsif block_given?
29
+ yield(OpenTelemetry::Trace::Span::INVALID)
26
30
  end
27
31
  end
28
32
 
29
33
  def self.log(level, message, attrs = {})
30
- H.instance.record_log(nil, nil, level, message, attrs)
34
+ return unless H.initialized?
35
+
36
+ H.instance&.record_log(nil, nil, level, message, attrs)
31
37
  end
32
38
 
33
39
  def self.exception(error, attrs = {})
34
- H.instance.record_exception(error, attrs)
40
+ return unless H.initialized?
41
+
42
+ H.instance&.record_exception(error, attrs)
35
43
  end
36
44
 
37
45
  def self.traceparent_meta
46
+ return unless H.initialized?
47
+
38
48
  Helpers.traceparent_meta
39
49
  end
40
50
 
51
+ def self.traceparent_meta_tag
52
+ return unless H.initialized?
53
+
54
+ Helpers.traceparent_meta_tag
55
+ end
56
+
57
+ def self.flush
58
+ return unless H.initialized?
59
+
60
+ H.instance.flush
61
+ end
62
+
63
+ def self.shutdown
64
+ return unless H.initialized?
65
+
66
+ H.instance.shutdown
67
+ end
68
+
41
69
  class H
42
- HIGHLIGHT_REQUEST_HEADER = 'X-Highlight-Request'.freeze
70
+ SDK_NAME = 'highlight-ruby'.freeze
43
71
  OTLP_HTTP = 'https://otel.highlight.io:4318'.freeze
72
+ HIGHLIGHT_REQUEST_HEADER = 'X-Highlight-Request'.freeze
44
73
  HIGHLIGHT_PROJECT_ATTRIBUTE = 'highlight.project_id'.freeze
45
74
  HIGHLIGHT_SESSION_ATTRIBUTE = 'highlight.session_id'.freeze
46
75
  HIGHLIGHT_TRACE_ATTRIBUTE = 'highlight.trace_id'.freeze
@@ -50,171 +79,170 @@ module Highlight
50
79
  CODE_FILEPATH = OpenTelemetry::SemanticConventions::Trace::CODE_FILEPATH
51
80
  CODE_LINENO = OpenTelemetry::SemanticConventions::Trace::CODE_LINENO
52
81
  CODE_FUNCTION = OpenTelemetry::SemanticConventions::Trace::CODE_FUNCTION
82
+ DEPLOYMENT_ENVIRONMENT_ATTRIBUTE = OpenTelemetry::SemanticConventions::Resource::DEPLOYMENT_ENVIRONMENT
83
+ HIGHLIGHT_SDK_VERSION_ATTRIBUTE = 'telemetry.distro.version'.freeze
84
+ HIGHLIGHT_SDK_NAME_ATTRIBUTE = 'telemetry.distro.name'.freeze
53
85
 
54
- def self.instance
55
- @@instance
86
+ class << self
87
+ attr_reader :instance
56
88
  end
57
89
 
58
- def initialize(project_id, environment: '', otlp_endpoint: OTLP_HTTP)
59
- @@instance = self # rubocop:disable Style/ClassVars
90
+ def self.initialized?
91
+ !@instance.nil?
92
+ end
60
93
 
61
- @project_id = project_id
62
- @otlp_endpoint = otlp_endpoint
94
+ def self.parse_headers(headers)
95
+ return HighlightHeaders.new(nil, nil) if headers.nil? || !headers.key?(HIGHLIGHT_REQUEST_HEADER)
63
96
 
64
- OpenTelemetry::SDK.configure do |c|
65
- c.add_span_processor(Highlight::Tracing::BaggageSpanProcessor.new)
97
+ session_id, request_id = headers[HIGHLIGHT_REQUEST_HEADER].split('/')
98
+ traceparent = headers['traceparent']
99
+ trace_id = traceparent&.split('-')&.[](1) || request_id
100
+ HighlightHeaders.new(session_id, trace_id)
101
+ end
66
102
 
67
- c.add_span_processor(
68
- OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
69
- OpenTelemetry::Exporter::OTLP::Exporter.new(
70
- endpoint: "#{@otlp_endpoint}/v1/traces",
71
- compression: 'gzip'
72
- ),
73
- schedule_delay: 1000,
74
- max_export_batch_size: 128,
75
- max_queue_size: 1024
76
- )
77
- )
103
+ def self.log_level_string(level)
104
+ case level
105
+ when Logger::FATAL then 'FATAL'
106
+ when Logger::ERROR then 'ERROR'
107
+ when Logger::WARN then 'WARN'
108
+ when Logger::INFO then 'INFO'
109
+ when Logger::DEBUG then 'DEBUG'
110
+ else 'UNKNOWN'
111
+ end
112
+ end
78
113
 
79
- c.resource = OpenTelemetry::SDK::Resources::Resource.create(
80
- HIGHLIGHT_PROJECT_ATTRIBUTE => @project_id,
81
- OpenTelemetry::SemanticConventions::Resource::SERVICE_NAME => environment,
82
- OpenTelemetry::SemanticConventions::Resource::DEPLOYMENT_ENVIRONMENT => environment
83
- )
114
+ def initialize(project_id, environment: '', otlp_endpoint: OTLP_HTTP, &block)
115
+ self.class.instance_variable_set(:@instance, self)
84
116
 
85
- c.use_all
117
+ @project_id = project_id
118
+ @otlp_endpoint = otlp_endpoint
119
+ @environment = environment
86
120
 
87
- yield c if block_given?
88
- end
121
+ configure_opentelemetry(&block)
89
122
 
90
123
  @tracer_provider = OpenTelemetry.tracer_provider
91
124
  @tracer = @tracer_provider.tracer('highlight-tracer')
92
125
  end
93
126
 
94
127
  def initialized?
95
- defined?(@tracer_provider)
128
+ !@tracer_provider.nil?
96
129
  end
97
130
 
98
131
  def flush
99
- return unless initialized?
132
+ @tracer_provider&.force_flush
133
+ end
100
134
 
101
- @tracer_provider.force_flush
135
+ def shutdown
136
+ @tracer_provider&.shutdown
102
137
  end
103
138
 
104
139
  def trace(session_id, request_id, attrs = {}, name: 'highlight.span', &block)
105
140
  return unless initialized?
106
141
 
107
- # Passed along by the BaggageSpanProcessor to child spans as attributes.
108
142
  ctx = OpenTelemetry::Baggage.set_value(HIGHLIGHT_SESSION_ATTRIBUTE, session_id || '')
109
143
  ctx = OpenTelemetry::Baggage.set_value(HIGHLIGHT_TRACE_ATTRIBUTE, request_id || '', context: ctx)
110
-
111
- OpenTelemetry::Context.with_current(ctx) do
112
- start_span(name, attrs, &block)
113
- end
144
+ OpenTelemetry::Context.with_current(ctx) { start_span(name, attrs, &block) }
114
145
  end
115
146
 
116
- def start_span(name, attrs = {}, &block)
147
+ def start_span(name, attrs = {})
117
148
  return unless initialized?
118
149
 
119
- if block_given?
120
- @tracer.in_span(name, attributes: attrs, &block)
121
- else
122
- @tracer.in_span(name, attributes: attrs) { |_| }
123
- end
150
+ @tracer.in_span(name, attributes: attrs.transform_keys(&:to_s)) { |span| yield(span) if block_given? }
124
151
  end
125
152
 
126
153
  def record_exception(e, attrs = {})
127
154
  return unless initialized?
128
155
 
129
- span = OpenTelemetry::Trace.current_span
130
- return unless span
131
-
132
- span.record_exception(e, attributes: attrs)
156
+ OpenTelemetry::Trace.current_span&.record_exception(e, attributes: attrs.transform_keys(&:to_s))
133
157
  end
134
158
 
135
159
  def record_log(session_id, request_id, level, message, attrs = {})
136
160
  return unless initialized?
137
161
 
138
- caller_info = caller[0].split(':', 3)
139
- function = caller_info[2]
140
- if function
141
- # format: "in `<function_name>""
142
- function.delete_prefix!('in `')
143
- function.delete_suffix!('"')
144
- end
162
+ log_attributes = create_log_attributes(level, message, attrs)
145
163
 
146
- @tracer.in_span('highlight.log', attributes: {
147
- HIGHLIGHT_SESSION_ATTRIBUTE => session_id,
148
- HIGHLIGHT_TRACE_ATTRIBUTE => request_id
149
- }.compact) do |span|
164
+ @tracer.in_span(
165
+ 'highlight.log',
166
+ attributes: {
167
+ HIGHLIGHT_SESSION_ATTRIBUTE => session_id || '',
168
+ HIGHLIGHT_TRACE_ATTRIBUTE => request_id || ''
169
+ }.compact
170
+ ) do |span|
150
171
  span.status = OpenTelemetry::Trace::Status.error(message) if [Logger::ERROR, Logger::FATAL].include?(level)
151
- span.add_event(LOG_EVENT, attributes: {
152
- LOG_SEVERITY_ATTRIBUTE => H.log_level_string(level),
153
- LOG_MESSAGE_ATTRIBUTE => message.to_s,
154
- CODE_FILEPATH => caller_info[0],
155
- CODE_LINENO => caller_info[1],
156
- CODE_FUNCTION => function
157
- }.merge(attrs))
172
+ span.add_event(LOG_EVENT, attributes: log_attributes)
158
173
  end
159
174
  end
160
175
 
161
- def self.parse_headers(headers)
162
- if headers && headers[HIGHLIGHT_REQUEST_HEADER]
163
- session_id, request_id = headers[HIGHLIGHT_REQUEST_HEADER].split('/')
164
- traceparent = headers['traceparent']
165
- trace_id = traceparent&.split('-')&.second || request_id
166
- return HighlightHeaders.new(session_id, trace_id)
176
+ private
177
+
178
+ def configure_opentelemetry
179
+ OpenTelemetry::SDK.configure do |c|
180
+ c.add_span_processor(Highlight::Tracing::BaggageSpanProcessor.new)
181
+ c.add_span_processor(create_batch_span_processor)
182
+ c.resource = create_resource
183
+ c.use_all
184
+ yield(c) if block_given?
167
185
  end
168
- HighlightHeaders.new(nil, nil)
169
186
  end
170
187
 
171
- def self.log_level_string(level)
172
- case level
173
- when Logger::UNKNOWN
174
- 'UNKNOWN'
175
- when Logger::FATAL
176
- 'FATAL'
177
- when Logger::ERROR
178
- 'ERROR'
179
- when Logger::WARN
180
- 'WARN'
181
- when Logger::INFO
182
- 'INFO'
183
- when Logger::DEBUG
184
- 'DEBUG'
185
- else
186
- 'UNKNOWN'
187
- end
188
+ def create_batch_span_processor
189
+ OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
190
+ OpenTelemetry::Exporter::OTLP::Exporter.new(
191
+ endpoint: "#{@otlp_endpoint}/v1/traces",
192
+ compression: 'gzip'
193
+ ),
194
+ schedule_delay: 1000,
195
+ max_export_batch_size: 128,
196
+ max_queue_size: 1024
197
+ )
188
198
  end
189
199
 
190
- private
200
+ def create_resource
201
+ OpenTelemetry::SDK::Resources::Resource.create(
202
+ HIGHLIGHT_PROJECT_ATTRIBUTE => @project_id,
203
+ HIGHLIGHT_SDK_VERSION_ATTRIBUTE => Highlight::VERSION,
204
+ HIGHLIGHT_SDK_NAME_ATTRIBUTE => SDK_NAME,
205
+ DEPLOYMENT_ENVIRONMENT_ATTRIBUTE => @environment
206
+ )
207
+ end
208
+
209
+ def create_log_attributes(level, message, attrs)
210
+ caller_info = parse_caller_info
191
211
 
192
- def trace_id_from_headers(headers)
193
- headers.traceparent&.split('-')&.first
212
+ {
213
+ LOG_SEVERITY_ATTRIBUTE => self.class.log_level_string(level),
214
+ LOG_MESSAGE_ATTRIBUTE => message.to_s,
215
+ CODE_FILEPATH => caller_info.first,
216
+ CODE_LINENO => caller_info[1],
217
+ CODE_FUNCTION => caller_info[2]
218
+ }.merge(attrs).transform_keys(&:to_s)
219
+ end
220
+
221
+ def parse_caller_info
222
+ caller_info = caller.first.split(':', 3)
223
+ function = caller_info[2]&.gsub(/^in `|'$/, '')
224
+ [caller_info.first, caller_info[1], function]
194
225
  end
195
226
  end
196
227
 
197
228
  class Logger < ::Logger
229
+ include ActiveSupport::LoggerSilence if defined?(::ActiveSupport::LoggerSilence)
230
+
198
231
  def initialize(*args)
199
232
  super
200
233
  @local_level = nil
201
234
  end
202
235
 
203
236
  def add(severity, message = nil, progname = nil, &block)
204
- severity ||= UNKNOWN
237
+ severity ||= ::Logger::UNKNOWN
205
238
  return true if @logdev.nil? || severity < level
206
239
 
207
- progname = @progname if progname.nil?
208
- if message.nil?
209
- if block_given?
210
- message = yield
211
- else
212
- message = progname
213
- progname = @progname
214
- end
215
- end
216
- super(severity, message, progname, &block)
217
- H.instance.record_log(nil, nil, severity, message)
240
+ progname ||= @progname
241
+ message = yield if message.nil? && block_given?
242
+ message = progname if message.nil?
243
+
244
+ super
245
+ H.instance&.record_log(nil, nil, severity, message)
218
246
  end
219
247
  end
220
248
 
@@ -223,41 +251,49 @@ module Highlight
223
251
  def self.included(base)
224
252
  base.extend(ClassMethods)
225
253
  base.helper_method(:highlight_headers)
254
+ base.around_action(:with_highlight_context)
255
+ base.helper(ViewHelpers)
226
256
  end
227
257
 
228
258
  def with_highlight_context(&block)
229
259
  set_highlight_headers
230
- H.instance.trace(highlight_headers.session_id, highlight_headers.request_id,
231
- name: "#{request.method.upcase} #{request.path}", &block)
260
+ H.instance.trace(
261
+ highlight_headers.session_id,
262
+ highlight_headers.request_id,
263
+ name: "#{request.method.upcase} #{request.path}",
264
+ &block
265
+ )
232
266
  end
233
267
 
234
268
  private
235
269
 
236
270
  def set_highlight_headers
237
271
  @highlight_headers = H.parse_headers(request.headers)
238
- return unless @highlight_headers.session_id.nil?
272
+ return if @highlight_headers.session_id
239
273
 
240
274
  session_id = request.cookies['sessionID'].presence || SecureRandom.alphanumeric(28)
241
-
242
275
  session_data_key = "sessionData_#{session_id}"
243
- @session_data = request.cookies[session_data_key] || {
276
+ @session_data = request.cookies[session_data_key] || create_session_data(session_id)
277
+
278
+ set_cookies(session_id, session_data_key)
279
+ @highlight_headers = HighlightHeaders.new(session_id, nil)
280
+ end
281
+
282
+ def create_session_data(session_id)
283
+ {
244
284
  sessionSecureID: session_id,
245
285
  projectID: @project_id,
246
286
  payloadID: 1,
247
- sessionStartTime: DateTime.now.strftime('%Q'),
248
- lastPushTime: DateTime.now.strftime('%Q')
287
+ sessionStartTime: Time.now.strftime('%Q'),
288
+ lastPushTime: Time.now.strftime('%Q')
249
289
  }
290
+ end
250
291
 
251
- cookies[:sessionID] = {
252
- value: session_id,
253
- expires: 15.minutes.from_now
254
- }
255
- cookies[session_data_key] = {
256
- value: @session_data.to_json,
257
- expires: 15.minutes.from_now
258
- }
292
+ def set_cookies(session_id, session_data_key)
293
+ expiration = 15.minutes.from_now
259
294
 
260
- @highlight_headers = HighlightHeaders.new(session_id, nil)
295
+ cookies[:sessionID] = { value: session_id, expires: expiration }
296
+ cookies[session_data_key] = { value: @session_data.to_json, expires: expiration }
261
297
  end
262
298
 
263
299
  def highlight_headers
@@ -266,6 +302,12 @@ module Highlight
266
302
 
267
303
  module ClassMethods
268
304
  end
305
+
306
+ module ViewHelpers
307
+ def highlight_traceparent_meta
308
+ tag.meta(name: 'traceparent', content: Helpers.traceparent_meta)
309
+ end
310
+ end
269
311
  end
270
312
  end
271
313
 
@@ -279,10 +321,24 @@ module Highlight
279
321
  current_trace = OpenTelemetry::Trace.current_span
280
322
  trace_id = current_trace&.context&.trace_id
281
323
  span_id = current_trace&.context&.span_id
282
- hex_trace_id = trace_id&.unpack1('H*') || '00000000000000000000000000000000'
283
- hex_span_id = span_id&.unpack1('H*') || '0000000000000000'
324
+ hex_trace_id = trace_id&.unpack1('H*') || ('0' * 32)
325
+ hex_span_id = span_id&.unpack1('H*') || ('0' * 16)
326
+
327
+ "00-#{hex_trace_id}-#{hex_span_id}-01"
328
+ end
284
329
 
285
- tag(:meta, name: 'traceparent', content: "00-#{hex_trace_id}-#{hex_span_id}-01")
330
+ def self.traceparent_meta_tag
331
+ "<meta name=\"traceparent\" content=\"#{traceparent_meta}\">"
332
+ end
333
+ end
334
+
335
+ if defined?(::Rails::Railtie)
336
+ class Railtie < ::Rails::Railtie
337
+ config.after_initialize do
338
+ ActiveSupport.on_load(:action_controller) do
339
+ include ::Highlight::Integrations::Rails
340
+ end
341
+ end
286
342
  end
287
343
  end
288
344
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: highlight_io
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Highlight
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-16 00:00:00.000000000 Z
11
+ date: 2024-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grpc
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.65'
19
+ version: '1.66'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.65'
26
+ version: '1.66'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: opentelemetry-exporter-otlp
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -106,6 +106,7 @@ licenses:
106
106
  - MIT
107
107
  metadata:
108
108
  homepage_uri: https://www.highlight.io
109
+ rubygems_mfa_required: 'true'
109
110
  post_install_message:
110
111
  rdoc_options: []
111
112
  require_paths:
@@ -121,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
122
  - !ruby/object:Gem::Version
122
123
  version: '0'
123
124
  requirements: []
124
- rubygems_version: 3.5.11
125
+ rubygems_version: 3.5.16
125
126
  signing_key:
126
127
  specification_version: 4
127
128
  summary: The Highlight SDK for Ruby