@@ -62,14 +62,16 @@ mod socket;
62
62
/// names by translating `.`s into `_`s, stripping leading `_`s and non-ascii-alphanumeric
63
63
/// characters other than `_`, and upcasing.
64
64
///
65
- /// Levels are mapped losslessly to journald `PRIORITY` values as follows:
65
+ /// By default, levels are mapped losslessly to journald `PRIORITY` values as follows:
66
66
///
67
67
/// - `ERROR` => Error (3)
68
68
/// - `WARN` => Warning (4)
69
69
/// - `INFO` => Notice (5)
70
70
/// - `DEBUG` => Informational (6)
71
71
/// - `TRACE` => Debug (7)
72
72
///
73
+ /// These mappings can be changed with [`Subscriber::with_priority_mappings`].
74
+ ///
73
75
/// The standard journald `CODE_LINE` and `CODE_FILE` fields are automatically emitted. A `TARGET`
74
76
/// field is emitted containing the event's target.
75
77
///
@@ -86,6 +88,7 @@ pub struct Subscriber {
86
88
field_prefix : Option < String > ,
87
89
syslog_identifier : String ,
88
90
additional_fields : Vec < u8 > ,
91
+ priority_mappings : PriorityMappings ,
89
92
}
90
93
91
94
#[ cfg( unix) ]
@@ -111,6 +114,7 @@ impl Subscriber {
111
114
// If we fail to get the name of the current executable fall back to an empty string.
112
115
. unwrap_or_default ( ) ,
113
116
additional_fields : Vec :: new ( ) ,
117
+ priority_mappings : PriorityMappings :: new ( ) ,
114
118
} ;
115
119
// Check that we can talk to journald, by sending empty payload which journald discards.
116
120
// However if the socket didn't exist or if none listened we'd get an error here.
@@ -131,6 +135,41 @@ impl Subscriber {
131
135
self
132
136
}
133
137
138
+ /// Sets how [`tracing_core::Level`]s are mapped to [journald priorities](Priority).
139
+ ///
140
+ /// # Examples
141
+ ///
142
+ /// ```rust
143
+ /// use tracing_journald::{Priority, PriorityMappings};
144
+ /// use tracing_subscriber::prelude::*;
145
+ /// use tracing::error;
146
+ ///
147
+ /// let registry = tracing_subscriber::registry();
148
+ /// match tracing_journald::subscriber() {
149
+ /// Ok(subscriber) => {
150
+ /// registry.with(
151
+ /// subscriber
152
+ /// // We can tweak the mappings between the trace level and
153
+ /// // the journal priorities.
154
+ /// .with_priority_mappings(PriorityMappings {
155
+ /// info: Priority::Informational,
156
+ /// ..PriorityMappings::new()
157
+ /// }),
158
+ /// );
159
+ /// }
160
+ /// // journald is typically available on Linux systems, but nowhere else. Portable software
161
+ /// // should handle its absence gracefully.
162
+ /// Err(e) => {
163
+ /// registry.init();
164
+ /// error!("couldn't connect to journald: {}", e);
165
+ /// }
166
+ /// }
167
+ /// ```
168
+ pub fn with_priority_mappings ( mut self , mappings : PriorityMappings ) -> Self {
169
+ self . priority_mappings = mappings;
170
+ self
171
+ }
172
+
134
173
/// Sets the syslog identifier for this logger.
135
174
///
136
175
/// The syslog identifier comes from the classic syslog interface (`openlog()`
@@ -234,6 +273,20 @@ impl Subscriber {
234
273
memfd:: seal_fully ( mem. as_raw_fd ( ) ) ?;
235
274
socket:: send_one_fd_to ( & self . socket , mem. as_raw_fd ( ) , JOURNALD_PATH )
236
275
}
276
+
277
+ fn put_priority ( & self , buf : & mut Vec < u8 > , meta : & Metadata ) {
278
+ put_field_wellformed (
279
+ buf,
280
+ "PRIORITY" ,
281
+ & [ match * meta. level ( ) {
282
+ Level :: ERROR => self . priority_mappings . error as u8 ,
283
+ Level :: WARN => self . priority_mappings . warn as u8 ,
284
+ Level :: INFO => self . priority_mappings . info as u8 ,
285
+ Level :: DEBUG => self . priority_mappings . debug as u8 ,
286
+ Level :: TRACE => self . priority_mappings . trace as u8 ,
287
+ } ] ,
288
+ ) ;
289
+ }
237
290
}
238
291
239
292
/// Construct a journald subscriber
@@ -288,7 +341,7 @@ where
288
341
}
289
342
290
343
// Record event fields
291
- put_priority ( & mut buf, event. metadata ( ) ) ;
344
+ self . put_priority ( & mut buf, event. metadata ( ) ) ;
292
345
put_metadata ( & mut buf, event. metadata ( ) , None ) ;
293
346
put_field_length_encoded ( & mut buf, "SYSLOG_IDENTIFIER" , |buf| {
294
347
write ! ( buf, "{}" , self . syslog_identifier) . unwrap ( )
@@ -376,18 +429,114 @@ impl Visit for EventVisitor<'_> {
376
429
}
377
430
}
378
431
379
- fn put_priority ( buf : & mut Vec < u8 > , meta : & Metadata ) {
380
- put_field_wellformed (
381
- buf,
382
- "PRIORITY" ,
383
- match * meta. level ( ) {
384
- Level :: ERROR => b"3" ,
385
- Level :: WARN => b"4" ,
386
- Level :: INFO => b"5" ,
387
- Level :: DEBUG => b"6" ,
388
- Level :: TRACE => b"7" ,
389
- } ,
390
- ) ;
432
+ /// A priority (called "severity code" by syslog) is used to mark the
433
+ /// importance of a message.
434
+ ///
435
+ /// Descriptions and examples are taken from the [Arch Linux wiki].
436
+ /// Priorities are also documented in the
437
+ /// [section 6.2.1 of the Syslog protocol RFC][syslog].
438
+ ///
439
+ /// [Arch Linux wiki]: https://wiki.archlinux.org/title/Systemd/Journal#Priority_level
440
+ /// [syslog]: https://www.rfc-editor.org/rfc/rfc5424#section-6.2.1
441
+ #[ derive( Debug , Clone , Copy , Hash , PartialEq , Eq ) ]
442
+ #[ repr( u8 ) ]
443
+ pub enum Priority {
444
+ /// System is unusable.
445
+ ///
446
+ /// Examples:
447
+ ///
448
+ /// - severe Kernel BUG
449
+ /// - systemd dumped core
450
+ ///
451
+ /// This level should not be used by applications.
452
+ Emergency = b'0' ,
453
+ /// Should be corrected immediately.
454
+ ///
455
+ /// Examples:
456
+ ///
457
+ /// - Vital subsystem goes out of work, data loss:
458
+ /// - `kernel: BUG: unable to handle kernel paging request at ffffc90403238ffc`
459
+ Alert = b'1' ,
460
+ /// Critical conditions
461
+ ///
462
+ /// Examples:
463
+ ///
464
+ /// - Crashe, coredumps
465
+ /// - `systemd-coredump[25319]: Process 25310 (plugin-container) of user 1000 dumped core`
466
+ Critical = b'2' ,
467
+ /// Error conditions
468
+ ///
469
+ /// Examples:
470
+ ///
471
+ /// - Not severe error reported
472
+ /// - `kernel: usb 1-3: 3:1: cannot get freq at ep 0x84, systemd[1]: Failed unmounting /var`
473
+ /// - `libvirtd[1720]: internal error: Failed to initialize a valid firewall backend`
474
+ Error = b'3' ,
475
+ /// May indicate that an error will occur if action is not taken.
476
+ ///
477
+ /// Examples:
478
+ ///
479
+ /// - a non-root file system has only 1GB free
480
+ /// - `org.freedesktop. Notifications[1860]: (process:5999): Gtk-WARNING **: Locale not supported by C library. Using the fallback 'C' locale`
481
+ Warning = b'4' ,
482
+ /// Events that are unusual, but not error conditions.
483
+ ///
484
+ /// Examples:
485
+ ///
486
+ /// - `systemd[1]: var.mount: Directory /var to mount over is not empty, mounting anyway`
487
+ /// - `gcr-prompter[4997]: Gtk: GtkDialog mapped without a transient parent. This is discouraged`
488
+ Notice = b'5' ,
489
+ /// Normal operational messages that require no action.
490
+ ///
491
+ /// Example: `lvm[585]: 7 logical volume(s) in volume group "archvg" now active`
492
+ Informational = b'6' ,
493
+ /// Information useful to developers for debugging the
494
+ /// application.
495
+ ///
496
+ /// Example: `kdeinit5[1900]: powerdevil: Scheduling inhibition from ":1.14" "firefox" with cookie 13 and reason "screen"`
497
+ Debug = b'7' ,
498
+ }
499
+
500
+ /// Mappings from tracing [`Level`]s to journald [priorities].
501
+ ///
502
+ /// [priorities]: Priority
503
+ #[ derive( Debug , Clone ) ]
504
+ pub struct PriorityMappings {
505
+ /// Priority mapped to the `ERROR` level
506
+ pub error : Priority ,
507
+ /// Priority mapped to the `WARN` level
508
+ pub warn : Priority ,
509
+ /// Priority mapped to the `INFO` level
510
+ pub info : Priority ,
511
+ /// Priority mapped to the `DEBUG` level
512
+ pub debug : Priority ,
513
+ /// Priority mapped to the `TRACE` level
514
+ pub trace : Priority ,
515
+ }
516
+
517
+ impl PriorityMappings {
518
+ /// Returns the default priority mappings:
519
+ ///
520
+ /// - [`tracing::Level::ERROR`]: [`Priority::Error`] (3)
521
+ /// - [`tracing::Level::WARN`]: [`Priority::Warning`] (4)
522
+ /// - [`tracing::Level::INFO`]: [`Priority::Notice`] (5)
523
+ /// - [`tracing::Level::DEBUG`]: [`Priority::Informational`] (6)
524
+ /// - [`tracing::Level::TRACE`]: [`Priority::Debug`] (7)
525
+ pub fn new ( ) -> PriorityMappings {
526
+ Self {
527
+ error : Priority :: Error ,
528
+ warn : Priority :: Warning ,
529
+ info : Priority :: Notice ,
530
+ debug : Priority :: Informational ,
531
+ trace : Priority :: Debug ,
532
+ }
533
+ }
534
+ }
535
+
536
+ impl Default for PriorityMappings {
537
+ fn default ( ) -> Self {
538
+ Self :: new ( )
539
+ }
391
540
}
392
541
393
542
fn put_metadata ( buf : & mut Vec < u8 > , meta : & Metadata , prefix : Option < & str > ) {
0 commit comments