Skip to content

Commit e76a743

Browse files
committed
complete rotate test
1 parent 97c77e3 commit e76a743

File tree

2 files changed

+105
-90
lines changed

2 files changed

+105
-90
lines changed

src/logger.rs

Lines changed: 102 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use crate::db::filename::{generate_filename, FileType};
1515
use crate::error::Result;
1616
use crate::storage::{File, Storage};
1717

18-
1918
use log::{LevelFilter, Log, Metadata, Record};
2019
use slog::{o, Drain, Level};
2120

@@ -26,12 +25,11 @@ use std::sync::Mutex;
2625
///
2726
/// See `slog` at https://github.com/slog-rs/slog
2827
/// See `log` at https://github.com/rust-lang/log
29-
///
28+
///
3029
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-
30+
pub fn create_file<S: Storage>(storage: &S, db_path: &str, timestamp: i64) -> Result<S::F> {
31+
let log_path = generate_filename(db_path, FileType::Log, timestamp as u64);
32+
storage.create(log_path)
3533
}
3634

3735
pub struct Logger {
@@ -46,10 +44,10 @@ impl Logger {
4644
/// If `inner` is `None`
4745
/// - In dev mode, use a std output
4846
/// - In release mode, use a storage specific file with name `LOG`
49-
pub fn new<S:Storage+Clone+'static>(
47+
pub fn new<S: Storage + Clone + 'static>(
5048
inner: Option<slog::Logger>,
5149
level: LevelFilter,
52-
storage:S,
50+
storage: S,
5351
db_path: &'static str,
5452
) -> Self {
5553
let inner = match inner {
@@ -62,14 +60,12 @@ impl Logger {
6260
slog::Logger::root(drain, o!())
6361
} else {
6462
// Use a file `Log` to record all logs
65-
// TODO: add file rotation
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,
69-
path.as_str(),Local::now().timestamp())};
70-
let drain =FileBasedDrain::new(file,db_path,
71-
file_fn)
72-
.add_rotator(RotatedFileBySize::new(1));
63+
let file = create_file(&storage, db_path, Local::now().timestamp()).unwrap();
64+
let file_fn = move |path: String| {
65+
create_file(&storage, path.as_str(), Local::now().timestamp())
66+
};
67+
let drain = FileBasedDrain::new(file, db_path, file_fn)
68+
.add_rotator(RotatedFileBySize::new(1));
7369
let drain = slog_async::Async::new(drain).build().fuse();
7470
slog::Logger::root(drain, o!())
7571
}
@@ -130,56 +126,56 @@ fn log_to_slog_level(level: log::Level) -> Level {
130126
}
131127
}
132128

