legion-logging 1.5.2 → 1.5.4

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: 57e4eef04828ffa39cae5277822be4f2f5264d4010b05e724dbb179f0af5b771
4
- data.tar.gz: 740663a6979cf6b5c5d90a12bc8c43e0fcd989b8d8253269d8a1f1bf9aff9d03
3
+ metadata.gz: 3a7e958bdf135cd4798a6619992fd2661a9864b13dab2133c378d67ccea54380
4
+ data.tar.gz: 280391287ca3a8e15f91979e63bdbb3f4f7bab3c0e71bcc1f47b9a4eac378cb0
5
5
  SHA512:
6
- metadata.gz: c590642e775a8f6ed7f87f9b4525049033c3e3f42635ea2e460e5b4ddd89e646a97d8744b80755a82db340ba6e813d8e95e3a8b27ffc17a63f8f3aee99e5b5a6
7
- data.tar.gz: b812f47d57057a466655f22ae1f3922b6326a22fd40297ce602850069092efaf20ff40a6689ecbfe22a7498429bb3266df70ec40efb69617d11da045695155bd
6
+ metadata.gz: 55b8db2c9e50ad4d9d91f10379821c33c0cacdeed46a1da16a23d49835108f65ab9d59305bd3c421219510932d58f684c2816c7b39e39d51dc36ad65396a8afe
7
+ data.tar.gz: c7914b118692f0e2738ab5a68af4290e117b275b320a43a548ae5e85366f6f8cfec5f16f3c611f2b47a9f7e90a5446063f77c97ef3bb98a5e169a6dee177e9ad
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Legion::Logging Changelog
2
2
 
3
+ ## [1.5.4] - 2026-05-22
4
+
5
+ ### Added
6
+ - Structured log and exception AMQP writer headers now include `legion_protocol_version`, best-effort `x-legion-version`, and transport-standard `x-legion-identity-*` headers when process identity is resolved.
7
+ - `log_writer` now receives the same `headers:` and `properties:` envelope metadata shape as `exception_writer`.
8
+
9
+ ## [1.5.3] - 2026-05-13
10
+
11
+ ### Added
12
+ - `backtrace_limit:` kwarg on `log_exception` and `handle_exception` (nil=full, 0=suppress, N=cap at N frames)
13
+ - `backtrace_limit` key in `Legion::Logging::Settings.default` (defaults to nil — full backtraces)
14
+ - Settings-driven default reads from `Legion::Settings[:logging][:backtrace_limit]` when no explicit kwarg is passed
15
+
3
16
  ## [1.5.2] - 2026-04-27
4
17
 
5
18
  ### Changed
data/CLAUDE.md CHANGED
@@ -1,92 +1,46 @@
1
- # legion-logging: Logging Framework for LegionIO
1
+ # legion-logging
2
2
 
3
- **Repository Level 3 Documentation**
4
- - **Parent**: `/Users/miverso2/rubymine/legion/CLAUDE.md`
5
-
6
- ## Purpose
7
-
8
- Ruby logging class for the LegionIO framework. Provides colorized console output via Rainbow, structured JSON logging (`format: :json`), and a consistent logging interface across all Legion gems and extensions.
3
+ Structured logging framework for LegionIO. Provides colorized console output (Rainbow), structured JSON logging, and a consistent interface across all Legion gems and extensions.
9
4
 
10
5
  **GitHub**: https://github.com/LegionIO/legion-logging
11
- **Version**: 1.5.0
12
- **License**: Apache-2.0
6
+ **Version**: 1.5.3
13
7
 
14
8
  ## Architecture
15
9
 
16
10
  ```
17
11
  Legion::Logging (singleton module)
18
- ├── Methods # Log level methods: debug, info, warn, error, fatal, unknown; log_exception helper
19
- ├── Builder # Output destination (stdout/file), log level, formatter, async: keyword
20
- ├── AsyncWriter # Non-blocking SizedQueue-backed writer thread; fatal calls bypass queue
21
- ├── Hooks # Callback registry for fatal/error/warn events (on_fatal, on_error, on_warn)
22
- ├── EventBuilder # Structured event payload builder (caller, exception, lex, gem metadata); fingerprint for dedup
23
- ├── Helper # Injectable log mixin for LEX extensions (derives logger tags from segments/class)
24
- ├── Logger # Core logger configuration and setup
25
- ├── MultiIO # Write to multiple destinations simultaneously
26
- ├── TaggedLogger # Logger wrapper that prepends structured tags to each message
27
- ├── CategoryRegistry # Registry of named log categories with description and expected_fields
28
- ├── MethodTracer # Tracing module for instrumenting method calls (call/return, formatted args)
29
- ├── SIEMExporter # PHI-redacting SIEM export (Splunk HEC, ELK/OpenSearch)
30
- ├── Shipper # Buffered log event forwarding; sub-transports: FileTransport, HttpTransport
31
- ├── Redactor # PII/PHI + secret pattern redaction; opt-in via logging.redaction.enabled
32
- └── Version # VERSION constant
33
-
34
- # Module-level writers (pluggable lambda slots replacing old Hooks for AMQP forwarding)
35
- Legion::Logging.log_writer # -> lambda(->(event, routing_key:) {})
36
- Legion::Logging.exception_writer # -> lambda(->(event, routing_key:, headers:, properties:) {})
12
+ ├── Methods # debug, info, warn, error, fatal, unknown; log_exception
13
+ ├── Builder # Output destination, log level, formatter, async: keyword
14
+ ├── AsyncWriter # Non-blocking SizedQueue-backed writer thread
15
+ ├── Hooks # Callback registry for fatal/error/warn events
16
+ ├── EventBuilder # Structured event payload + fingerprint for dedup
17
+ ├── Helper # Injectable log mixin for LEX extensions
18
+ ├── TaggedLogger # Prepends structured tags to each message
19
+ ├── CategoryRegistry # Named log categories with expected_fields
20
+ ├── SIEMExporter # PHI-redacting SIEM export (Splunk HEC, ELK)
21
+ ├── Shipper # Buffered forwarding (FileTransport, HttpTransport)
22
+ ├── Redactor # PII/PHI + secret pattern redaction (opt-in)
23
+ └── MultiIO # Write to multiple destinations simultaneously
24
+
25
+ # Module-level writer lambdas (pluggable forwarding slots)
26
+ Legion::Logging.log_writer # ->(event, routing_key:) {}
27
+ Legion::Logging.exception_writer # ->(event, routing_key:, headers:, properties:) {}
37
28
  ```
38
29
 
39
- ### Key Design Patterns
40
-
41
- - **Singleton Module**: `Legion::Logging` uses `class << self` — called directly: `Legion::Logging.info("msg")`
42
- - **Rainbow Colorization**: Console output uses Rainbow gem for colored terminal output. Color auto-disabled in JSON format and when writing to a log file.
43
- - **Setup Method**: `Legion::Logging.setup(level:, format:, async:, **options)` configures output, level, format, and async mode. Increments `configuration_generation` on each call.
44
- - **Async by Default**: `setup` enables async logging — calls return immediately. Fatal calls always bypass the queue. `stop_async_writer` flushes and stops on shutdown. Buffer size configurable via `Legion::Settings[:logging][:async][:buffer_size]` (default 10,000). Back-pressure: callers block when buffer is full.
45
- - **Structured JSON**: `format: :json` in settings outputs machine-parseable JSON log lines (disables color)
46
- - **Shared Interface**: Same method signature (`info`, `warn`, `error`, etc.) across all Legion components
47
- - **MultiIO**: Splits writes to stdout and a log file simultaneously (used by Builder when `log_file` is set)
48
- - **SIEMExporter**: PHI redaction (SSN, phone, MRN, DOB patterns), `export_to_splunk` (HEC), `format_for_elk`
49
- - **Hook Callbacks**: `on_fatal`, `on_error`, `on_warn` register procs called after each log at those levels. Hooks are gated by `enable_hooks!`/`disable_hooks!`. Hook failures are silently rescued. Hooks fire on the async writer thread; event context captured on caller thread.
50
- - **EventBuilder**: Builds structured event hashes from log context (caller location, exception info, lex identity, gem metadata). All from in-memory data, zero IO. `fingerprint` produces MD5 for dedup in log aggregation.
51
- - **Helper mixin**: `Legion::Logging::Helper` is injectable into LEX extensions. Derives logger tags from `segments`, `lex_filename`, or class name. Passes through `settings[:logger]` config when available.
52
- - **Writer Lambdas**: `log_writer` and `exception_writer` are module-level lambda slots for forwarding to external systems (AMQP, etc.). Default implementations are no-ops. Set via `Legion::Logging.log_writer = lambda`.
53
- - **CategoryRegistry**: Named log categories with description and expected_fields. Register via `Legion::Logging.register_category`. Used for structured log validation.
54
- - **Redactor**: Opt-in PII/PHI redaction (`logging.redaction.enabled: true`). Guards against Settings recursive init via `@loader` ivar check. Patterns: SSN, phone, MRN, DOB, Vault tokens, JWTs, bearer tokens, lease IDs.
30
+ ## Key Patterns
55
31
 
56
- ## Dependencies
57
-
58
- | Gem | Purpose |
59
- |-----|---------|
60
- | `rainbow` (~> 3) | Terminal colorization |
61
-
62
- ## File Map
63
-
64
- | Path | Purpose |
65
- |------|---------|
66
- | `lib/legion/logging.rb` | Module entry point |
67
- | `lib/legion/logging/methods.rb` | Log level methods |
68
- | `lib/legion/logging/builder.rb` | Output config and formatter (async: keyword) |
69
- | `lib/legion/logging/async_writer.rb` | Non-blocking SizedQueue-backed writer thread with back-pressure |
70
- | `lib/legion/logging/helper.rb` | Injectable log mixin for LEX extensions |
71
- | `lib/legion/logging/logger.rb` | Core logger setup |
72
- | `lib/legion/logging/multi_io.rb` | Multi-output IO (write to multiple destinations simultaneously) |
73
- | `lib/legion/logging/siem_exporter.rb` | PHI-redacting SIEM export helpers (Splunk HEC, ELK format) |
74
- | `lib/legion/logging/hooks.rb` | Callback registry (fatal/error/warn hook arrays, enable/disable/clear) |
75
- | `lib/legion/logging/event_builder.rb` | Structured event payload builder; `fingerprint` for MD5 dedup |
76
- | `lib/legion/logging/tagged_logger.rb` | Logger wrapper that prepends structured tags to each message |
77
- | `lib/legion/logging/category_registry.rb` | Named log category registration and lookup |
78
- | `lib/legion/logging/method_tracer.rb` | Method call tracing instrumentation (call/return, formatted args) |
79
- | `lib/legion/logging/shipper.rb` | Buffered log event forwarding to external systems |
80
- | `lib/legion/logging/shipper/file_transport.rb` | File-based log shipper transport |
81
- | `lib/legion/logging/shipper/http_transport.rb` | HTTP-based log shipper transport |
82
- | `lib/legion/logging/siem_exporter.rb` | PHI-redacting SIEM export (Splunk HEC, ELK format) |
83
- | `lib/legion/logging/redactor.rb` | PII/PHI + secret pattern redaction (opt-in) |
84
- | `lib/legion/logging/version.rb` | VERSION constant |
32
+ - **Singleton module** — `class << self`; called directly: `Legion::Logging.info("msg")`
33
+ - **Async by default** — `setup` enables async logging; fatal bypasses queue. Buffer size via `Settings[:logging][:async][:buffer_size]` (default 10,000). Back-pressure blocks callers when full.
34
+ - **Structured JSON** `format: :json` outputs machine-parseable JSON lines (disables color)
35
+ - **Helper mixin** — `Legion::Logging::Helper` injects into LEX extensions; derives tags from `segments`, `lex_filename`, or class name
36
+ - **Writer lambdas** — `log_writer` and `exception_writer` are module-level lambda slots for forwarding to external systems (AMQP, etc.). Default no-ops.
37
+ - **Redactor** — Opt-in (`logging.redaction.enabled: true`). Patterns: SSN, phone, MRN, DOB, Vault tokens, JWTs, bearer tokens, lease IDs. Guards against Settings recursive init.
38
+ - **Hook callbacks** — `on_fatal`, `on_error`, `on_warn` register procs; gated by `enable_hooks!`/`disable_hooks!`; fire on async writer thread
39
+ - **EventBuilder** — Structured event hashes from log context (caller, exception, lex identity). `fingerprint` produces MD5 for dedup.
85
40
 
86
41
  ## Role in LegionIO
87
42
 
88
- **Foundational gem** - used by `legion-cache`, `legion-data`, and `LegionIO` as a direct dependency. First module initialized during `Legion::Service` startup.
43
+ Foundational gem dependency of `legion-cache`, `legion-data`, and `LegionIO`. First module initialized during `Legion::Service` startup.
89
44
 
90
45
  ---
91
-
92
46
  **Maintained By**: Matthew Iverson (@Esity)
@@ -110,7 +110,9 @@ module Legion
110
110
  lex_name = event[:lex] || 'core'
111
111
  component = event.dig(:caller, :file).to_s[Legion::Logging::Methods::COMPONENT_REGEX, 1] || 'unknown'
112
112
  routing_key = "legion.logging.log.#{level}.#{lex_name}.#{component}"
113
- Legion::Logging.log_writer.call(event, routing_key: routing_key)
113
+ headers = Legion::Logging.send(:build_log_headers, event, component, level)
114
+ properties = Legion::Logging.send(:build_log_properties, level)
115
+ Legion::Logging.log_writer.call(event, routing_key: routing_key, headers: headers, properties: properties)
114
116
  Legion::Logging::Hooks.fire(level, entry.message, event) if defined?(Legion::Logging::Hooks)
115
117
  rescue StandardError => e
116
118
  warn("legion-log-writer writer error: #{e.message}")
@@ -487,8 +487,18 @@ module Legion
487
487
  context_line = build_context_line(event)
488
488
  lines << " #{context_line}" unless context_line.empty?
489
489
 
490
- bt = exception.backtrace
491
- bt.each { |frame| lines << " #{frame}" } if bt&.any?
490
+ max_frames = if event[:backtrace_limit].nil?
491
+ defined?(Legion::Settings) ? Legion::Settings[:logging][:backtrace_limit] : nil
492
+ else
493
+ event[:backtrace_limit]
494
+ end
495
+ unless max_frames&.zero?
496
+ bt = exception.backtrace
497
+ if bt&.any?
498
+ frames = max_frames ? bt.first(max_frames) : bt
499
+ frames.each { |frame| lines << " #{frame}" }
500
+ end
501
+ end
492
502
 
493
503
  lines.join("\n")
494
504
  end
@@ -549,21 +559,70 @@ module Legion
549
559
 
550
560
  def build_exception_headers(event, comp, level)
551
561
  headers = {
552
- 'x-error-fingerprint' => event[:error_fingerprint],
553
- 'x-exception-class' => event[:exception_class],
554
- 'x-handled' => event[:handled].to_s,
555
- 'x-gem-name' => event[:gem_name].to_s,
556
- 'x-lex-version' => event[:lex_version].to_s,
557
- 'x-component-type' => comp.to_s,
558
- 'x-level' => level.to_s
562
+ 'legion_protocol_version' => '2.0',
563
+ 'x-error-fingerprint' => event[:error_fingerprint],
564
+ 'x-exception-class' => event[:exception_class],
565
+ 'x-handled' => event[:handled].to_s,
566
+ 'x-gem-name' => event[:gem_name].to_s,
567
+ 'x-lex-version' => event[:lex_version].to_s,
568
+ 'x-component-type' => comp.to_s,
569
+ 'x-level' => level.to_s
559
570
  }
