@@ -15,22 +15,23 @@ use crate::db::filename::{generate_filename, FileType};
15
15
use crate :: error:: Result ;
16
16
use crate :: storage:: { File , Storage } ;
17
17
18
+
18
19
use log:: { LevelFilter , Log , Metadata , Record } ;
19
20
use slog:: { o, Drain , Level } ;
20
21
21
22
use chrono:: prelude:: * ;
22
23
use std:: sync:: Mutex ;
24
+
23
25
/// A `slog` based logger which can be used with `log` crate
24
26
///
25
27
/// See `slog` at https://github.com/slog-rs/slog
26
28
/// See `log` at https://github.com/rust-lang/log
27
29
///
28
30
29
- fn create_file < S : Storage > ( storage : & S , dp_path : & str , timestamp : i64 ) -> Result < S :: F > {
30
- let new_path = generate_filename ( dp_path, FileType :: OldInfoLog , timestamp as u64 ) ;
31
- storage. rename ( dp_path, new_path. as_str ( ) ) ?;
32
- storage. create ( dp_path)
33
-
31
+ pub fn create_file < S : Storage > ( storage : & S , db_path : & str , timestamp : i64 ) -> Result < S :: F > {
32
+ let new_path = generate_filename ( db_path, FileType :: Log , timestamp as u64 ) ;
33
+ storage. create ( new_path)
34
+
34
35
}
35
36
36
37
pub struct Logger {
@@ -49,7 +50,7 @@ impl Logger {
49
50
inner : Option < slog:: Logger > ,
50
51
level : LevelFilter ,
51
52
storage : S ,
52
- db_path : String ,
53
+ db_path : & ' static str ,
53
54
) -> Self {
54
55
let inner = match inner {
55
56
Some ( l) => l,
@@ -62,12 +63,13 @@ impl Logger {
62
63
} else {
63
64
// Use a file `Log` to record all logs
64
65
// TODO: add file rotation
65
- let file = create_file ( & storage, db_path. as_str ( ) , Local :: now ( ) . timestamp ( ) ) . unwrap ( ) ;
66
- let file_fn = move |path : String | { create_file ( & storage,
66
+ //db_path 是generate_filename
67
+ let file = create_file ( & storage, db_path, Local :: now ( ) . timestamp ( ) ) . unwrap ( ) ;
68
+ let file_fn = move |path : String | { create_file ( & storage,
67
69
path. as_str ( ) , Local :: now ( ) . timestamp ( ) ) } ;
68
- let drain =FileBasedDrain :: new ( file, db_path. clone ( ) ,
70
+ let drain =FileBasedDrain :: new ( file, db_path,
69
71
file_fn)
70
- . add_rotator ( RotatedFileBySize :: new ( 0 ) ) ;
72
+ . add_rotator ( RotatedFileBySize :: new ( 1 ) ) ;
71
73
let drain = slog_async:: Async :: new ( drain) . build ( ) . fuse ( ) ;
72
74
slog:: Logger :: root ( drain, o ! ( ) )
73
75
}
@@ -131,46 +133,52 @@ fn log_to_slog_level(level: log::Level) -> Level {
131
133
struct FileBasedDrain < F : File > {
132
134
inner : Mutex < F > ,
133
135
rotators : Vec < Box < dyn Rotator > > ,
134
- dp_path : String ,
136
+ db_path : String ,
135
137
new_file : Box < dyn Send +Fn ( String ) ->Result < F > >
136
138
}
137
139
138
140
impl < F : File > FileBasedDrain < F > {
139
- fn new < H > ( f : F , path : String , new_file : H ) -> Self
141
+ fn new < H > ( f : F , path : & str , new_file : H ) -> Self
140
142
where H : ' static +Send +Fn ( String ) ->Result < F >
141
143
{
142
144
FileBasedDrain {
143
- dp_path : path. clone ( ) ,
145
+ db_path : path. to_string ( ) ,
144
146
inner : Mutex :: new ( f) ,
145
147
rotators : vec ! [ ] ,
146
148
new_file : Box :: new ( new_file)
147
149
}
148
150
}
149
151
152
+
150
153
fn add_rotator < R : ' static +Rotator > ( mut self , rotator : R ) -> Self {
151
154
if rotator. is_enabled ( ) {
152
155
self . rotators . push ( Box :: new ( rotator) ) ;
153
156
}
154
- for rotator in ( & self ) . rotators . iter ( ) {
157
+ for rotator in ( & self ) . rotators . iter ( ) {
155
158
rotator. prepare ( & * self . inner . lock ( ) . unwrap ( ) ) . unwrap ( ) ;
156
159
}
157
160
self
158
161
}
159
162
160
- fn flush ( & self ) ->Result < ( ) > {
161
- self . inner . lock ( ) . unwrap ( ) . flush ( ) ?;
162
- let new_file = ( self . new_file ) ( self . dp_path . clone ( ) ) . unwrap ( ) ;
163
-
164
- let mut old_file = self . inner . lock ( ) . unwrap ( ) ;
165
- std:: mem:: replace ( & mut * old_file, new_file) ;
163
+ fn flush ( & self ) -> Result < ( ) > {
164
+ // use crate::storage::file::FileStorage;
165
+ // let storage = FileStorage::default();
166
166
for rotator in self . rotators . iter ( ) {
167
- rotator. on_rotate ( ) ?;
168
- }
169
- return Ok ( ( ) ) ;
170
-
167
+ if rotator. should_rotate ( ) {
168
+ // let _ = storage.rename("log/000000.log","log/000000.log");
169
+ let new_file = ( self . new_file ) ( self . db_path . clone ( ) ) . unwrap ( ) ;
170
+ let mut old_file = self . inner . lock ( ) . unwrap ( ) ;
171
+ * old_file =new_file;
172
+
173
+ for rotator in self . rotators . iter ( ) {
174
+ rotator. on_rotate ( ) ;
175
+ }
176
+ return Ok ( ( ) ) ;
177
+ }
178
+ }
179
+ self . inner . lock ( ) . unwrap ( ) . flush ( )
171
180
}
172
181
}
173
-
174
182
impl < F : File > Drain for FileBasedDrain < F > {
175
183
type Ok = ( ) ;
176
184
type Err = slog:: Never ;
@@ -186,19 +194,17 @@ impl<F:File> Drain for FileBasedDrain<F> {
186
194
record. msg( ) ,
187
195
values
188
196
) ;
189
- for rotator in self . rotators . iter ( ) {
190
- if rotator. should_rotate ( ) {
191
- self . flush ( ) . unwrap ( ) ;
192
- return Ok ( ( ) ) ;
193
- }
194
- }
195
-
196
- for rotator in self . rotators . iter ( ) {
197
- rotator. on_write ( by. as_bytes ( ) ) . unwrap ( ) ;
197
+
198
+
199
+ for rotator in self . rotators . iter ( ) {
200
+ rotator. on_write ( by. as_bytes ( ) ) . unwrap ( ) ;
198
201
}
199
- // Ignore errors here
200
- let _ = self . inner . lock ( ) . unwrap ( ) . write ( by . as_bytes ( ) ) ;
202
+
203
+ let _f = self . flush ( ) . unwrap ( ) ;
201
204
205
+ //Ignore errors here
206
+ let _ = self . inner . lock ( ) . unwrap ( ) . write ( by. as_bytes ( ) ) ;
207
+
202
208
Ok ( ( ) )
203
209
}
204
210
}
@@ -218,7 +224,7 @@ trait Rotator: Send {
218
224
219
225
fn on_write ( & self , buf : & [ u8 ] ) -> Result < ( ) > ;
220
226
// Call by operator, update rotators' state while the operator execute a rotation.
221
- fn on_rotate ( & self ) -> Result < ( ) > ;
227
+ fn on_rotate ( & self ) ;
222
228
}
223
229
224
230
struct RotatedFileBySize {
@@ -253,9 +259,8 @@ impl Rotator for RotatedFileBySize {
253
259
Ok ( ( ) )
254
260
}
255
261
256
- fn on_rotate ( & self ) -> Result < ( ) > {
262
+ fn on_rotate ( & self ) {
257
263
* self . file_size . lock ( ) . unwrap ( ) = 0 ;
258
- Ok ( ( ) )
259
264
}
260
265
}
261
266
@@ -264,21 +269,51 @@ mod tests {
264
269
265
270
use super :: * ;
266
271
use crate :: storage:: mem:: MemStorage ;
267
-
272
+ use crate :: storage:: file:: FileStorage ;
273
+ use slog:: info;
274
+ use std:: fs;
268
275
use std:: thread;
269
276
use std:: time:: Duration ;
270
-
277
+ use std:: path:: Path ;
278
+
279
+ fn file_exists ( file : impl AsRef < Path > , storage : FileStorage ) -> bool {
280
+ storage. exists ( file)
281
+ }
282
+ // #[test]
283
+ // fn test_default_logger() {
284
+ // let s =MemStorage::default();
285
+ // // let s = &'static s;
286
+ // let db_path = "test";
287
+ // let logger = Logger::new(None, LevelFilter::Debug, s, db_path);
288
+ // // Ignore the error if the logger have been set
289
+ // let _ = log::set_logger(Box::leak(Box::new(logger)));
290
+ // log::set_max_level(LevelFilter::Debug);
291
+ // self::info!(,"Hello World");
292
+ // // Wait for the async logger print the result
293
+ // thread::sleep(Duration::from_millis(100));
294
+ // }
295
+
271
296
#[ test]
272
- fn test_default_logger ( ) {
273
- let s =MemStorage :: default ( ) ;
274
- // let s = &'static s;
275
- let db_path = "test" ;
276
- let logger = Logger :: new ( None , LevelFilter :: Debug , s, db_path. to_string ( ) ) ;
277
- // Ignore the error if the logger have been set
278
- let _ = log:: set_logger ( Box :: leak ( Box :: new ( logger) ) ) ;
279
- log:: set_max_level ( LevelFilter :: Debug ) ;
280
- info ! ( "Hello World" ) ;
281
- // Wait for the async logger print the result
282
- thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
297
+ fn test_rotate_by_size ( ) {
298
+ let db_path = "log" ;
299
+
300
+ let storage = FileStorage :: default ( ) ;
301
+ let _= storage. mkdir_all ( db_path) ;
302
+ let storage2 = storage. clone ( ) ;
303
+ let file= create_file ( & storage, db_path, 0 ) . unwrap ( ) ;
304
+ let new_path = generate_filename ( db_path, FileType :: Log , 1 ) ;
305
+
306
+
307
+
308
+ let file_fn = move |path : String | { create_file ( & storage,
309
+ path. as_str ( ) , 1 ) } ;
310
+
311
+ let drain =FileBasedDrain :: new ( file, db_path, file_fn)
312
+ . add_rotator ( RotatedFileBySize :: new ( 1 ) ) ;
313
+ let drain = slog_async:: Async :: new ( drain) . build ( ) . fuse ( ) ;
314
+ let _log = slog:: Logger :: root ( drain, o ! ( ) ) ;
315
+ self :: info!( _log, "Test log file rotated by size" ) ;
316
+
317
+ assert ! ( file_exists( new_path, FileStorage :: default ( ) ) ) ;
283
318
}
284
319
}
0 commit comments