legion-logging 1.5.3 → 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: f751e228eb4c00edae10784b3edf4176afb2f84ec7a8df1525a9c8432145c50f
4
- data.tar.gz: 728db26335f6bffdcef54523760d9b8051615f0bee280ac01a897a3373b3403f
3
+ metadata.gz: 3a7e958bdf135cd4798a6619992fd2661a9864b13dab2133c378d67ccea54380
4
+ data.tar.gz: 280391287ca3a8e15f91979e63bdbb3f4f7bab3c0e71bcc1f47b9a4eac378cb0
5
5
  SHA512:
6
- metadata.gz: 3ba593790cf603ab542162e685c97450f7db2d18da76dd288981317ecf627b708a391e2b0f1eecfef43e3a308f0391a89a6bc636ab3216c6450a973d653b7e3e
7
- data.tar.gz: 5c6fb87b90d197c3f70e0d69e1d5a3a13c55083aa1f8ebbd79676ff8926b12686e3fa9b2df91286ac2a216ace987863eb719b21df8693e3f0981768a2f70f748
6
+ metadata.gz: 55b8db2c9e50ad4d9d91f10379821c33c0cacdeed46a1da16a23d49835108f65ab9d59305bd3c421219510932d58f684c2816c7b39e39d51dc36ad65396a8afe
7
+ data.tar.gz: c7914b118692f0e2738ab5a68af4290e117b275b320a43a548ae5e85366f6f8cfec5f16f3c611f2b47a9f7e90a5446063f77c97ef3bb98a5e169a6dee177e9ad
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
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
+
3
9
  ## [1.5.3] - 2026-05-13
4
10
 
5
11
  ### Added
@@ -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}")
@@ -559,21 +559,70 @@ module Legion
559
559
 
560
560
  def build_exception_headers(event, comp, level)
561
561
  headers = {
562
- 'x-error-fingerprint' => event[:error_fingerprint],
563
- 'x-exception-class' => event[:exception_class],
564
- 'x-handled' => event[:handled].to_s,
565
- 'x-gem-name' => event[:gem_name].to_s,
566
- 'x-lex-version' => event[:lex_version].to_s,
567
- 'x-component-type' => comp.to_s,
568
- '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
569
570
  }
571
+ append_legion_version_header(headers)
570
572
  headers['x-task-id'] = event[:task_id].to_s if event[:task_id]
571
573
  headers['x-conversation-id'] = event[:conversation_id].to_s if event[:conversation_id]
572
574
  headers['x-chain-id'] = event[:chain_id].to_s if event[:chain_id]
573
575
  headers['x-user'] = event[:user].to_s if event[:user]
576
+ append_identity_headers(headers)
574
577
  headers
575
578
  end
576
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
+
577
626
  def build_exception_properties(event, level)
578
627
  {
579
628
  content_type: 'application/json',
@@ -270,6 +270,48 @@ module Legion
270
270
  false
271
271
  end
272
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
+
273
315
  def publish_exception_event(event, level)
274
316
  lex_name = event[:lex] || 'core'
275
317
  comp = event[:component_type] || :unknown
@@ -281,17 +323,20 @@ module Legion
281
323
 
282
324
  def build_exception_headers(event, comp, level)
283
325
  headers = {
284
- 'x-error-fingerprint' => event[:error_fingerprint],
285
- 'x-exception-class' => event[:exception_class],
286
- 'x-handled' => event[:handled].to_s,
287
- 'x-gem-name' => event[:gem_name].to_s,
288
- 'x-lex-version' => event[:lex_version].to_s,
289
- 'x-component-type' => comp.to_s,
290
- '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
291
334
  }
335
+ append_legion_version_header(headers)
292
336
  append_optional_header(headers, 'x-task-id', event[:task_id])
293
337
  append_optional_header(headers, 'x-conversation-id', event[:conversation_id])
294
338
  append_optional_header(headers, 'x-user', event[:user])
339
+ append_identity_headers(headers)
295
340
  headers
296
341
  end
297
342
 
@@ -302,6 +347,28 @@ module Legion
302
347
  headers[key] = value.to_s
303
348
  end
304
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
+
305
372
  def build_exception_properties(event, level)
306
373
  {
307
374
  content_type: 'application/json',
@@ -347,7 +414,9 @@ module Legion
347
414
  lex_name = event[:lex] || 'core'
348
415
  component = event.dig(:caller, :file).to_s[COMPONENT_REGEX, 1] || 'unknown'
349
416
  routing_key = "legion.logging.log.#{level}.#{lex_name}.#{component}"
350
- 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)
351
420
  Legion::Logging::Hooks.fire(level, message, event) if defined?(Legion::Logging::Hooks)
352
421
  rescue StandardError => e
353
422
  rk = defined?(routing_key) ? routing_key : 'unknown'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Logging
5
- VERSION = '1.5.3'
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.3
4
+ version: 1.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity