@@ -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
///
@@ -85,6 +87,7 @@ pub struct Subscriber {
85
87
socket : UnixDatagram ,
86
88
field_prefix : Option < String > ,
87
89
syslog_identifier : String ,
90
+ priority_mappings : PriorityMappings ,
88
91
}
89
92
90
93
#[ cfg( unix) ]
@@ -109,6 +112,7 @@ impl Subscriber {
109
112
. map ( |n| n. to_string_lossy ( ) . into_owned ( ) )
110
113
// If we fail to get the name of the current executable fall back to an empty string.
111
114
. unwrap_or_else ( String :: new) ,
115
+ priority_mappings : PriorityMappings :: new ( ) ,
112
116
} ;
113
117
// Check that we can talk to journald, by sending empty payload which journald discards.
114
118
// However if the socket didn't exist or if none listened we'd get an error here.
@@ -129,6 +133,12 @@ impl Subscriber {
129
133
self
130
134
}
131
135
136
+ /// Sets the mappings from the tracing level to the journald priorities.
137
+ pub fn with_priority_mappings ( mut self , mappings : PriorityMappings ) -> Self {
138
+ self . priority_mappings = mappings;
139
+ self
140
+ }
141
+
132
142
/// Sets the syslog identifier for this logger.
133
143
///
134
144
/// The syslog identifier comes from the classic syslog interface (`openlog()`
@@ -198,6 +208,20 @@ impl Subscriber {
198
208
memfd:: seal_fully ( mem. as_raw_fd ( ) ) ?;
199
209
socket:: send_one_fd_to ( & self . socket , mem. as_raw_fd ( ) , JOURNALD_PATH )
200
210
}
211
+
212
+ fn put_priority ( & self , buf : & mut Vec < u8 > , meta : & Metadata ) {
213
+ put_field_wellformed (
214
+ buf,
215
+ "PRIORITY" ,
216
+ & [ match * meta. level ( ) {
217
+ Level :: ERROR => self . priority_mappings . error as u8 ,
218
+ Level :: WARN => self . priority_mappings . warn as u8 ,
219
+ Level :: INFO => self . priority_mappings . info as u8 ,
220
+ Level :: DEBUG => self . priority_mappings . debug as u8 ,
221
+ Level :: TRACE => self . priority_mappings . trace as u8 ,
222
+ } ] ,
223
+ ) ;
224
+ }
201
225
}
202
226
203
227
/// Construct a journald subscriber
@@ -252,7 +276,7 @@ where
252
276
}
253
277
254
278
// Record event fields
255
- put_priority ( & mut buf, event. metadata ( ) ) ;
279
+ self . put_priority ( & mut buf, event. metadata ( ) ) ;
256
280
put_metadata ( & mut buf, event. metadata ( ) , None ) ;
257
281
put_field_length_encoded ( & mut buf, "SYSLOG_IDENTIFIER" , |buf| {
258
282
write ! ( buf, "{}" , self . syslog_identifier) . unwrap ( )
@@ -339,18 +363,112 @@ impl Visit for EventVisitor<'_> {
339
363
}
340
364
}
341
365
342
- fn put_priority ( buf : & mut Vec < u8 > , meta : & Metadata ) {
343
- put_field_wellformed (
344
- buf,
345
- "PRIORITY" ,
346
- match * meta. level ( ) {
347
- Level :: ERROR => b"3" ,
348
- Level :: WARN => b"4" ,
349
- Level :: INFO => b"5" ,
350
- Level :: DEBUG => b"6" ,
351
- Level :: TRACE => b"7" ,
352
- } ,
353
- ) ;
366
+ /// A priority (in syslog called severity code) is used to mark the
367
+ /// importance of a message.
368
+ ///
369
+ /// Descriptions and examples are taken from the [Archlinux wiki].
370
+ /// Priorities are also documented in the
371
+ /// [section 6.2.1 of the Syslog protocol RFC][syslog].
372
+ ///
373
+ /// [Archlinux wiki]: https://wiki.archlinux.org/title/Systemd/Journal#Priority_level
374
+ /// [syslog]: https://www.rfc-editor.org/rfc/rfc5424#section-6.2.1
375
+ #[ derive( Debug , Clone , Copy , Hash , PartialEq , Eq ) ]
376
+ #[ repr( u8 ) ]
377
+ pub enum Priority {
378
+ /// System is unusable.
379
+ ///
380
+ /// Examples:
381
+ ///
382
+ /// - severe Kernel BUG
383
+ /// - systemd dumped core
384
+ ///
385
+ /// This level should not be used by applications.
386
+ Emergency = b'0' ,
387
+ /// Should be corrected immediately.
388
+ ///
389
+ /// Examples:
390
+ ///
391
+ /// - Vital subsystem goes out of work, data loss:
392
+ /// - `kernel: BUG: unable to handle kernel paging request at ffffc90403238ffc`
393
+ Alert = b'1' ,
394
+ /// Critical conditions
395
+ ///
396
+ /// Examples:
397
+ ///
398
+ /// - Crashe, coredumps
399
+ /// - `systemd-coredump[25319]: Process 25310 (plugin-container) of user 1000 dumped core`
400
+ Critical = b'2' ,
401
+ /// Error conditions
402
+ ///
403
+ /// Examples:
404
+ ///
405
+ /// - Not severe error reported
406
+ /// - `kernel: usb 1-3: 3:1: cannot get freq at ep 0x84, systemd[1]: Failed unmounting /var`
407
+ /// - `libvirtd[1720]: internal error: Failed to initialize a valid firewall backend`
408
+ Error = b'3' ,
409
+ /// May indicate that an error will occur if action is not taken.
410
+ ///
411
+ /// Examples:
412
+ ///
413
+ /// - a non-root file system has only 1GB free
414
+ /// - `org.freedesktop. Notifications[1860]: (process:5999): Gtk-WARNING **: Locale not supported by C library. Using the fallback 'C' locale`
415
+ Warning = b'4' ,
416
+ /// Events that are unusual, but not error conditions.
417
+ ///
418
+ /// Examples:
419
+ ///
420
+ /// - `systemd[1]: var.mount: Directory /var to mount over is not empty, mounting anyway`
421
+ /// - `gcr-prompter[4997]: Gtk: GtkDialog mapped without a transient parent. This is discouraged`
422
+ Notice = b'5' ,
423
+ /// Normal operational messages that require no action.
424
+ ///
425
+ /// Example: `lvm[585]: 7 logical volume(s) in volume group "archvg" now active`
426
+ Informational = b'6' ,
427
+ /// Information useful to developers for debugging the
428
+ /// application.
429
+ ///
430
+ /// Example: `kdeinit5[1900]: powerdevil: Scheduling inhibition from ":1.14" "firefox" with cookie 13 and reason "screen"`
431
+ Debug = b'7' ,
432
+ }
433
+
434
+ /// Mappings from the tracing levels to the journald priorities.
435
+ #[ derive( Debug , Clone ) ]
436
+ pub struct PriorityMappings {
437
+ /// Priority mapped to the `ERROR` level
438
+ pub error : Priority ,
439
+ /// Priority mapped to the `WARN` level
440
+ pub warn : Priority ,
441
+ /// Priority mapped to the `INFO` level
442
+ pub info : Priority ,
443
+ /// Priority mapped to the `DEBUG` level
444
+ pub debug : Priority ,
445
+ /// Priority mapped to the `TRACE` level
446
+ pub trace : Priority ,
447
+ }
448
+
449
+ impl PriorityMappings {
450
+ /// Create new default mappings:
451
+ ///
452
+ /// - `tracing::Level::ERROR`: Error (3)
453
+ /// - `tracing::Level::WARN`: Warning (4)
454
+ /// - `tracing::Level::INFO`: Notice (5)
455
+ /// - `tracing::Level::DEBUG`: Informational (6)
456
+ /// - `tracing::Level::TRACE`: Debug (7)
457
+ pub fn new ( ) -> PriorityMappings {
458
+ Self {
459
+ error : Priority :: Error ,
460
+ warn : Priority :: Warning ,
461
+ info : Priority :: Notice ,
462
+ debug : Priority :: Informational ,
463
+ trace : Priority :: Debug ,
464
+ }
465
+ }
466
+ }
467
+
468
+ impl Default for PriorityMappings {
469
+ fn default ( ) -> Self {
470
+ Self :: new ( )
471
+ }
354
472
}
355
473
356
474
fn put_metadata ( buf : & mut Vec < u8 > , meta : & Metadata , prefix : Option < & str > ) {
0 commit comments