highlight_io 0.3.1 → 0.5.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 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