571
+ append_legion_version_header(headers)
560
572
  headers['x-task-id'] = event[:task_id].to_s if event[:task_id]
561
573
  headers['x-conversation-id'] = event[:conversation_id].to_s if event[:conversation_id]
562
574
  headers['x-chain-id'] = event[:chain_id].to_s if event[:chain_id]
563
575
  headers['x-user'] = event[:user].to_s if event[:user]
576
+ append_identity_headers(headers)
564
577
  headers
565
578
  end
566
579
 
580
+ def append_identity_headers(headers)
581
+ return unless defined?(Legion::Identity::Process)
582
+ return if Legion::Identity::Process.respond_to?(:resolved?) && !Legion::Identity::Process.resolved?
583
+
584
+ id = identity_hash
585
+ append_optional_header(headers, 'x-legion-identity-canonical-name', id[:canonical_name])
586
+ append_optional_header(headers, 'x-legion-identity-trust', id[:trust])
587
+ append_optional_header(headers, 'x-legion-identity-id', id[:id])
588
+ append_optional_header(headers, 'x-legion-identity-kind', id[:kind])
589
+ append_optional_header(headers, 'x-legion-identity-mode', id[:mode])
590
+ append_optional_header(headers, 'x-legion-identity-source', id[:source])
591
+ headers['x-legion-identity-db-principal-id'] = id[:db_principal_id] if id[:db_principal_id]
592
+ headers['x-legion-identity-db-identity-id'] = id[:db_identity_id] if id[:db_identity_id]
593
+ rescue StandardError
594
+ nil
595
+ end
596
+
597
+ def append_optional_header(headers, key, value)
598
+ return if value.nil?
599
+ return if value.respond_to?(:empty?) && value.empty?
600
+
601
+ headers[key] = value.to_s
602
+ end
603
+
604
+ def append_legion_version_header(headers)
605
+ append_optional_header(headers, 'x-legion-version', Legion::VERSION) if defined?(Legion::VERSION)
606
+ end
607
+
608
+ def identity_hash
609
+ process = Legion::Identity::Process
610
+ return process.identity_hash if process.respond_to?(:identity_hash)
611
+
612
+ {
613
+ canonical_name: identity_value(process, :canonical_name),
614
+ id: identity_value(process, :id),
615
+ kind: identity_value(process, :kind),
616
+ mode: identity_value(process, :mode),
617
+ source: identity_value(process, :source),
618
+ trust: identity_value(process, :trust)
619
+ }
620
+ end
621
+
622
+ def identity_value(process, method_name)
623
+ process.public_send(method_name) if process.respond_to?(method_name)
624
+ end
625
+
567
626
  def build_exception_properties(event, level)
568
627
  {
569
628
  content_type: 'application/json',
@@ -102,17 +102,12 @@ module Legion
102
102
  def log_exception(exception, level: :error, lex: nil, component_type: nil,
103
103
  gem_name: nil, lex_version: nil, gem_path: nil,
104
104
  source_code_uri: nil, handled: false, payload_summary: nil,
105
- task_id: nil, **extra)
105
+ task_id: nil, backtrace_limit: nil, **extra)
106
106
  level = level.to_sym if level.respond_to?(:to_sym)
107
107
  # 1. Log human-readable line + backtrace to stdout/file (bypass writer callbacks)
108
108
  msg = exception.respond_to?(:message) ? exception.message : exception.to_s
109
109
  msg = maybe_redact(msg)
110
- bt = Array(exception.backtrace)
111
- if bt.any?
112
- lines = ["#{exception.class}: #{msg}"]
113
- bt.each { |frame| lines << " #{frame}" }
114
- msg = lines.join("\n")
115
- end
110
+ msg = build_exception_log_message(exception, msg, backtrace_limit)
116
111
  log.public_send(level, msg) if respond_to?(:log) && log.respond_to?(level)
117
112
 
118
113
  # 2. Build rich exception event
@@ -155,6 +150,30 @@ module Legion
155
150
 
156
151
  private
157
152
 
153
+ def resolve_backtrace_limit(explicit_limit)
154
+ return explicit_limit unless explicit_limit.nil?
155
+ return nil unless defined?(Legion::Settings)
156
+
157
+ Legion::Settings[:logging][:backtrace_limit]
158
+ end
159
+
160
+ def build_exception_log_message(exception, msg, backtrace_limit)
161
+ max_frames = resolve_backtrace_limit(backtrace_limit)
162
+ bt = collect_backtrace_frames(exception, max_frames)
163
+ return msg unless bt.any?
164
+
165
+ lines = ["#{exception.class}: #{msg}"]
166
+ bt.each { |frame| lines << " #{frame}" }
167
+ lines.join("\n")
168
+ end
169
+
170
+ def collect_backtrace_frames(exception, max_frames)
171
+ return [] if max_frames&.zero?
172
+
173
+ frames = Array(exception.backtrace)
174
+ max_frames ? frames.first(max_frames) : frames
175
+ end
176
+
158
177
  def maybe_redact(message)
159
178
  return message unless message.is_a?(String)
160
179
  return message unless redaction_enabled?
@@ -251,6 +270,48 @@ module Legion
251
270
  false
252
271
  end
253
272
 
273
+ def build_log_headers(event, component, level)
274
+ headers = {
275
+ 'legion_protocol_version' => '2.0',
276
+ 'x-component-type' => component.to_s,
277
+ 'x-level' => level.to_s
278
+ }
279
+ append_legion_version_header(headers)
280
+ append_optional_header(headers, 'x-lex', event[:lex])
281
+ append_optional_header(headers, 'x-node', event[:node])
282
+ append_identity_headers(headers)
283
+ headers
284
+ end
285
+
286
+ def build_log_properties(level)
287
+ {
288
+ content_type: 'application/json',
289
+ message_id: SecureRandom.uuid,
290
+ timestamp: Time.now.to_i,
291
+ app_id: 'legionio',
292
+ type: 'log_event',
293
+ priority: EXCEPTION_PRIORITY[level] || 0,
294
+ delivery_mode: 2
295
+ }
296
+ end
297
+
298
+ def append_identity_headers(headers)
299
+ return unless defined?(Legion::Identity::Process)
300
+ return if Legion::Identity::Process.respond_to?(:resolved?) && !Legion::Identity::Process.resolved?
301
+
302
+ id = identity_hash
303
+ append_optional_header(headers, 'x-legion-identity-canonical-name', id[:canonical_name])
304
+ append_optional_header(headers, 'x-legion-identity-trust', id[:trust])
305
+ append_optional_header(headers, 'x-legion-identity-id', id[:id])
306
+ append_optional_header(headers, 'x-legion-identity-kind', id[:kind])
307
+ append_optional_header(headers, 'x-legion-identity-mode', id[:mode])
308
+ append_optional_header(headers, 'x-legion-identity-source', id[:source])
309
+ headers['x-legion-identity-db-principal-id'] = id[:db_principal_id] if id[:db_principal_id]
310
+ headers['x-legion-identity-db-identity-id'] = id[:db_identity_id] if id[:db_identity_id]
311
+ rescue StandardError
312
+ nil
313
+ end
314
+
254
315
  def publish_exception_event(event, level)
255
316
  lex_name = event[:lex] || 'core'
256
317
  comp = event[:component_type] || :unknown
@@ -262,17 +323,20 @@ module Legion
262
323
 
263
324
  def build_exception_headers(event, comp, level)