133-
struct FileBasedDrain<F: File> {
129+
struct FileBasedDrain<F: File> {
134130
inner: Mutex<F>,
135131
rotators: Vec<Box<dyn Rotator>>,
136-
db_path:String,
137-
new_file:Box<dyn Send+Fn(String)->Result<F>>
132+
db_path: String,
133+
new_file: Box<dyn Send + Fn(String) -> Result<F>>,
138134
}
139135

140-
impl<F: File> FileBasedDrain<F> {
141-
fn new<H>(f:F,path:&str,new_file: H) -> Self
142-
where H:'static+Send+Fn(String)->Result<F>
143-
{
136+
impl<F: File> FileBasedDrain<F> {
137+
fn new<H>(f: F, path: &str, new_file: H) -> Self
138+
where
139+
H: 'static + Send + Fn(String) -> Result<F>,
140+
{
144141
FileBasedDrain {
145142
db_path: path.to_string(),
146143
inner: Mutex::new(f),
147144
rotators: vec![],
148-
new_file:Box::new(new_file)
145+
new_file: Box::new(new_file),
149146
}
150147
}
151148

152-
153-
fn add_rotator<R: 'static+Rotator>(mut self, rotator: R) -> Self {
149+
fn add_rotator<R: 'static + Rotator>(mut self, rotator: R) -> Self {
154150
if rotator.is_enabled() {
155151
self.rotators.push(Box::new(rotator));
156152
}
157-
for rotator in (&self).rotators.iter() {
153+
for rotator in self.rotators.iter() {
158154
rotator.prepare(&*self.inner.lock().unwrap()).unwrap();
159155
}
160156
self
161157
}
162158

163-
fn flush(&self) -> Result<()>{
164-
// use crate::storage::file::FileStorage;
165-
// let storage = FileStorage::default();
159+
fn flush(&self) -> Result<()> {
166160
for rotator in self.rotators.iter() {
167-
if rotator.should_rotate() {
168-
// let _ = storage.rename("log/000000.log","log/000000.log");
161+
if rotator.should_rotate() {
169162
let new_file = (self.new_file)(self.db_path.clone()).unwrap();
163+
170164
let mut old_file = self.inner.lock().unwrap();
171-
*old_file =new_file;
172-
165+
*old_file = new_file;
166+
173167
for rotator in self.rotators.iter() {
174168
rotator.on_rotate();
175169
}
170+
176171
return Ok(());
177-
}
178172
}
173+
}
174+
179175
self.inner.lock().unwrap().flush()
180176
}
181177
}
182-
impl<F:File> Drain for FileBasedDrain<F> {
178+
impl<F: File> Drain for FileBasedDrain<F> {
183179
type Ok = ();
184180
type Err = slog::Never;
185181

@@ -194,23 +190,20 @@ impl<F:File> Drain for FileBasedDrain<F> {
194190
record.msg(),
195191
values
196192
);
197-
198193

199-
for rotator in self.rotators.iter() {
200-
rotator.on_write(by.as_bytes()).unwrap();
194+
for rotator in self.rotators.iter() {
195+
rotator.on_write(by.as_bytes()).unwrap();
201196
}
202-
203-
let _f = self.flush().unwrap();
197+
198+
self.flush().unwrap();
204199

205200
//Ignore errors here
206201
let _ = self.inner.lock().unwrap().write(by.as_bytes());
207-
202+
208203
Ok(())
209204
}
210205
}
211206

212-
213-
214207
trait Rotator: Send {
215208
/// Check if the option is enabled in configuration.
216209
/// Return true if the `rotator` is valid.
@@ -224,7 +217,7 @@ trait Rotator: Send {
224217

225218
fn on_write(&self, buf: &[u8]) -> Result<()>;
226219
// Call by operator, update rotators' state while the operator execute a rotation.
227-
fn on_rotate(&self) ;
220+
fn on_rotate(&self);
228221
}
229222

230223
struct RotatedFileBySize {
@@ -245,10 +238,9 @@ impl Rotator for RotatedFileBySize {
245238
fn is_enabled(&self) -> bool {
246239
self.rotation_size != 0
247240
}
248-
fn prepare(&self, file: &dyn File) -> Result<()> {
241+
fn prepare(&self, file: &dyn File) -> Result<()> {
249242
*self.file_size.lock().unwrap() = file.len().unwrap();
250243
Ok(())
251-
252244
}
253245

254246
fn should_rotate(&self) -> bool {
@@ -259,7 +251,7 @@ impl Rotator for RotatedFileBySize {
259251
Ok(())
260252
}
261253

262-
fn on_rotate(&self) {
254+
fn on_rotate(&self) {
263255
*self.file_size.lock().unwrap() = 0;
264256
}
265257
}
@@ -268,52 +260,75 @@ impl Rotator for RotatedFileBySize {
268260
mod tests {
269261

270262
use super::*;
271-
use crate::storage::mem::MemStorage;
272263
use crate::storage::file::FileStorage;
273-
use slog::info;
274-
use std::fs;
275-
use std::thread;
276-
use std::time::Duration;
264+
use crate::storage::mem::MemStorage;
277265
use std::path::Path;
266+
use std::thread;
267+
use std::time::Duration;
278268

279-
fn file_exists(file: impl AsRef<Path>,storage:FileStorage) -> bool {
269+
fn file_exists(file: impl AsRef<Path>, storage: impl Storage) -> bool {
280270
storage.exists(file)
281271
}
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-
272+
296273
#[test]
297-
fn test_rotate_by_size() {
274+
fn test_default_logger() {
275+
let s = MemStorage::default();
276+
// let s = &'static s;
277+
let db_path = "test";
278+
let logger = Logger::new(None, LevelFilter::Debug, s, db_path);
279+
// Ignore the error if the logger have been set
280+
let _ = log::set_logger(Box::leak(Box::new(logger)));
281+
log::set_max_level(LevelFilter::Debug);
282+
log::info!("Hello World");
283+
// Wait for the async logger print the result
284+
thread::sleep(Duration::from_millis(100));
285+
}
286+
287+
#[test]
288+
fn test_rotate_by_size() {
298289
let db_path = "log";
299-
290+
300291
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()));
292+
293+
let _ = storage.mkdir_all(db_path);
294+
let file = create_file(&storage, db_path, 0).unwrap();
295+
let new_path = generate_filename(db_path, FileType::Log, 1);
296+
297+
{
298+
let file_fn = move |path: String| create_file(&storage, path.as_str(), 1);
299+
300+
let drain =
301+
FileBasedDrain::new(file, db_path, file_fn).add_rotator(RotatedFileBySize::new(1));
302+
let drain = slog_async::Async::new(drain).build().fuse();
303+
let _log = slog::Logger::root(drain, o!());
304+
slog::info!(_log, "Test log file rotated by size");
305+
}
306+
assert_eq!(true, file_exists(new_path, FileStorage::default()));
307+
}
308+
309+
#[test]
310+
fn test_not_rotate_by_size() {
311+
let db_path = "norotate";
312+
313+
let storage = FileStorage::default();
314+
315+
let _ = storage.mkdir_all(db_path);
316+
let file = create_file(&storage, db_path, 0).unwrap();
317+
let new_path = generate_filename(db_path, FileType::Log, 1);
318+
319+
{
320+
let file_fn = move |path: String| create_file(&storage, path.as_str(), 1);
321+
322+
let drain = FileBasedDrain::new(file, db_path, file_fn)
323+
.add_rotator(RotatedFileBySize::new(100));
324+
let drain = slog_async::Async::new(drain).build().fuse();
325+
let _log = slog::Logger::root(drain, o!());
326+
slog::info!(_log, "Test log file rotated by size");
327+
}
328+
assert_eq!(
329+
true,
330+
file_exists("norotate/000000.log", FileStorage::default())
331+
);
332+
assert_eq!(false, file_exists(new_path, FileStorage::default()));
318333
}
319334
}

src/options.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,10 @@ impl Options {
205205
}
206206

207207
/// Initialize Options by limiting ranges of some flags, applying customized Logger and etc.
208-
pub(crate) fn initialize<O: File + 'static, S:Storage<F = O>+Clone+'static>(
208+
pub(crate) fn initialize<O: File + 'static, S: Storage<F = O> + Clone + 'static>(
209209
&mut self,
210210
db_name: &'static str,
211-
storage: &S,
211+
storage: &S,
212212
) {
213213
self.max_open_files =
214214
Self::clip_range(self.max_open_files, 64 + self.non_table_cache_files, 50000);
@@ -225,7 +225,7 @@ impl Options {
225225
}
226226

227227
#[allow(unused_must_use)]
228-
fn apply_logger<S: 'static+Storage+Clone>(&mut self, storage: &S, db_path: &'static str) {
228+
fn apply_logger<S: 'static + Storage + Clone>(&mut self, storage: &S, db_path: &'static str) {
229229
let user_logger = std::mem::replace(&mut self.logger, None);
230230
let logger = Logger::new(user_logger, self.logger_level, storage.clone(), db_path);
231231
let static_logger: &'static dyn Log = Box::leak(Box::new(logger));

0 commit comments

Comments
 (0)