logstruct 0.1.11 → 0.2.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 +4 -4
- data/CHANGELOG.md +146 -1
- data/README.md +76 -68
- data/lib/log_struct/concerns/configuration.rb +139 -91
- data/lib/log_struct/concerns/error_handling.rb +36 -6
- data/lib/log_struct/config_struct/error_handling_modes.rb +3 -1
- data/lib/log_struct/config_struct/filters.rb +126 -22
- data/lib/log_struct/config_struct/integrations.rb +0 -4
- data/lib/log_struct/config_struct/limits.rb +29 -0
- data/lib/log_struct/configuration.rb +2 -0
- data/lib/log_struct/enums/event.rb +3 -1
- data/lib/log_struct/enums/log_field.rb +5 -0
- data/lib/log_struct/formatter.rb +304 -56
- data/lib/log_struct/hash_utils.rb +33 -4
- data/lib/log_struct/integrations/action_mailer/error_handling.rb +78 -20
- data/lib/log_struct/integrations/action_mailer/fallback_error_handlers.rb +81 -0
- data/lib/log_struct/integrations/action_mailer/metadata_collection.rb +0 -20
- data/lib/log_struct/integrations/action_mailer.rb +22 -17
- data/lib/log_struct/integrations/active_job/log_subscriber.rb +177 -25
- data/lib/log_struct/integrations/active_job.rb +2 -7
- data/lib/log_struct/integrations/active_model_serializers.rb +9 -3
- data/lib/log_struct/integrations/active_record.rb +45 -17
- data/lib/log_struct/integrations/active_storage.rb +31 -31
- data/lib/log_struct/integrations/ahoy.rb +19 -15
- data/lib/log_struct/integrations/carrierwave.rb +55 -51
- data/lib/log_struct/integrations/dotenv.rb +22 -32
- data/lib/log_struct/integrations/good_job/logger.rb +30 -24
- data/lib/log_struct/integrations/good_job.rb +111 -40
- data/lib/log_struct/integrations/host_authorization.rb +47 -36
- data/lib/log_struct/integrations/lograge.rb +39 -4
- data/lib/log_struct/integrations/puma.rb +74 -34
- data/lib/log_struct/integrations/rack_error_handler/debug_exceptions_logging.rb +35 -0
- data/lib/log_struct/integrations/rack_error_handler/error_lines.rb +160 -0
- data/lib/log_struct/integrations/rack_error_handler/middleware.rb +14 -169
- data/lib/log_struct/integrations/rack_error_handler/parse_error_logging.rb +36 -0
- data/lib/log_struct/integrations/rack_error_handler.rb +20 -4
- data/lib/log_struct/integrations/rack_middleware.rb +23 -0
- data/lib/log_struct/integrations/rails_log_subscribers.rb +32 -0
- data/lib/log_struct/integrations/request_context/middleware.rb +4 -9
- data/lib/log_struct/integrations/shrine.rb +48 -73
- data/lib/log_struct/integrations/sidekiq/job_context_middleware.rb +32 -0
- data/lib/log_struct/integrations/sidekiq/logger.rb +17 -9
- data/lib/log_struct/integrations/sidekiq.rb +98 -7
- data/lib/log_struct/integrations/sorbet.rb +10 -46
- data/lib/log_struct/integrations.rb +3 -2
- data/lib/log_struct/log/{good_job/enqueue.rb → active_job/discard.rb} +13 -13
- data/lib/log_struct/log/active_job/enqueue.rb +0 -4
- data/lib/log_struct/log/{good_job/schedule.rb → active_job/error.rb} +15 -15
- data/lib/log_struct/log/{good_job/start.rb → active_job/retry.rb} +13 -13
- data/lib/log_struct/log/{good_job/finish.rb → active_job/retry_stopped.rb} +13 -17
- data/lib/log_struct/log/active_job.rb +4 -0
- data/lib/log_struct/log/active_storage/delete.rb +6 -2
- data/lib/log_struct/log/active_storage/download.rb +2 -4
- data/lib/log_struct/log/active_storage/exist.rb +2 -2
- data/lib/log_struct/log/active_storage/metadata.rb +4 -4
- data/lib/log_struct/log/active_storage/upload.rb +2 -10
- data/lib/log_struct/log/active_storage/url.rb +2 -6
- data/lib/log_struct/log/active_storage.rb +2 -3
- data/lib/log_struct/log/error.rb +24 -1
- data/lib/log_struct/log/good_job.rb +0 -4
- data/lib/log_struct/log/puma/error.rb +63 -0
- data/lib/log_struct/log/puma.rb +1 -0
- data/lib/log_struct/log/security/blocked_host.rb +0 -4
- data/lib/log_struct/log/shrine/exist.rb +0 -2
- data/lib/log_struct/log/shrine/metadata.rb +2 -4
- data/lib/log_struct/log/shrine/upload.rb +4 -0
- data/lib/log_struct/log/sidekiq/error.rb +63 -0
- data/lib/log_struct/log/{active_storage/stream.rb → sidekiq/log.rb} +17 -11
- data/lib/log_struct/log/sidekiq.rb +3 -45
- data/lib/log_struct/log.rb +4 -2
- data/lib/log_struct/logged_errors.rb +25 -0
- data/lib/log_struct/monkey_patches/active_support/tagged_logging/formatter.rb +2 -3
- data/lib/log_struct/param_filters.rb +51 -38
- data/lib/log_struct/params_errors.rb +78 -0
- data/lib/log_struct/rails_boot_banner_silencer.rb +7 -2
- data/lib/log_struct/railtie.rb +29 -14
- data/lib/log_struct/semantic_logger/color_formatter.rb +60 -53
- data/lib/log_struct/semantic_logger/concerns/log_methods.rb +65 -57
- data/lib/log_struct/semantic_logger/formatter.rb +79 -57
- data/lib/log_struct/semantic_logger/logger.rb +29 -53
- data/lib/log_struct/semantic_logger/reopen_after_fork.rb +40 -0
- data/lib/log_struct/semantic_logger/setup.rb +115 -112
- data/lib/log_struct/shared/merge_additional_data_fields.rb +14 -1
- data/lib/log_struct/shared/serialize_common.rb +2 -7
- data/lib/log_struct/string_scrubber.rb +229 -20
- data/lib/log_struct/version.rb +1 -1
- data/lib/log_struct.rb +6 -4
- data/logstruct.gemspec +19 -10
- metadata +63 -11
- data/lib/log_struct/builders/active_job.rb +0 -84
- data/lib/log_struct/integrations/good_job/log_subscriber.rb +0 -179
- data/lib/log_struct/integrations/rack.rb +0 -31
data/lib/log_struct.rb
CHANGED
|
@@ -7,6 +7,7 @@ require "log_struct/version"
|
|
|
7
7
|
require "log_struct/enums"
|
|
8
8
|
require "log_struct/configuration"
|
|
9
9
|
require "log_struct/formatter"
|
|
10
|
+
require "log_struct/logged_errors"
|
|
10
11
|
require "log_struct/railtie"
|
|
11
12
|
require "log_struct/concerns/error_handling"
|
|
12
13
|
require "log_struct/concerns/configuration"
|
|
@@ -15,7 +16,7 @@ require "log_struct/concerns/logging"
|
|
|
15
16
|
# Require integrations
|
|
16
17
|
require "log_struct/integrations"
|
|
17
18
|
|
|
18
|
-
# SemanticLogger
|
|
19
|
+
# SemanticLogger: the logger, formatters and setup LogStruct writes its lines with
|
|
19
20
|
require "log_struct/semantic_logger/formatter"
|
|
20
21
|
require "log_struct/semantic_logger/color_formatter"
|
|
21
22
|
require "log_struct/semantic_logger/logger"
|
|
@@ -54,8 +55,9 @@ module LogStruct
|
|
|
54
55
|
LogStruct::RailsBootBannerSilencer.install!
|
|
55
56
|
|
|
56
57
|
# Patch Puma immediately for server runs so we can convert its lifecycle
|
|
57
|
-
# messages into structured logs reliably.
|
|
58
|
-
|
|
58
|
+
# messages into structured logs reliably. Not when LogStruct is disabled, and not
|
|
59
|
+
# when Puma isn't installed (install_patches! skips it).
|
|
60
|
+
if LogStruct.enabled? && ARGV.include?("server")
|
|
59
61
|
begin
|
|
60
62
|
require "log_struct/integrations/puma"
|
|
61
63
|
LogStruct::Integrations::Puma.install_patches!
|
|
@@ -65,7 +67,7 @@ module LogStruct
|
|
|
65
67
|
if defined?(::Rails) && ::Rails.respond_to?(:env) && ::Rails.env.test?
|
|
66
68
|
raise e
|
|
67
69
|
else
|
|
68
|
-
LogStruct.handle_exception(e, source: LogStruct::Source::
|
|
70
|
+
LogStruct.handle_exception(e, source: LogStruct::Source::Internal, context: {integration: :puma})
|
|
69
71
|
end
|
|
70
72
|
end
|
|
71
73
|
end
|
data/logstruct.gemspec
CHANGED
|
@@ -15,26 +15,35 @@ Gem::Specification.new do |spec|
|
|
|
15
15
|
"Log messages, params, and job args are automatically filtered and scrubbed to remove any sensitive info."
|
|
16
16
|
spec.homepage = "https://logstruct.com"
|
|
17
17
|
spec.license = "MIT"
|
|
18
|
-
spec.required_ruby_version = ">= 3.
|
|
18
|
+
spec.required_ruby_version = ">= 3.3.0"
|
|
19
19
|
|
|
20
20
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
21
21
|
spec.metadata["source_code_uri"] = "https://github.com/DocSpring/logstruct"
|
|
22
22
|
spec.metadata["changelog_uri"] = "#{spec.metadata["source_code_uri"]}/blob/main/CHANGELOG.md"
|
|
23
23
|
|
|
24
|
-
# Specify which files should be added to the gem when it is released
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
# Specify which files should be added to the gem when it is released: only files committed to git, so a
|
|
25
|
+
# local build can't pick up untracked files. Without git (an unpacked gem), it falls back to Dir.
|
|
26
|
+
patterns = ["lib/**/*", "README.md", "CHANGELOG.md", "LICENSE", "*.gemspec"]
|
|
27
|
+
tracked_files = begin
|
|
28
|
+
output = IO.popen(%w[git ls-files -z], chdir: __dir__, err: File::NULL, &:read)
|
|
29
|
+
output.split("\x0") if $?.success?
|
|
30
|
+
rescue Errno::ENOENT
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
spec.files = if tracked_files
|
|
34
|
+
tracked_files.select { |file| patterns.any? { |pattern| File.fnmatch?(pattern, file, File::FNM_PATHNAME) } }
|
|
35
|
+
else
|
|
36
|
+
Dir[*patterns].select { |file| File.file?(file) }
|
|
37
|
+
end
|
|
32
38
|
spec.bindir = "exe"
|
|
33
39
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
34
40
|
spec.require_paths = ["lib"]
|
|
35
41
|
|
|
42
|
+
spec.add_dependency "actionpack", ">= 7.1"
|
|
43
|
+
spec.add_dependency "activesupport", ">= 7.1"
|
|
44
|
+
spec.add_dependency "globalid", ">= 1.0"
|
|
36
45
|
spec.add_dependency "lograge", ">= 0.11"
|
|
37
|
-
spec.add_dependency "
|
|
46
|
+
spec.add_dependency "railties", ">= 7.1"
|
|
38
47
|
spec.add_dependency "semantic_logger", "~> 4.15"
|
|
39
48
|
spec.add_dependency "sorbet-runtime", ">= 0.5"
|
|
40
49
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: logstruct
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- DocSpring
|
|
@@ -9,6 +9,48 @@ bindir: exe
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: actionpack
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '7.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '7.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: activesupport
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '7.1'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '7.1'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: globalid
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '1.0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '1.0'
|
|
12
54
|
- !ruby/object:Gem::Dependency
|
|
13
55
|
name: lograge
|
|
14
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -24,7 +66,7 @@ dependencies:
|
|
|
24
66
|
- !ruby/object:Gem::Version
|
|
25
67
|
version: '0.11'
|
|
26
68
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
69
|
+
name: railties
|
|
28
70
|
requirement: !ruby/object:Gem::Requirement
|
|
29
71
|
requirements:
|
|
30
72
|
- - ">="
|
|
@@ -240,13 +282,13 @@ files:
|
|
|
240
282
|
- README.md
|
|
241
283
|
- lib/log_struct.rb
|
|
242
284
|
- lib/log_struct/boot_buffer.rb
|
|
243
|
-
- lib/log_struct/builders/active_job.rb
|
|
244
285
|
- lib/log_struct/concerns/configuration.rb
|
|
245
286
|
- lib/log_struct/concerns/error_handling.rb
|
|
246
287
|
- lib/log_struct/concerns/logging.rb
|
|
247
288
|
- lib/log_struct/config_struct/error_handling_modes.rb
|
|
248
289
|
- lib/log_struct/config_struct/filters.rb
|
|
249
290
|
- lib/log_struct/config_struct/integrations.rb
|
|
291
|
+
- lib/log_struct/config_struct/limits.rb
|
|
250
292
|
- lib/log_struct/configuration.rb
|
|
251
293
|
- lib/log_struct/enums.rb
|
|
252
294
|
- lib/log_struct/enums/error_handling_mode.rb
|
|
@@ -262,6 +304,7 @@ files:
|
|
|
262
304
|
- lib/log_struct/integrations/action_mailer.rb
|
|
263
305
|
- lib/log_struct/integrations/action_mailer/error_handling.rb
|
|
264
306
|
- lib/log_struct/integrations/action_mailer/event_logging.rb
|
|
307
|
+
- lib/log_struct/integrations/action_mailer/fallback_error_handlers.rb
|
|
265
308
|
- lib/log_struct/integrations/action_mailer/metadata_collection.rb
|
|
266
309
|
- lib/log_struct/integrations/active_job.rb
|
|
267
310
|
- lib/log_struct/integrations/active_job/log_subscriber.rb
|
|
@@ -273,20 +316,24 @@ files:
|
|
|
273
316
|
- lib/log_struct/integrations/dotenv.rb
|
|
274
317
|
- lib/log_struct/integrations/event_time.rb
|
|
275
318
|
- lib/log_struct/integrations/good_job.rb
|
|
276
|
-
- lib/log_struct/integrations/good_job/log_subscriber.rb
|
|
277
319
|
- lib/log_struct/integrations/good_job/logger.rb
|
|
278
320
|
- lib/log_struct/integrations/host_authorization.rb
|
|
279
321
|
- lib/log_struct/integrations/integration_interface.rb
|
|
280
322
|
- lib/log_struct/integrations/lograge.rb
|
|
281
323
|
- lib/log_struct/integrations/puma.rb
|
|
282
|
-
- lib/log_struct/integrations/rack.rb
|
|
283
324
|
- lib/log_struct/integrations/rack_error_handler.rb
|
|
325
|
+
- lib/log_struct/integrations/rack_error_handler/debug_exceptions_logging.rb
|
|
326
|
+
- lib/log_struct/integrations/rack_error_handler/error_lines.rb
|
|
284
327
|
- lib/log_struct/integrations/rack_error_handler/middleware.rb
|
|
328
|
+
- lib/log_struct/integrations/rack_error_handler/parse_error_logging.rb
|
|
329
|
+
- lib/log_struct/integrations/rack_middleware.rb
|
|
285
330
|
- lib/log_struct/integrations/rack_setup.rb
|
|
331
|
+
- lib/log_struct/integrations/rails_log_subscribers.rb
|
|
286
332
|
- lib/log_struct/integrations/request_context.rb
|
|
287
333
|
- lib/log_struct/integrations/request_context/middleware.rb
|
|
288
334
|
- lib/log_struct/integrations/shrine.rb
|
|
289
335
|
- lib/log_struct/integrations/sidekiq.rb
|
|
336
|
+
- lib/log_struct/integrations/sidekiq/job_context_middleware.rb
|
|
290
337
|
- lib/log_struct/integrations/sidekiq/logger.rb
|
|
291
338
|
- lib/log_struct/integrations/sorbet.rb
|
|
292
339
|
- lib/log_struct/log.rb
|
|
@@ -295,8 +342,12 @@ files:
|
|
|
295
342
|
- lib/log_struct/log/action_mailer/delivery.rb
|
|
296
343
|
- lib/log_struct/log/action_mailer/error.rb
|
|
297
344
|
- lib/log_struct/log/active_job.rb
|
|
345
|
+
- lib/log_struct/log/active_job/discard.rb
|
|
298
346
|
- lib/log_struct/log/active_job/enqueue.rb
|
|
347
|
+
- lib/log_struct/log/active_job/error.rb
|
|
299
348
|
- lib/log_struct/log/active_job/finish.rb
|
|
349
|
+
- lib/log_struct/log/active_job/retry.rb
|
|
350
|
+
- lib/log_struct/log/active_job/retry_stopped.rb
|
|
300
351
|
- lib/log_struct/log/active_job/schedule.rb
|
|
301
352
|
- lib/log_struct/log/active_job/start.rb
|
|
302
353
|
- lib/log_struct/log/active_model_serializers.rb
|
|
@@ -305,7 +356,6 @@ files:
|
|
|
305
356
|
- lib/log_struct/log/active_storage/download.rb
|
|
306
357
|
- lib/log_struct/log/active_storage/exist.rb
|
|
307
358
|
- lib/log_struct/log/active_storage/metadata.rb
|
|
308
|
-
- lib/log_struct/log/active_storage/stream.rb
|
|
309
359
|
- lib/log_struct/log/active_storage/upload.rb
|
|
310
360
|
- lib/log_struct/log/active_storage/url.rb
|
|
311
361
|
- lib/log_struct/log/ahoy.rb
|
|
@@ -320,18 +370,15 @@ files:
|
|
|
320
370
|
- lib/log_struct/log/dotenv/update.rb
|
|
321
371
|
- lib/log_struct/log/error.rb
|
|
322
372
|
- lib/log_struct/log/good_job.rb
|
|
323
|
-
- lib/log_struct/log/good_job/enqueue.rb
|
|
324
373
|
- lib/log_struct/log/good_job/error.rb
|
|
325
|
-
- lib/log_struct/log/good_job/finish.rb
|
|
326
374
|
- lib/log_struct/log/good_job/log.rb
|
|
327
|
-
- lib/log_struct/log/good_job/schedule.rb
|
|
328
|
-
- lib/log_struct/log/good_job/start.rb
|
|
329
375
|
- lib/log_struct/log/interfaces/additional_data_field.rb
|
|
330
376
|
- lib/log_struct/log/interfaces/common_fields.rb
|
|
331
377
|
- lib/log_struct/log/interfaces/public_common_fields.rb
|
|
332
378
|
- lib/log_struct/log/interfaces/request_fields.rb
|
|
333
379
|
- lib/log_struct/log/plain.rb
|
|
334
380
|
- lib/log_struct/log/puma.rb
|
|
381
|
+
- lib/log_struct/log/puma/error.rb
|
|
335
382
|
- lib/log_struct/log/puma/shutdown.rb
|
|
336
383
|
- lib/log_struct/log/puma/start.rb
|
|
337
384
|
- lib/log_struct/log/request.rb
|
|
@@ -346,16 +393,21 @@ files:
|
|
|
346
393
|
- lib/log_struct/log/shrine/metadata.rb
|
|
347
394
|
- lib/log_struct/log/shrine/upload.rb
|
|
348
395
|
- lib/log_struct/log/sidekiq.rb
|
|
396
|
+
- lib/log_struct/log/sidekiq/error.rb
|
|
397
|
+
- lib/log_struct/log/sidekiq/log.rb
|
|
349
398
|
- lib/log_struct/log/sql.rb
|
|
399
|
+
- lib/log_struct/logged_errors.rb
|
|
350
400
|
- lib/log_struct/monkey_patches/active_support/tagged_logging/formatter.rb
|
|
351
401
|
- lib/log_struct/multi_error_reporter.rb
|
|
352
402
|
- lib/log_struct/param_filters.rb
|
|
403
|
+
- lib/log_struct/params_errors.rb
|
|
353
404
|
- lib/log_struct/rails_boot_banner_silencer.rb
|
|
354
405
|
- lib/log_struct/railtie.rb
|
|
355
406
|
- lib/log_struct/semantic_logger/color_formatter.rb
|
|
356
407
|
- lib/log_struct/semantic_logger/concerns/log_methods.rb
|
|
357
408
|
- lib/log_struct/semantic_logger/formatter.rb
|
|
358
409
|
- lib/log_struct/semantic_logger/logger.rb
|
|
410
|
+
- lib/log_struct/semantic_logger/reopen_after_fork.rb
|
|
359
411
|
- lib/log_struct/semantic_logger/setup.rb
|
|
360
412
|
- lib/log_struct/shared/add_request_fields.rb
|
|
361
413
|
- lib/log_struct/shared/interfaces/additional_data_field.rb
|
|
@@ -387,7 +439,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
387
439
|
requirements:
|
|
388
440
|
- - ">="
|
|
389
441
|
- !ruby/object:Gem::Version
|
|
390
|
-
version: 3.
|
|
442
|
+
version: 3.3.0
|
|
391
443
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
392
444
|
requirements:
|
|
393
445
|
- - ">="
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# typed: strict
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require_relative "../log/active_job/enqueue"
|
|
5
|
-
require_relative "../log/active_job/schedule"
|
|
6
|
-
require_relative "../log/active_job/start"
|
|
7
|
-
require_relative "../log/active_job/finish"
|
|
8
|
-
|
|
9
|
-
module LogStruct
|
|
10
|
-
module Builders
|
|
11
|
-
module ActiveJob
|
|
12
|
-
extend T::Sig
|
|
13
|
-
|
|
14
|
-
sig { params(job: T.untyped).returns(T.nilable(String)) }
|
|
15
|
-
def self.safe_provider_job_id(job)
|
|
16
|
-
job.respond_to?(:provider_job_id) ? job.provider_job_id : nil
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
sig { params(job: T.untyped).returns(T.nilable(Integer)) }
|
|
20
|
-
def self.safe_executions(job)
|
|
21
|
-
job.respond_to?(:executions) ? job.executions : nil
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
sig { params(job: T.untyped).returns(T.nilable(T::Array[T.untyped])) }
|
|
25
|
-
def self.safe_arguments(job)
|
|
26
|
-
return nil unless job.class.respond_to?(:log_arguments?)
|
|
27
|
-
job.class.log_arguments? ? job.arguments : nil
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
sig { params(job: T.untyped).returns(Log::ActiveJob::Enqueue) }
|
|
31
|
-
def self.enqueue(job)
|
|
32
|
-
Log::ActiveJob::Enqueue.new(
|
|
33
|
-
job_id: job.job_id,
|
|
34
|
-
job_class: job.class.to_s,
|
|
35
|
-
queue_name: job.queue_name,
|
|
36
|
-
arguments: safe_arguments(job),
|
|
37
|
-
executions: safe_executions(job),
|
|
38
|
-
provider_job_id: safe_provider_job_id(job)
|
|
39
|
-
)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
sig { params(job: T.untyped, scheduled_at: Time).returns(Log::ActiveJob::Schedule) }
|
|
43
|
-
def self.schedule(job, scheduled_at:)
|
|
44
|
-
Log::ActiveJob::Schedule.new(
|
|
45
|
-
job_id: job.job_id,
|
|
46
|
-
job_class: job.class.to_s,
|
|
47
|
-
queue_name: job.queue_name,
|
|
48
|
-
arguments: safe_arguments(job),
|
|
49
|
-
executions: safe_executions(job),
|
|
50
|
-
provider_job_id: safe_provider_job_id(job),
|
|
51
|
-
scheduled_at: scheduled_at
|
|
52
|
-
)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
sig { params(job: T.untyped, started_at: Time, attempt: T.nilable(Integer)).returns(Log::ActiveJob::Start) }
|
|
56
|
-
def self.start(job, started_at:, attempt:)
|
|
57
|
-
Log::ActiveJob::Start.new(
|
|
58
|
-
job_id: job.job_id,
|
|
59
|
-
job_class: job.class.to_s,
|
|
60
|
-
queue_name: job.queue_name,
|
|
61
|
-
arguments: safe_arguments(job),
|
|
62
|
-
executions: safe_executions(job),
|
|
63
|
-
provider_job_id: safe_provider_job_id(job),
|
|
64
|
-
started_at: started_at,
|
|
65
|
-
attempt: attempt
|
|
66
|
-
)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
sig { params(job: T.untyped, duration_ms: Float, finished_at: Time).returns(Log::ActiveJob::Finish) }
|
|
70
|
-
def self.finish(job, duration_ms:, finished_at:)
|
|
71
|
-
Log::ActiveJob::Finish.new(
|
|
72
|
-
job_id: job.job_id,
|
|
73
|
-
job_class: job.class.to_s,
|
|
74
|
-
queue_name: job.queue_name,
|
|
75
|
-
arguments: safe_arguments(job),
|
|
76
|
-
executions: safe_executions(job),
|
|
77
|
-
provider_job_id: safe_provider_job_id(job),
|
|
78
|
-
duration_ms: duration_ms,
|
|
79
|
-
finished_at: finished_at
|
|
80
|
-
)
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
# typed: strict
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
begin
|
|
5
|
-
require "active_support/log_subscriber"
|
|
6
|
-
rescue LoadError
|
|
7
|
-
# ActiveSupport is not available, log subscriber will be skipped
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
require_relative "../../log/good_job"
|
|
11
|
-
require_relative "../../enums/event"
|
|
12
|
-
require_relative "../../enums/level"
|
|
13
|
-
require_relative "../event_time"
|
|
14
|
-
|
|
15
|
-
module LogStruct
|
|
16
|
-
module Integrations
|
|
17
|
-
module GoodJob
|
|
18
|
-
# LogSubscriber for GoodJob ActiveSupport notifications
|
|
19
|
-
#
|
|
20
|
-
# This subscriber captures GoodJob's ActiveSupport notifications and converts
|
|
21
|
-
# them into structured LogStruct::Log::GoodJob entries. It provides detailed
|
|
22
|
-
# logging for job lifecycle events, performance metrics, and error tracking.
|
|
23
|
-
#
|
|
24
|
-
# ## Supported Events:
|
|
25
|
-
# - job.enqueue - Job queued for execution
|
|
26
|
-
# - job.start - Job execution started
|
|
27
|
-
# - job.finish - Job completed successfully
|
|
28
|
-
# - job.error - Job failed with error
|
|
29
|
-
# - job.retry - Job retry initiated
|
|
30
|
-
# - job.schedule - Job scheduled for future execution
|
|
31
|
-
#
|
|
32
|
-
# ## Event Data Captured:
|
|
33
|
-
# - Job identification (ID, class, queue)
|
|
34
|
-
# - Execution context (arguments, priority, scheduled time)
|
|
35
|
-
# - Performance metrics (execution time, wait time)
|
|
36
|
-
# - Error information (class, message, backtrace)
|
|
37
|
-
# - Process and thread information
|
|
38
|
-
class LogSubscriber < ::ActiveSupport::LogSubscriber
|
|
39
|
-
extend T::Sig
|
|
40
|
-
|
|
41
|
-
# Job enqueued event
|
|
42
|
-
sig { params(event: ::ActiveSupport::Notifications::Event).void }
|
|
43
|
-
def enqueue(event)
|
|
44
|
-
payload = T.let(event.payload, T::Hash[Symbol, T.untyped])
|
|
45
|
-
job = payload[:job]
|
|
46
|
-
base_fields = build_base_fields(job, payload)
|
|
47
|
-
ts = EventTime.coerce_event_time(event.time)
|
|
48
|
-
|
|
49
|
-
logger.info(Log::GoodJob::Enqueue.new(
|
|
50
|
-
**base_fields.to_kwargs,
|
|
51
|
-
scheduled_at: (job&.scheduled_at ? Time.at(job.scheduled_at.to_i) : nil),
|
|
52
|
-
duration_ms: event.duration.to_f,
|
|
53
|
-
enqueue_caller: job&.enqueue_caller_location,
|
|
54
|
-
timestamp: ts
|
|
55
|
-
))
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Job execution started event
|
|
59
|
-
sig { params(event: ::ActiveSupport::Notifications::Event).void }
|
|
60
|
-
def start(event)
|
|
61
|
-
payload = T.let(event.payload, T::Hash[Symbol, T.untyped])
|
|
62
|
-
job = payload[:job]
|
|
63
|
-
execution = payload[:execution] || payload[:good_job_execution]
|
|
64
|
-
base_fields = build_base_fields(job, payload)
|
|
65
|
-
ts = EventTime.coerce_event_time(event.time)
|
|
66
|
-
|
|
67
|
-
logger.info(Log::GoodJob::Start.new(
|
|
68
|
-
**base_fields.to_kwargs,
|
|
69
|
-
wait_ms: begin
|
|
70
|
-
wt = execution&.wait_time || calculate_wait_time(execution)
|
|
71
|
-
wt ? (wt.to_f * 1000.0) : nil
|
|
72
|
-
end,
|
|
73
|
-
scheduled_at: (job&.scheduled_at ? Time.at(job.scheduled_at.to_i) : nil),
|
|
74
|
-
process_id: ::Process.pid,
|
|
75
|
-
thread_id: Thread.current.object_id.to_s(36),
|
|
76
|
-
timestamp: ts
|
|
77
|
-
))
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Job completed successfully event
|
|
81
|
-
sig { params(event: ::ActiveSupport::Notifications::Event).void }
|
|
82
|
-
def finish(event)
|
|
83
|
-
payload = T.let(event.payload, T::Hash[Symbol, T.untyped])
|
|
84
|
-
job = payload[:job]
|
|
85
|
-
base_fields = build_base_fields(job, payload)
|
|
86
|
-
start_ts = EventTime.coerce_event_time(event.time)
|
|
87
|
-
end_ts = EventTime.coerce_event_time(event.end)
|
|
88
|
-
|
|
89
|
-
logger.info(Log::GoodJob::Finish.new(
|
|
90
|
-
**base_fields.to_kwargs,
|
|
91
|
-
duration_ms: event.duration.to_f,
|
|
92
|
-
finished_at: end_ts,
|
|
93
|
-
process_id: ::Process.pid,
|
|
94
|
-
thread_id: Thread.current.object_id.to_s(36),
|
|
95
|
-
result: payload[:result]&.to_s,
|
|
96
|
-
timestamp: start_ts
|
|
97
|
-
))
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
# Job failed with error event
|
|
101
|
-
sig { params(event: ::ActiveSupport::Notifications::Event).void }
|
|
102
|
-
def error(event)
|
|
103
|
-
payload = T.let(event.payload, T::Hash[Symbol, T.untyped])
|
|
104
|
-
job = payload[:job]
|
|
105
|
-
execution = payload[:execution] || payload[:good_job_execution]
|
|
106
|
-
exception = payload[:exception] || payload[:error]
|
|
107
|
-
ts = EventTime.coerce_event_time(event.time)
|
|
108
|
-
base_fields = build_base_fields(job, payload)
|
|
109
|
-
|
|
110
|
-
logger.error(Log::GoodJob::Error.new(
|
|
111
|
-
**base_fields.to_kwargs,
|
|
112
|
-
exception_executions: execution&.exception_executions,
|
|
113
|
-
error_class: exception&.class&.name,
|
|
114
|
-
error_message: exception&.message,
|
|
115
|
-
backtrace: exception&.backtrace,
|
|
116
|
-
duration_ms: event.duration.to_f,
|
|
117
|
-
process_id: ::Process.pid,
|
|
118
|
-
thread_id: Thread.current.object_id.to_s(36),
|
|
119
|
-
timestamp: ts
|
|
120
|
-
))
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
# Job scheduled for future execution event
|
|
124
|
-
sig { params(event: ::ActiveSupport::Notifications::Event).void }
|
|
125
|
-
def schedule(event)
|
|
126
|
-
payload = T.let(event.payload, T::Hash[Symbol, T.untyped])
|
|
127
|
-
job = payload[:job]
|
|
128
|
-
base_fields = build_base_fields(job, payload)
|
|
129
|
-
ts = EventTime.coerce_event_time(event.time)
|
|
130
|
-
|
|
131
|
-
logger.info(Log::GoodJob::Schedule.new(
|
|
132
|
-
**base_fields.to_kwargs,
|
|
133
|
-
scheduled_at: (job&.scheduled_at ? Time.at(job.scheduled_at.to_i) : nil),
|
|
134
|
-
priority: job&.priority,
|
|
135
|
-
cron_key: job&.cron_key,
|
|
136
|
-
duration_ms: event.duration.to_f,
|
|
137
|
-
timestamp: ts
|
|
138
|
-
))
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
private
|
|
142
|
-
|
|
143
|
-
# Build BaseFields from job + payload (execution)
|
|
144
|
-
sig { params(job: T.untyped, payload: T::Hash[Symbol, T.untyped]).returns(Log::GoodJob::BaseFields) }
|
|
145
|
-
def build_base_fields(job, payload)
|
|
146
|
-
execution = payload[:execution] || payload[:good_job_execution]
|
|
147
|
-
Log::GoodJob::BaseFields.new(
|
|
148
|
-
job_id: job&.job_id,
|
|
149
|
-
job_class: job&.job_class,
|
|
150
|
-
queue_name: job&.queue_name&.to_sym,
|
|
151
|
-
arguments: job&.arguments,
|
|
152
|
-
executions: execution&.executions
|
|
153
|
-
)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
# Calculate wait time from job creation to execution start
|
|
157
|
-
sig { params(execution: T.untyped).returns(T.nilable(Float)) }
|
|
158
|
-
def calculate_wait_time(execution)
|
|
159
|
-
return nil unless execution.respond_to?(:created_at)
|
|
160
|
-
return nil unless execution.respond_to?(:performed_at)
|
|
161
|
-
return nil unless execution.created_at && execution.performed_at
|
|
162
|
-
|
|
163
|
-
(execution.performed_at - execution.created_at).to_f
|
|
164
|
-
rescue
|
|
165
|
-
# Return nil if calculation fails
|
|
166
|
-
nil
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
# Get the appropriate logger for GoodJob events
|
|
170
|
-
sig { returns(T.untyped) }
|
|
171
|
-
def logger
|
|
172
|
-
# Always use Rails.logger - in production it will be configured by the integration setup,
|
|
173
|
-
# in tests it will be set up by the test harness
|
|
174
|
-
Rails.logger
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# typed: strict
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require "rack"
|
|
5
|
-
require "action_dispatch/middleware/show_exceptions"
|
|
6
|
-
require_relative "rack/error_handling_middleware"
|
|
7
|
-
require_relative "rack_setup"
|
|
8
|
-
|
|
9
|
-
module LogStruct
|
|
10
|
-
module Integrations
|
|
11
|
-
# Rack middleware integration for structured logging
|
|
12
|
-
module Rack
|
|
13
|
-
extend T::Sig
|
|
14
|
-
extend IntegrationInterface
|
|
15
|
-
|
|
16
|
-
# Set up Rack middleware for structured error logging
|
|
17
|
-
sig { override.params(config: LogStruct::Configuration).returns(T.nilable(T::Boolean)) }
|
|
18
|
-
def self.setup(config)
|
|
19
|
-
return nil unless RackSetup.enabled?(config)
|
|
20
|
-
|
|
21
|
-
# Add structured logging middleware for security violations and errors
|
|
22
|
-
# Need to insert after ShowExceptions to catch IP spoofing errors
|
|
23
|
-
RackSetup.insert_after(
|
|
24
|
-
::ActionDispatch::ShowExceptions,
|
|
25
|
-
Integrations::RackErrorHandler::Middleware
|
|
26
|
-
)
|
|
27
|
-
true
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|