11//! Google Cloud Platform structured logging using JSON, following
22//! <https://cloud.google.com/logging/docs/structured-logging>.
33
4- use std:: fmt:: { self , Write } ;
54use std:: io:: IoSlice ;
65
76use log:: { kv, Record } ;
87
9- #[ cfg( feature = "timestamp" ) ]
10- use crate :: format:: format_timestamp;
118use crate :: format:: json;
129use crate :: format:: { Buffer , Format , BUFS_SIZE } ;
1310use crate :: PANIC_TARGET ;
@@ -28,18 +25,18 @@ impl Format for Gcloud {
2825 // Write all parts of the buffer that need formatting.
2926 buf. buf [ 0 ] = b'{' ;
3027 #[ cfg( feature = "timestamp" ) ]
31- write_timestamp ( buf) ;
32- write_msg ( buf, record. args ( ) ) ;
33- write_key_values ( buf, record. key_values ( ) , kvs) ;
28+ json :: write_timestamp ( buf) ;
29+ json :: write_msg ( buf, record. args ( ) ) ;
30+ json :: write_key_values ( buf, record. key_values ( ) , kvs) ;
3431 if add_loc {
35- write_line ( buf, record. line ( ) . unwrap_or ( 0 ) ) ;
32+ json :: write_line ( buf, record. line ( ) . unwrap_or ( 0 ) ) ;
3633 }
3734
3835 // Now that we've written the message to our buffer we have to construct it.
3936 // The first part of the message is the timestamp and log level (severity),
4037 // e.g. `{"timestamp":"2020-12-31T12:32:23.906132Z","severity":"INFO`.
4138 // Or without a timestamp, i.e. `{"severity":"INFO`.
42- bufs[ 0 ] = IoSlice :: new ( timestamp ( buf) ) ;
39+ bufs[ 0 ] = IoSlice :: new ( json :: timestamp ( buf) ) ;
4340 bufs[ 1 ] = IoSlice :: new ( b"\" severity\" :\" " ) ;
4441 if record. level ( ) == log:: Level :: Error && record. target ( ) == PANIC_TARGET {
4542 // If we're panicking we increase the severity to critical.
@@ -49,23 +46,23 @@ impl Format for Gcloud {
4946 }
5047 // The message (and the end of the log level), e.g. `","message":"some message`.
5148 bufs[ 3 ] = IoSlice :: new ( b"\" ,\" message\" :\" " ) ;
52- bufs[ 4 ] = IoSlice :: new ( msg ( buf) ) ;
49+ bufs[ 4 ] = IoSlice :: new ( json :: msg ( buf) ) ;
5350 // The target, e.g. `","target":"request`.
5451 bufs[ 5 ] = IoSlice :: new ( b"\" ,\" target\" :\" " ) ;
5552 bufs[ 6 ] = IoSlice :: new ( record. target ( ) . as_bytes ( ) ) ;
5653 // The module, e.g. `","module":"stored::http`.
5754 bufs[ 7 ] = IoSlice :: new ( b"\" ,\" module\" :\" " ) ;
5855 bufs[ 8 ] = IoSlice :: new ( record. module_path ( ) . unwrap_or ( "" ) . as_bytes ( ) ) ;
5956 // Any key value pairs supplied by the user.
60- bufs[ 9 ] = IoSlice :: new ( key_values ( buf) ) ;
57+ bufs[ 9 ] = IoSlice :: new ( json :: key_values ( buf) ) ;
6158 // Optional file, e.g.
6259 // `","sourceLocation":{"file":"some_file.rs","line":"123"}}`, and a line
6360 // end.
6461 let n = if add_loc {
6562 bufs[ 10 ] = IoSlice :: new ( b",\" sourceLocation\" :{\" file\" :\" " ) ;
6663 bufs[ 11 ] = IoSlice :: new ( record. file ( ) . unwrap_or ( "??" ) . as_bytes ( ) ) ;
6764 bufs[ 12 ] = IoSlice :: new ( b"\" ,\" line\" :\" " ) ;
68- bufs[ 13 ] = IoSlice :: new ( line ( buf) ) ;
65+ bufs[ 13 ] = IoSlice :: new ( json :: line ( buf) ) ;
6966 bufs[ 14 ] = IoSlice :: new ( b"\" }}\n " ) ;
7067 15
7168 } else {
@@ -76,90 +73,9 @@ impl Format for Gcloud {
7673 }
7774}
7875
79- /// Index of the end of `{"timestamp":"0000-00-00T00:00:00.000000Z",`.
80- #[ cfg( feature = "timestamp" ) ]
81- const TS_END_INDEX : usize = 43 ;
82- #[ cfg( not( feature = "timestamp" ) ) ]
83- const TS_END_INDEX : usize = 1 ;
84-
85- #[ inline]
86- #[ cfg( feature = "timestamp" ) ]
87- fn write_timestamp ( buf : & mut Buffer ) {
88- let _ = buf. buf [ TS_END_INDEX ] ;
89- buf. buf [ 1 ] = b'"' ;
90- buf. buf [ 2 ] = b't' ;
91- buf. buf [ 3 ] = b'i' ;
92- buf. buf [ 4 ] = b'm' ;
93- buf. buf [ 5 ] = b'e' ;
94- buf. buf [ 6 ] = b's' ;
95- buf. buf [ 7 ] = b't' ;
96- buf. buf [ 8 ] = b'a' ;
97- buf. buf [ 9 ] = b'm' ;
98- buf. buf [ 10 ] = b'p' ;
99- buf. buf [ 11 ] = b'"' ;
100- buf. buf [ 12 ] = b':' ;
101- buf. buf [ 13 ] = b'"' ;
102- format_timestamp ( & mut buf. buf [ 14 ..] ) ;
103- buf. buf [ TS_END_INDEX - 2 ] = b'"' ;
104- buf. buf [ TS_END_INDEX - 1 ] = b',' ;
105- }
106-
107- #[ inline]
108- fn timestamp ( buf : & Buffer ) -> & [ u8 ] {
109- & buf. buf [ ..TS_END_INDEX ]
110- }
111-
11276#[ inline]
11377const fn severity ( level : log:: Level ) -> & ' static [ u8 ] {
11478 // NOTE: gcloud doesn't have trace messages so we use debug twice.
11579 const SEVERITIES : [ & [ u8 ] ; 6 ] = [ b"OFF" , b"ERROR" , b"WARNING" , b"INFO" , b"DEBUG" , b"DEBUG" ] ;
11680 SEVERITIES [ level as usize ]
11781}
118-
119- #[ inline]
120- fn write_msg ( buf : & mut Buffer , args : & fmt:: Arguments ) {
121- buf. buf . truncate ( TS_END_INDEX ) ;
122- if let Some ( msg) = args. as_str ( ) {
123- json:: Buf ( & mut buf. buf )
124- . write_str ( msg)
125- . unwrap_or_else ( |_| unreachable ! ( ) ) ;
126- } else {
127- json:: Buf ( & mut buf. buf )
128- . write_fmt ( * args)
129- . unwrap_or_else ( |_| unreachable ! ( ) ) ;
130- }
131- buf. indices [ 0 ] = buf. buf . len ( ) ;
132- }
133-
134- #[ inline]
135- fn msg ( buf : & Buffer ) -> & [ u8 ] {
136- & buf. buf [ TS_END_INDEX ..buf. indices [ 0 ] ]
137- }
138-
139- #[ inline]
140- fn write_key_values < Kvs : kv:: Source > ( buf : & mut Buffer , kvs1 : & dyn kv:: Source , kvs2 : Kvs ) {
141- buf. buf . extend_from_slice ( b"\" " ) ;
142- // TODO: see if we can add to the slice of `IoSlice` using the keys
143- // and string values.
144- let mut visitor = json:: KeyValueVisitor ( & mut buf. buf ) ;
145- kvs1. visit ( & mut visitor) . unwrap_or_else ( |_| unreachable ! ( ) ) ;
146- kvs2. visit ( & mut visitor) . unwrap_or_else ( |_| unreachable ! ( ) ) ;
147- buf. indices [ 1 ] = buf. buf . len ( ) ;
148- }
149-
150- #[ inline]
151- fn key_values ( buf : & Buffer ) -> & [ u8 ] {
152- & buf. buf [ buf. indices [ 0 ] ..buf. indices [ 1 ] ]
153- }
154-
155- #[ inline]
156- fn write_line ( buf : & mut Buffer , line : u32 ) {
157- let mut itoa = itoa:: Buffer :: new ( ) ;
158- buf. buf . extend_from_slice ( itoa. format ( line) . as_bytes ( ) ) ;
159- buf. indices [ 2 ] = buf. buf . len ( ) ;
160- }
161-
162- #[ inline]
163- fn line ( buf : & Buffer ) -> & [ u8 ] {
164- & buf. buf [ buf. indices [ 1 ] ..buf. indices [ 2 ] ]
165- }
0 commit comments