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