logstruct 0.1.0 → 0.1.2
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 +11 -1
- data/README.md +23 -3
- data/lib/log_struct/boot_buffer.rb +28 -0
- data/lib/log_struct/builders/active_job.rb +84 -0
- data/lib/log_struct/concerns/configuration.rb +178 -15
- data/lib/log_struct/concerns/error_handling.rb +3 -7
- data/lib/log_struct/config_struct/filters.rb +18 -0
- data/lib/log_struct/config_struct/integrations.rb +8 -12
- data/lib/log_struct/configuration.rb +13 -0
- data/lib/log_struct/enums/event.rb +13 -0
- data/lib/log_struct/enums/log_field.rb +154 -0
- data/lib/log_struct/enums/source.rb +4 -1
- data/lib/log_struct/formatter.rb +29 -17
- data/lib/log_struct/integrations/action_mailer/error_handling.rb +3 -11
- data/lib/log_struct/integrations/action_mailer/event_logging.rb +22 -12
- data/lib/log_struct/integrations/active_job/log_subscriber.rb +52 -48
- data/lib/log_struct/integrations/active_model_serializers.rb +8 -14
- data/lib/log_struct/integrations/active_record.rb +35 -5
- data/lib/log_struct/integrations/active_storage.rb +59 -20
- data/lib/log_struct/integrations/ahoy.rb +2 -1
- data/lib/log_struct/integrations/carrierwave.rb +13 -16
- data/lib/log_struct/integrations/dotenv.rb +278 -0
- data/lib/log_struct/integrations/good_job/log_subscriber.rb +86 -136
- data/lib/log_struct/integrations/good_job/logger.rb +8 -10
- data/lib/log_struct/integrations/good_job.rb +5 -7
- data/lib/log_struct/integrations/host_authorization.rb +25 -4
- data/lib/log_struct/integrations/lograge.rb +20 -14
- data/lib/log_struct/integrations/puma.rb +477 -0
- data/lib/log_struct/integrations/rack_error_handler/middleware.rb +11 -18
- data/lib/log_struct/integrations/shrine.rb +44 -19
- data/lib/log_struct/integrations/sorbet.rb +48 -0
- data/lib/log_struct/integrations.rb +21 -0
- data/lib/log_struct/log/action_mailer/delivered.rb +99 -0
- data/lib/log_struct/log/action_mailer/delivery.rb +99 -0
- data/lib/log_struct/log/action_mailer.rb +30 -45
- data/lib/log_struct/log/active_job/enqueue.rb +125 -0
- data/lib/log_struct/log/active_job/finish.rb +130 -0
- data/lib/log_struct/log/active_job/schedule.rb +125 -0
- data/lib/log_struct/log/active_job/start.rb +130 -0
- data/lib/log_struct/log/active_job.rb +41 -54
- data/lib/log_struct/log/active_model_serializers.rb +72 -33
- data/lib/log_struct/log/active_storage/delete.rb +87 -0
- data/lib/log_struct/log/active_storage/download.rb +103 -0
- data/lib/log_struct/log/active_storage/exist.rb +93 -0
- data/lib/log_struct/log/active_storage/metadata.rb +93 -0
- data/lib/log_struct/log/active_storage/stream.rb +93 -0
- data/lib/log_struct/log/active_storage/upload.rb +118 -0
- data/lib/log_struct/log/active_storage/url.rb +93 -0
- data/lib/log_struct/log/active_storage.rb +32 -68
- data/lib/log_struct/log/ahoy.rb +67 -33
- data/lib/log_struct/log/carrierwave/delete.rb +115 -0
- data/lib/log_struct/log/carrierwave/download.rb +131 -0
- data/lib/log_struct/log/carrierwave/upload.rb +141 -0
- data/lib/log_struct/log/carrierwave.rb +37 -72
- data/lib/log_struct/log/dotenv/load.rb +76 -0
- data/lib/log_struct/log/dotenv/restore.rb +76 -0
- data/lib/log_struct/log/dotenv/save.rb +76 -0
- data/lib/log_struct/log/dotenv/update.rb +76 -0
- data/lib/log_struct/log/dotenv.rb +12 -0
- data/lib/log_struct/log/error.rb +58 -47
- data/lib/log_struct/log/good_job/enqueue.rb +126 -0
- data/lib/log_struct/log/good_job/error.rb +151 -0
- data/lib/log_struct/log/good_job/finish.rb +136 -0
- data/lib/log_struct/log/good_job/log.rb +131 -0
- data/lib/log_struct/log/good_job/schedule.rb +136 -0
- data/lib/log_struct/log/good_job/start.rb +136 -0
- data/lib/log_struct/log/good_job.rb +40 -141
- data/lib/log_struct/log/interfaces/additional_data_field.rb +1 -17
- data/lib/log_struct/log/interfaces/common_fields.rb +1 -39
- data/lib/log_struct/log/interfaces/public_common_fields.rb +1 -28
- data/lib/log_struct/log/interfaces/request_fields.rb +1 -33
- data/lib/log_struct/log/plain.rb +59 -34
- data/lib/log_struct/log/puma/shutdown.rb +80 -0
- data/lib/log_struct/log/puma/start.rb +120 -0
- data/lib/log_struct/log/puma.rb +10 -0
- data/lib/log_struct/log/request.rb +132 -48
- data/lib/log_struct/log/security/blocked_host.rb +141 -0
- data/lib/log_struct/log/security/csrf_violation.rb +131 -0
- data/lib/log_struct/log/security/ip_spoof.rb +141 -0
- data/lib/log_struct/log/security.rb +40 -70
- data/lib/log_struct/log/shared/add_request_fields.rb +1 -26
- data/lib/log_struct/log/shared/merge_additional_data_fields.rb +1 -22
- data/lib/log_struct/log/shared/serialize_common.rb +1 -33
- data/lib/log_struct/log/shared/serialize_common_public.rb +9 -9
- data/lib/log_struct/log/shrine/delete.rb +85 -0
- data/lib/log_struct/log/shrine/download.rb +90 -0
- data/lib/log_struct/log/shrine/exist.rb +90 -0
- data/lib/log_struct/log/shrine/metadata.rb +90 -0
- data/lib/log_struct/log/shrine/upload.rb +105 -0
- data/lib/log_struct/log/shrine.rb +10 -67
- data/lib/log_struct/log/sidekiq.rb +65 -26
- data/lib/log_struct/log/sql.rb +113 -106
- data/lib/log_struct/log.rb +29 -36
- data/lib/log_struct/multi_error_reporter.rb +80 -22
- data/lib/log_struct/param_filters.rb +50 -7
- data/lib/log_struct/rails_boot_banner_silencer.rb +116 -0
- data/lib/log_struct/railtie.rb +67 -0
- data/lib/log_struct/semantic_logger/formatter.rb +4 -2
- data/lib/log_struct/semantic_logger/setup.rb +34 -18
- data/lib/log_struct/shared/interfaces/additional_data_field.rb +22 -0
- data/lib/log_struct/shared/interfaces/common_fields.rb +39 -0
- data/lib/log_struct/shared/interfaces/public_common_fields.rb +29 -0
- data/lib/log_struct/shared/interfaces/request_fields.rb +39 -0
- data/lib/log_struct/shared/shared/add_request_fields.rb +28 -0
- data/lib/log_struct/shared/shared/merge_additional_data_fields.rb +27 -0
- data/lib/log_struct/shared/shared/serialize_common.rb +58 -0
- data/lib/log_struct/version.rb +1 -1
- data/lib/log_struct.rb +36 -4
- data/logstruct.gemspec +2 -1
- metadata +78 -9
- data/lib/log_struct/log/interfaces/message_field.rb +0 -20
- data/lib/log_struct/log_keys.rb +0 -102
@@ -0,0 +1,105 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# AUTO-GENERATED: DO NOT EDIT
|
5
|
+
# Generated by scripts/generate_structs.rb
|
6
|
+
# Schemas dir: schemas/log_sources/
|
7
|
+
# Template: tools/codegen/templates/sorbet/event.rb.erb
|
8
|
+
|
9
|
+
require "log_struct/shared/interfaces/common_fields"
|
10
|
+
require "log_struct/shared/interfaces/additional_data_field"
|
11
|
+
require "log_struct/shared/interfaces/request_fields"
|
12
|
+
require "log_struct/shared/shared/serialize_common"
|
13
|
+
require "log_struct/shared/shared/merge_additional_data_fields"
|
14
|
+
require "log_struct/shared/shared/add_request_fields"
|
15
|
+
require_relative "../../enums/source"
|
16
|
+
require_relative "../../enums/event"
|
17
|
+
require_relative "../../enums/level"
|
18
|
+
require_relative "../../enums/log_field"
|
19
|
+
|
20
|
+
module LogStruct
|
21
|
+
module Log
|
22
|
+
class Shrine
|
23
|
+
class Upload < T::Struct
|
24
|
+
# typed: strict
|
25
|
+
# frozen_string_literal: true
|
26
|
+
|
27
|
+
extend T::Sig
|
28
|
+
|
29
|
+
extend T::Sig
|
30
|
+
|
31
|
+
# Shared/common fields
|
32
|
+
const :source, Source::Shrine, default: Source::Shrine
|
33
|
+
const :event, Event, default: Event::Upload
|
34
|
+
const :timestamp, Time, factory: -> { Time.now }
|
35
|
+
const :level, Level, default: Level::Info
|
36
|
+
|
37
|
+
# Event-specific fields
|
38
|
+
const :storage, String
|
39
|
+
const :location, String
|
40
|
+
const :upload_options, T.nilable(T::Hash[Symbol, T.untyped]), default: nil
|
41
|
+
const :options, T.nilable(T::Hash[Symbol, T.untyped]), default: nil
|
42
|
+
const :uploader, T.nilable(String), default: nil
|
43
|
+
const :duration_ms, T.nilable(Float), default: nil
|
44
|
+
|
45
|
+
# Additional data
|
46
|
+
include LogStruct::Log::Interfaces::AdditionalDataField
|
47
|
+
const :additional_data, T.nilable(T::Hash[T.any(String, Symbol), T.untyped]), default: nil
|
48
|
+
include LogStruct::Log::Shared::MergeAdditionalDataFields
|
49
|
+
|
50
|
+
# Request fields (optional)
|
51
|
+
|
52
|
+
# Serialize shared fields
|
53
|
+
include LogStruct::Log::Interfaces::CommonFields
|
54
|
+
include LogStruct::Log::Shared::SerializeCommon
|
55
|
+
|
56
|
+
sig { returns(T::Hash[LogStruct::LogField, T.untyped]) }
|
57
|
+
def self.base_hash
|
58
|
+
{}
|
59
|
+
end
|
60
|
+
|
61
|
+
sig {
|
62
|
+
params(storage: T.untyped,
|
63
|
+
location: T.untyped,
|
64
|
+
upload_options: T.untyped,
|
65
|
+
options: T.untyped,
|
66
|
+
uploader: T.untyped,
|
67
|
+
duration_ms: T.untyped,
|
68
|
+
additional_data: T.untyped,
|
69
|
+
timestamp: T.untyped).returns(T::Hash[LogStruct::LogField, T.untyped])
|
70
|
+
}
|
71
|
+
def self.build(storage:,
|
72
|
+
location:,
|
73
|
+
upload_options: nil,
|
74
|
+
options: nil,
|
75
|
+
uploader: nil,
|
76
|
+
duration_ms: nil,
|
77
|
+
additional_data: nil,
|
78
|
+
timestamp: Time.now)
|
79
|
+
h = base_hash
|
80
|
+
h[LogField::Storage] = storage
|
81
|
+
h[LogField::Location] = location
|
82
|
+
h[LogField::UploadOptions] = upload_options unless upload_options.nil?
|
83
|
+
h[LogField::Options] = options unless options.nil?
|
84
|
+
h[LogField::Uploader] = uploader unless uploader.nil?
|
85
|
+
h[LogField::DurationMs] = duration_ms unless duration_ms.nil?
|
86
|
+
h
|
87
|
+
end
|
88
|
+
|
89
|
+
sig { returns(T::Hash[LogStruct::LogField, T.untyped]) }
|
90
|
+
def to_h
|
91
|
+
self.class.build(
|
92
|
+
storage: storage,
|
93
|
+
location: location,
|
94
|
+
upload_options: upload_options,
|
95
|
+
options: options,
|
96
|
+
uploader: uploader,
|
97
|
+
duration_ms: duration_ms,
|
98
|
+
additional_data: additional_data,
|
99
|
+
timestamp: timestamp
|
100
|
+
)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -1,70 +1,13 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
require_relative "
|
10
|
-
require_relative "
|
11
|
-
require_relative "
|
12
|
-
|
13
|
-
|
14
|
-
module Log
|
15
|
-
# Shrine log entry for structured logging
|
16
|
-
class Shrine < T::Struct
|
17
|
-
extend T::Sig
|
18
|
-
|
19
|
-
include Interfaces::CommonFields
|
20
|
-
include Interfaces::AdditionalDataField
|
21
|
-
include SerializeCommon
|
22
|
-
include MergeAdditionalDataFields
|
23
|
-
|
24
|
-
ShrineEvent = T.type_alias {
|
25
|
-
T.any(
|
26
|
-
Event::Upload,
|
27
|
-
Event::Download,
|
28
|
-
Event::Delete,
|
29
|
-
Event::Metadata,
|
30
|
-
Event::Exist,
|
31
|
-
Event::Unknown
|
32
|
-
)
|
33
|
-
}
|
34
|
-
|
35
|
-
# Common fields
|
36
|
-
const :source, Source::Shrine, default: T.let(Source::Shrine, Source::Shrine)
|
37
|
-
const :event, ShrineEvent
|
38
|
-
const :timestamp, Time, factory: -> { Time.now }
|
39
|
-
const :level, Level, default: T.let(Level::Info, Level)
|
40
|
-
|
41
|
-
# Shrine-specific fields
|
42
|
-
const :storage, T.nilable(String), default: nil
|
43
|
-
const :location, T.nilable(String), default: nil
|
44
|
-
const :upload_options, T.nilable(T::Hash[Symbol, T.untyped]), default: nil
|
45
|
-
const :download_options, T.nilable(T::Hash[Symbol, T.untyped]), default: nil
|
46
|
-
const :options, T.nilable(T::Hash[Symbol, T.untyped]), default: nil
|
47
|
-
const :uploader, T.nilable(String), default: nil
|
48
|
-
const :duration, T.nilable(Float), default: nil
|
49
|
-
const :additional_data, T::Hash[Symbol, T.untyped], default: {}
|
50
|
-
|
51
|
-
# Convert the log entry to a hash for serialization
|
52
|
-
sig { override.params(strict: T::Boolean).returns(T::Hash[Symbol, T.untyped]) }
|
53
|
-
def serialize(strict = true)
|
54
|
-
hash = serialize_common(strict)
|
55
|
-
merge_additional_data_fields(hash)
|
56
|
-
|
57
|
-
# Add Shrine-specific fields if they're present
|
58
|
-
hash[LOG_KEYS.fetch(:storage)] = storage if storage
|
59
|
-
hash[LOG_KEYS.fetch(:location)] = location if location
|
60
|
-
hash[LOG_KEYS.fetch(:upload_options)] = upload_options if upload_options
|
61
|
-
hash[LOG_KEYS.fetch(:download_options)] = download_options if download_options
|
62
|
-
hash[LOG_KEYS.fetch(:options)] = options if options
|
63
|
-
hash[LOG_KEYS.fetch(:uploader)] = uploader if uploader
|
64
|
-
hash[LOG_KEYS.fetch(:duration)] = duration if duration
|
65
|
-
|
66
|
-
hash
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
4
|
+
# AUTO-GENERATED: DO NOT EDIT
|
5
|
+
# Generated by scripts/generate_structs.rb
|
6
|
+
# Schemas dir: schemas/log_sources/
|
7
|
+
# Template: tools/codegen/templates/sorbet/source_parent.rb.erb
|
8
|
+
|
9
|
+
require_relative "shrine/upload"
|
10
|
+
require_relative "shrine/download"
|
11
|
+
require_relative "shrine/delete"
|
12
|
+
require_relative "shrine/metadata"
|
13
|
+
require_relative "shrine/exist"
|
@@ -1,49 +1,88 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
# AUTO-GENERATED: DO NOT EDIT
|
5
|
+
# Generated by scripts/generate_structs.rb
|
6
|
+
# Schemas dir: schemas/log_sources/
|
7
|
+
# Template: tools/codegen/templates/sorbet/event.rb.erb
|
8
|
+
|
9
|
+
require "log_struct/shared/interfaces/common_fields"
|
10
|
+
require "log_struct/shared/interfaces/additional_data_field"
|
11
|
+
require "log_struct/shared/interfaces/request_fields"
|
12
|
+
require "log_struct/shared/shared/serialize_common"
|
13
|
+
require "log_struct/shared/shared/merge_additional_data_fields"
|
14
|
+
require "log_struct/shared/shared/add_request_fields"
|
6
15
|
require_relative "../enums/source"
|
7
16
|
require_relative "../enums/event"
|
8
17
|
require_relative "../enums/level"
|
9
|
-
require_relative "../
|
18
|
+
require_relative "../enums/log_field"
|
10
19
|
|
11
20
|
module LogStruct
|
12
21
|
module Log
|
13
|
-
# Sidekiq log entry for structured logging
|
14
22
|
class Sidekiq < T::Struct
|
15
|
-
|
23
|
+
# typed: strict
|
24
|
+
# frozen_string_literal: true
|
16
25
|
|
17
|
-
|
18
|
-
include SerializeCommon
|
26
|
+
extend T::Sig
|
19
27
|
|
20
|
-
|
21
|
-
SidekiqEvent = T.type_alias { Event::Log }
|
28
|
+
extend T::Sig
|
22
29
|
|
23
|
-
#
|
24
|
-
const :source, Source::Sidekiq, default:
|
25
|
-
const :event,
|
30
|
+
# Shared/common fields
|
31
|
+
const :source, Source::Sidekiq, default: Source::Sidekiq
|
32
|
+
const :event, Event, default: Event::Log
|
26
33
|
const :timestamp, Time, factory: -> { Time.now }
|
27
|
-
const :level, Level, default:
|
34
|
+
const :level, Level, default: Level::Info
|
28
35
|
|
29
|
-
#
|
30
|
-
const :process_id, T.nilable(Integer), default: nil
|
31
|
-
const :thread_id, T.nilable(T.any(Integer, String)), default: nil
|
36
|
+
# Event-specific fields
|
32
37
|
const :message, T.nilable(String), default: nil
|
33
38
|
const :context, T.nilable(T::Hash[Symbol, T.untyped]), default: nil
|
39
|
+
const :process_id, T.nilable(Integer), default: nil
|
40
|
+
const :thread_id, T.nilable(T.any(Integer, String)), default: nil
|
41
|
+
|
42
|
+
# Additional data
|
43
|
+
|
44
|
+
# Request fields (optional)
|
34
45
|
|
35
|
-
#
|
36
|
-
|
37
|
-
|
38
|
-
hash = serialize_common(strict)
|
46
|
+
# Serialize shared fields
|
47
|
+
include LogStruct::Log::Interfaces::CommonFields
|
48
|
+
include LogStruct::Log::Shared::SerializeCommon
|
39
49
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
50
|
+
sig { returns(T::Hash[LogStruct::LogField, T.untyped]) }
|
51
|
+
def self.base_hash
|
52
|
+
{}
|
53
|
+
end
|
54
|
+
|
55
|
+
sig {
|
56
|
+
params(message: T.untyped,
|
57
|
+
context: T.untyped,
|
58
|
+
process_id: T.untyped,
|
59
|
+
thread_id: T.untyped,
|
60
|
+
additional_data: T.untyped,
|
61
|
+
timestamp: T.untyped).returns(T::Hash[LogStruct::LogField, T.untyped])
|
62
|
+
}
|
63
|
+
def self.build(message: nil,
|
64
|
+
context: nil,
|
65
|
+
process_id: nil,
|
66
|
+
thread_id: nil,
|
67
|
+
additional_data: nil,
|
68
|
+
timestamp: Time.now)
|
69
|
+
h = base_hash
|
70
|
+
h[LogField::Message] = message unless message.nil?
|
71
|
+
h[LogField::Context] = context unless context.nil?
|
72
|
+
h[LogField::ProcessId] = process_id unless process_id.nil?
|
73
|
+
h[LogField::ThreadId] = thread_id unless thread_id.nil?
|
74
|
+
h
|
75
|
+
end
|
45
76
|
|
46
|
-
|
77
|
+
sig { returns(T::Hash[LogStruct::LogField, T.untyped]) }
|
78
|
+
def to_h
|
79
|
+
self.class.build(
|
80
|
+
message: message,
|
81
|
+
context: context,
|
82
|
+
process_id: process_id,
|
83
|
+
thread_id: thread_id,
|
84
|
+
timestamp: timestamp
|
85
|
+
)
|
47
86
|
end
|
48
87
|
end
|
49
88
|
end
|
data/lib/log_struct/log/sql.rb
CHANGED
@@ -1,125 +1,132 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
# AUTO-GENERATED: DO NOT EDIT
|
5
|
+
# Generated by scripts/generate_structs.rb
|
6
|
+
# Schemas dir: schemas/log_sources/
|
7
|
+
# Template: tools/codegen/templates/sorbet/event.rb.erb
|
8
|
+
|
9
|
+
require "log_struct/shared/interfaces/common_fields"
|
10
|
+
require "log_struct/shared/interfaces/additional_data_field"
|
11
|
+
require "log_struct/shared/interfaces/request_fields"
|
12
|
+
require "log_struct/shared/shared/serialize_common"
|
13
|
+
require "log_struct/shared/shared/merge_additional_data_fields"
|
14
|
+
require "log_struct/shared/shared/add_request_fields"
|
15
|
+
require_relative "../enums/source"
|
16
|
+
require_relative "../enums/event"
|
17
|
+
require_relative "../enums/level"
|
18
|
+
require_relative "../enums/log_field"
|
8
19
|
|
9
20
|
module LogStruct
|
10
21
|
module Log
|
11
|
-
# SQL Query Log Structure
|
12
|
-
#
|
13
|
-
# Captures detailed information about SQL queries executed through ActiveRecord.
|
14
|
-
# This provides structured logging for database operations, including:
|
15
|
-
# - Query text and operation name
|
16
|
-
# - Execution timing and performance metrics
|
17
|
-
# - Row counts and connection information
|
18
|
-
# - Safely filtered bind parameters
|
19
|
-
#
|
20
|
-
# ## Use Cases:
|
21
|
-
# - Development debugging of N+1 queries
|
22
|
-
# - Production performance monitoring
|
23
|
-
# - Database query analysis and optimization
|
24
|
-
# - Audit trails for data access patterns
|
25
|
-
#
|
26
|
-
# ## Security:
|
27
|
-
# - SQL queries are safe (always parameterized with ?)
|
28
|
-
# - Bind parameters are filtered through LogStruct's param filters
|
29
|
-
# - Sensitive data like passwords, tokens are automatically scrubbed
|
30
|
-
#
|
31
|
-
# ## Example Usage:
|
32
|
-
#
|
33
|
-
# ```ruby
|
34
|
-
# # Automatically captured when SQL query integration is enabled
|
35
|
-
# LogStruct.config.integrations.enable_sql_logging = true
|
36
|
-
#
|
37
|
-
# # Manual logging (rare)
|
38
|
-
# sql_log = LogStruct::Log::SQL.new(
|
39
|
-
# message: "User lookup query",
|
40
|
-
# sql: "SELECT * FROM users WHERE id = ?",
|
41
|
-
# name: "User Load",
|
42
|
-
# duration: 2.3,
|
43
|
-
# row_count: 1,
|
44
|
-
# bind_params: [123]
|
45
|
-
# )
|
46
|
-
# LogStruct.info(sql_log)
|
47
|
-
# ```
|
48
22
|
class SQL < T::Struct
|
23
|
+
# typed: strict
|
24
|
+
# frozen_string_literal: true
|
25
|
+
|
49
26
|
extend T::Sig
|
50
|
-
include Interfaces::CommonFields
|
51
|
-
include Interfaces::AdditionalDataField
|
52
|
-
include SerializeCommon
|
53
|
-
include MergeAdditionalDataFields
|
54
27
|
|
55
|
-
|
56
|
-
Event::Database
|
57
|
-
}
|
28
|
+
extend T::Sig
|
58
29
|
|
59
|
-
#
|
60
|
-
const :source, Source, default:
|
61
|
-
const :event,
|
62
|
-
const :level, Level, default: T.let(Level::Info, Level)
|
30
|
+
# Shared/common fields
|
31
|
+
const :source, Source::App, default: Source::App
|
32
|
+
const :event, Event, default: Event::Database
|
63
33
|
const :timestamp, Time, factory: -> { Time.now }
|
64
|
-
const :
|
34
|
+
const :level, Level, default: Level::Info
|
65
35
|
|
66
|
-
#
|
36
|
+
# Event-specific fields
|
37
|
+
const :message, String
|
67
38
|
const :sql, String
|
68
|
-
|
69
|
-
# The name of the database operation (e.g., "User Load", "Post Create")
|
70
39
|
const :name, String
|
40
|
+
const :duration_ms, Float
|
41
|
+
const :row_count, T.nilable(Integer), default: nil
|
42
|
+
const :adapter, T.nilable(String), default: nil
|
43
|
+
const :bind_params, T.nilable(T::Array[T.untyped]), default: nil
|
44
|
+
const :database_name, T.nilable(String), default: nil
|
45
|
+
const :connection_pool_size, T.nilable(Integer), default: nil
|
46
|
+
const :active_connections, T.nilable(Integer), default: nil
|
47
|
+
const :operation_type, T.nilable(String), default: nil
|
48
|
+
const :table_names, T.nilable(T::Array[String]), default: nil
|
49
|
+
|
50
|
+
# Additional data
|
51
|
+
include LogStruct::Log::Interfaces::AdditionalDataField
|
52
|
+
const :additional_data, T.nilable(T::Hash[T.any(String, Symbol), T.untyped]), default: nil
|
53
|
+
include LogStruct::Log::Shared::MergeAdditionalDataFields
|
54
|
+
|
55
|
+
# Request fields (optional)
|
56
|
+
|
57
|
+
# Serialize shared fields
|
58
|
+
include LogStruct::Log::Interfaces::CommonFields
|
59
|
+
include LogStruct::Log::Shared::SerializeCommon
|
60
|
+
|
61
|
+
sig { returns(T::Hash[LogStruct::LogField, T.untyped]) }
|
62
|
+
def self.base_hash
|
63
|
+
{}
|
64
|
+
end
|
71
65
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
hash[LOG_KEYS.fetch(:connection_pool_size)] = connection_pool_size
|
118
|
-
hash[LOG_KEYS.fetch(:active_connections)] = active_connections
|
119
|
-
hash[LOG_KEYS.fetch(:operation_type)] = operation_type
|
120
|
-
hash[LOG_KEYS.fetch(:table_names)] = table_names
|
66
|
+
sig {
|
67
|
+
params(message: T.untyped,
|
68
|
+
sql: T.untyped,
|
69
|
+
name: T.untyped,
|
70
|
+
duration_ms: T.untyped,
|
71
|
+
row_count: T.untyped,
|
72
|
+
adapter: T.untyped,
|
73
|
+
bind_params: T.untyped,
|
74
|
+
database_name: T.untyped,
|
75
|
+
connection_pool_size: T.untyped,
|
76
|
+
active_connections: T.untyped,
|
77
|
+
operation_type: T.untyped,
|
78
|
+
table_names: T.untyped,
|
79
|
+
additional_data: T.untyped,
|
80
|
+
timestamp: T.untyped).returns(T::Hash[LogStruct::LogField, T.untyped])
|
81
|
+
}
|
82
|
+
def self.build(message:,
|
83
|
+
sql:,
|
84
|
+
name:,
|
85
|
+
duration_ms:,
|
86
|
+
row_count: nil,
|
87
|
+
adapter: nil,
|
88
|
+
bind_params: nil,
|
89
|
+
database_name: nil,
|
90
|
+
connection_pool_size: nil,
|
91
|
+
active_connections: nil,
|
92
|
+
operation_type: nil,
|
93
|
+
table_names: nil,
|
94
|
+
additional_data: nil,
|
95
|
+
timestamp: Time.now)
|
96
|
+
h = base_hash
|
97
|
+
h[LogField::Message] = message
|
98
|
+
h[LogField::Sql] = sql
|
99
|
+
h[LogField::Name] = name
|
100
|
+
h[LogField::DurationMs] = duration_ms
|
101
|
+
h[LogField::RowCount] = row_count unless row_count.nil?
|
102
|
+
h[LogField::Adapter] = adapter unless adapter.nil?
|
103
|
+
h[LogField::BindParams] = bind_params unless bind_params.nil?
|
104
|
+
h[LogField::DatabaseName] = database_name unless database_name.nil?
|
105
|
+
h[LogField::ConnectionPoolSize] = connection_pool_size unless connection_pool_size.nil?
|
106
|
+
h[LogField::ActiveConnections] = active_connections unless active_connections.nil?
|
107
|
+
h[LogField::OperationType] = operation_type unless operation_type.nil?
|
108
|
+
h[LogField::TableNames] = table_names unless table_names.nil?
|
109
|
+
h
|
110
|
+
end
|
121
111
|
|
122
|
-
|
112
|
+
sig { returns(T::Hash[LogStruct::LogField, T.untyped]) }
|
113
|
+
def to_h
|
114
|
+
self.class.build(
|
115
|
+
message: message,
|
116
|
+
sql: sql,
|
117
|
+
name: name,
|
118
|
+
duration_ms: duration_ms,
|
119
|
+
row_count: row_count,
|
120
|
+
adapter: adapter,
|
121
|
+
bind_params: bind_params,
|
122
|
+
database_name: database_name,
|
123
|
+
connection_pool_size: connection_pool_size,
|
124
|
+
active_connections: active_connections,
|
125
|
+
operation_type: operation_type,
|
126
|
+
table_names: table_names,
|
127
|
+
additional_data: additional_data,
|
128
|
+
timestamp: timestamp
|
129
|
+
)
|
123
130
|
end
|
124
131
|
end
|
125
132
|
end
|
data/lib/log_struct/log.rb
CHANGED
@@ -1,49 +1,42 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
# Common
|
4
|
+
# Common enums and shared interfaces
|
5
5
|
require_relative "enums/source"
|
6
6
|
require_relative "enums/event"
|
7
7
|
require_relative "enums/level"
|
8
|
+
require_relative "enums/log_field"
|
8
9
|
require_relative "log/interfaces/public_common_fields"
|
9
10
|
require_relative "log/shared/serialize_common_public"
|
10
11
|
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
require_relative "log/error"
|
17
|
-
require_relative "log/good_job"
|
18
|
-
require_relative "log/plain"
|
19
|
-
require_relative "log/request"
|
20
|
-
require_relative "log/security"
|
21
|
-
require_relative "log/shrine"
|
22
|
-
require_relative "log/sidekiq"
|
23
|
-
require_relative "log/sql"
|
24
|
-
require_relative "log/ahoy"
|
25
|
-
require_relative "log/active_model_serializers"
|
12
|
+
# Dynamically require all top-level log structs under log/*
|
13
|
+
# Nested per-event files are required by their parent files.
|
14
|
+
Dir[File.join(__dir__, "log", "*.rb")].sort.each do |file|
|
15
|
+
require file
|
16
|
+
end
|
26
17
|
|
27
18
|
module LogStruct
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
19
|
+
module Log
|
20
|
+
extend T::Sig
|
21
|
+
|
22
|
+
# Build an Error log from an exception with optional context and timestamp
|
23
|
+
sig do
|
24
|
+
params(
|
25
|
+
source: Source,
|
26
|
+
ex: StandardError,
|
27
|
+
additional_data: T::Hash[T.any(String, Symbol), T.untyped],
|
28
|
+
timestamp: Time
|
29
|
+
).returns(LogStruct::Log::Error)
|
30
|
+
end
|
31
|
+
def self.from_exception(source, ex, additional_data = {}, timestamp = Time.now)
|
32
|
+
LogStruct::Log::Error.new(
|
33
|
+
source: source,
|
34
|
+
err_class: ex.class,
|
35
|
+
message: ex.message,
|
36
|
+
backtrace: ex.backtrace,
|
37
|
+
additional_data: additional_data,
|
38
|
+
timestamp: timestamp
|
39
|
+
)
|
40
|
+
end
|
48
41
|
end
|
49
42
|
end
|