264
325
  headers = {
265
- 'x-error-fingerprint' => event[:error_fingerprint],
266
- 'x-exception-class' => event[:exception_class],
267
- 'x-handled' => event[:handled].to_s,
268
- 'x-gem-name' => event[:gem_name].to_s,
269
- 'x-lex-version' => event[:lex_version].to_s,
270
- 'x-component-type' => comp.to_s,
271
- 'x-level' => level.to_s
326
+ 'legion_protocol_version' => '2.0',
327
+ 'x-error-fingerprint' => event[:error_fingerprint],
328
+ 'x-exception-class' => event[:exception_class],
329
+ 'x-handled' => event[:handled].to_s,
330
+ 'x-gem-name' => event[:gem_name].to_s,
331
+ 'x-lex-version' => event[:lex_version].to_s,
332
+ 'x-component-type' => comp.to_s,
333
+ 'x-level' => level.to_s
272
334
  }
335
+ append_legion_version_header(headers)
273
336
  append_optional_header(headers, 'x-task-id', event[:task_id])
274
337
  append_optional_header(headers, 'x-conversation-id', event[:conversation_id])
275
338
  append_optional_header(headers, 'x-user', event[:user])
339
+ append_identity_headers(headers)
276
340
  headers
277
341
  end
278
342
 
@@ -283,6 +347,28 @@ module Legion
283
347
  headers[key] = value.to_s
284
348
  end
285
349
 
350
+ def append_legion_version_header(headers)
351
+ append_optional_header(headers, 'x-legion-version', Legion::VERSION) if defined?(Legion::VERSION)
352
+ end
353
+
354
+ def identity_hash
355
+ process = Legion::Identity::Process
356
+ return process.identity_hash if process.respond_to?(:identity_hash)
357
+
358
+ {
359
+ canonical_name: identity_value(process, :canonical_name),
360
+ id: identity_value(process, :id),
361
+ kind: identity_value(process, :kind),
362
+ mode: identity_value(process, :mode),
363
+ source: identity_value(process, :source),
364
+ trust: identity_value(process, :trust)
365
+ }
366
+ end
367
+
368
+ def identity_value(process, method_name)
369
+ process.public_send(method_name) if process.respond_to?(method_name)
370
+ end
371
+
286
372
  def build_exception_properties(event, level)
287
373
  {
288
374
  content_type: 'application/json',
@@ -328,7 +414,9 @@ module Legion
328
414
  lex_name = event[:lex] || 'core'
329
415
  component = event.dig(:caller, :file).to_s[COMPONENT_REGEX, 1] || 'unknown'
330
416
  routing_key = "legion.logging.log.#{level}.#{lex_name}.#{component}"
331
- Legion::Logging.log_writer.call(event, routing_key: routing_key)
417
+ headers = build_log_headers(event, component, level)
418
+ properties = build_log_properties(level)
419
+ Legion::Logging.log_writer.call(event, routing_key: routing_key, headers: headers, properties: properties)
332
420
  Legion::Logging::Hooks.fire(level, message, event) if defined?(Legion::Logging::Hooks)
333
421
  rescue StandardError => e
334
422
  rk = defined?(routing_key) ? routing_key : 'unknown'
@@ -5,10 +5,11 @@ module Legion
5
5
  module Settings
6
6
  def self.default
7
7
  {
8
- level: :info,
9
- trace: true,
10
- trace_size: 4,
11
- extended: true
8
+ level: :info,
9
+ trace: true,
10
+ trace_size: 4,
11
+ extended: true,
12
+ backtrace_limit: nil
12
13
  }
13
14
  end
14
15
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Logging
5
- VERSION = '1.5.2'
5
+ VERSION = '1.5.4'
6
6
  end
7
7
  end
@@ -25,7 +25,7 @@ module Legion
25
25
  attr_reader :color
26
26
  attr_writer :log_writer, :exception_writer
27
27
 
28
- DEFAULT_LOG_WRITER = ->(_event, routing_key:) {}
28
+ DEFAULT_LOG_WRITER = ->(_event, routing_key:, headers: nil, properties: nil) {}
29
29
  DEFAULT_EXCEPTION_WRITER = ->(_event, routing_key:, headers:, properties:) {}
30
30
 
31
31
  def log_writer
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-logging
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.2
4
+ version: 1.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity