diff --git a/FUTURE.md b/FUTURE.md index 05379f2..4d8385d 100644 --- a/FUTURE.md +++ b/FUTURE.md @@ -1,5 +1,13 @@ ## ✒ 未来版本的新特性 (Features in future version) +### v0.2.5 +* 修复配置文件中出现转义字符导致解析出错的问题 + +### v0.2.4 +* 新增屏蔽某个日志级别的日志处理器 +* 修正某些文档的语法问题 +* 修复部分单元测试引用外部文件(比如 _examples 中的文件)的问题 + ### v0.2.3 * 祝大家五一劳动节快乐! * ~~增加 timeout_handler.go,里面是带超时功能的日志处理器包装器~~ diff --git a/HISTORY.md b/HISTORY.md index 0aae6bb..01b3bbf 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,11 @@ ## ✒ 历史版本的特性介绍 (Features in old version) +### v0.2.4 +> 此版本发布于 2020-05-27 +* 新增屏蔽某个日志级别的日志处理器 +* 修正某些文档的语法问题 +* 修复部分单元测试引用外部文件(比如 _examples 中的文件)的问题 + ### v0.2.3 > 此版本发布于 2020-05-01 * 祝大家五一劳动节快乐! diff --git a/README.en.md b/README.en.md index ad28602..4910db7 100644 --- a/README.en.md +++ b/README.en.md @@ -24,7 +24,7 @@ _Check [HISTORY.md](./HISTORY.md) and [FUTURE.md](./FUTURE.md) to know about more information._ -> v0.1.x is an interim version and will not be updated but fixed from now on. Next version v0.2.x is a big update which will bring new features and user experience, also it will be updated and maintained for a long time! +> v0.1.x and older versions will not be supported anymore, please update to v0.2.x as quickly as possible. You will get some brand-new user experiences and supports for a long time! ### 🚀 Installation @@ -44,7 +44,7 @@ module your_project_name go 1.14 require ( - github.com/FishGoddess/logit v0.2.3 + github.com/FishGoddess/logit v0.2.4 ) ``` diff --git a/README.md b/README.md index 2a772e4..b021125 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ _历史版本的特性请查看 [HISTORY.md](./HISTORY.md)。未来版本的新特性和计划请查看 [FUTURE.md](./FUTURE.md)。_ -> v0.1.x 版本只是一个特性过渡版本,目前已经停止更新,只进行维护和修复。下一个大更新版本 v0.2.x 将带来全新的特性和使用体验(其中一点就是做减法),并保持长期更新和维护! +> v0.1.x 及以下版本已经停止维护,请尽快升级到 v0.2.x 版本!您将感受到全新的使用体验,并可以享受长期的更新和维护! ### 🚀 安装方式 @@ -45,7 +45,7 @@ module your_project_name go 1.14 require ( - github.com/FishGoddess/logit v0.2.3 + github.com/FishGoddess/logit v0.2.4 ) ``` diff --git a/_examples/config/logit-config-template.conf b/_examples/config/logit-config-template.conf index b0584e5..4a58998 100644 --- a/_examples/config/logit-config-template.conf +++ b/_examples/config/logit-config-template.conf @@ -1,6 +1,7 @@ -# logit 配置文件的模板 v0.2.1-alpha +# logit 配置文件的模板 v0.2.4 # 注意:以 # 开头的是注释,不参与配置文件的解析,注释必须是单独的一行,不能写在属性的后面 # 语法是基于 Json 并作了一些改动使其更适合做配置文件,所以要注意双引号和逗号这些格式 +# 下面所有涉及目录路径的都使用 / 或者 \\ 而不能是 \,否则会造成配置解析出错,这个问题后续会进行修复 # 日志级别,可取值有 debug,info,warn,error,off # 如果不配置的话,默认是 debug @@ -130,5 +131,35 @@ "file": { "path": "D:/error.log" } + }, + + # level shielded 日志处理器 + # 这个日志处理器一共有四个:!debug,!info,!warn,!error + # 它们只是一个包装器,做了一个日志级别的过滤,比如 !debug 的日志处理器就只会处理 debug 级别之外的日志 + # 每个日志处理器内部可以添加多个日志处理器,比如 console 日志处理器,甚至是再添加一个 level shielded 日志处理器 + # 所以日志怎么处理还是要靠具体添加的日志处理器,您可以添加所有注册进 logit 或者说上面出现的日志处理器 + "!debug": { + "console": {}, + "file": { + "path": "D:/non-debug.log" + } + }, + "!info": { + "console": {}, + "file": { + "path": "D:/non-info.log" + } + }, + "!warn": { + "console": {}, + "file": { + "path": "D:/non-warn.log" + } + }, + "!error": { + "console": {}, + "file": { + "path": "D:/non-error.log" + } } } \ No newline at end of file diff --git a/_examples/config/logit-config-template.en.conf b/_examples/config/logit-config-template.en.conf index 6a7579b..250e377 100644 --- a/_examples/config/logit-config-template.en.conf +++ b/_examples/config/logit-config-template.en.conf @@ -1,6 +1,7 @@ -# logit config template v0.2.1-alpha +# logit config template v0.2.4 # Notice that starting with # is comment, and it must be a new line # Grammar is based on Json, but adds more features to let it become more configured and easy-to-read +# You should always use / or \\ instead of \. This problem will be fixed in future version # Logger level, all valid values are debug, info, warn, error, off # Default is "debug" @@ -136,5 +137,36 @@ "file": { "path": "D:/error.log" } + }, + + # level shielded handlers + # There are four kinds of this handlers: !debug, !info, !warn, !error + # They are only a wrapper which only does a log level filtering + # For example, the !debug level shielded handler only handles logs in all levels except debug level + # Every level shielded handler can have many handlers, such as console handler, even one more level shielded handler + # So how to handle logs is dependent to specifically added handlers, and you can add all registered handlers above + "!debug": { + "console": {}, + "file": { + "path": "D:/non-debug.log" + } + }, + "!info": { + "console": {}, + "file": { + "path": "D:/non-info.log" + } + }, + "!warn": { + "console": {}, + "file": { + "path": "D:/non-warn.log" + } + }, + "!error": { + "console": {}, + "file": { + "path": "D:/non-error.log" + } } } \ No newline at end of file diff --git a/_examples/level_based_handler.conf b/_examples/level_based_handler.conf deleted file mode 100644 index 5ff13ca..0000000 --- a/_examples/level_based_handler.conf +++ /dev/null @@ -1,25 +0,0 @@ -"handlers": { - "debug": { - "file": { - "path": "Z:/debug.log" - } - }, - "info": { - "file": { - "path": "Z:/info.log" - } - }, - "warn": { - "file": { - "path": "Z:/warn.log" - } - }, - "error": { - "file": { - "path": "Z:/error.log" - } - }, - "console": { - "encoder": "json" - } -} \ No newline at end of file diff --git a/_examples/writer.go b/_examples/writer.go index b017a16..e1feb91 100644 --- a/_examples/writer.go +++ b/_examples/writer.go @@ -32,8 +32,8 @@ func main() { }) defer durationRollingFile.Close() - // You can use it like using os.File! - durationRollingFile.Write([]byte("Hello!")) + // You can use it like using io.Writer! + durationRollingFile.Write([]byte("durationRollingFile!")) // ================================================================================= @@ -43,6 +43,6 @@ func main() { }) defer sizeRollingFile.Close() - // You can use it like using os.File! - sizeRollingFile.Write([]byte("Hello!")) + // You can use it like using io.Writer! + sizeRollingFile.Write([]byte("sizeRollingFile!")) } diff --git a/config_test.go b/config_test.go index 916faed..59ab0b2 100644 --- a/config_test.go +++ b/config_test.go @@ -19,15 +19,46 @@ package logit import ( + "io/ioutil" "os" + "path/filepath" "testing" ) +// 创建 TestParseConfigFile 测试案例的配置文件 +func createParseConfigFileTestConfigFile(t *testing.T) string { + + // 创建配置文件 + configFile, err := ioutil.TempFile("", "TestParseConfigFile_*.conf") + if err != nil { + t.Fatal(err) + } + defer configFile.Close() + + // 写入配置内容 + configFile.WriteString(` + "level": "debug", + + "caller": false, + + "handlers": { + "console": { + "timeFormat": "unix", + "encoder": "json" + }, + "file": { + "path": "` + escapeString(filepath.Join(os.TempDir(), "logit.log")) + `" + } + } + `) + return configFile.Name() +} + // 测试解析配置文件的方法 func TestParseConfigFile(t *testing.T) { // 打开配置文件 - file, err := os.Open("./_examples/logger.conf") + file, err := os.Open(createParseConfigFileTestConfigFile(t)) if err != nil { t.Fatal(err) } @@ -54,7 +85,7 @@ func TestParseHandlersFromConfig(t *testing.T) { "k1": "v1", }, "file": { - "path": "Z:/TestParseHandlersFromConfig.log", + "path": escapeString(filepath.Join(os.TempDir(), "TestParseHandlersFromConfig.log")), "k2": "v2", }, }, diff --git a/doc.go b/doc.go index f1d1698..314738a 100644 --- a/doc.go +++ b/doc.go @@ -201,5 +201,5 @@ package logit // import "github.com/FishGoddess/logit" const ( // Version is the version string representation of logit. - Version = "v0.2.3" + Version = "v0.2.4" ) diff --git a/handler_extension_test.go b/handler_extension_test.go index c9447c5..9954671 100644 --- a/handler_extension_test.go +++ b/handler_extension_test.go @@ -19,6 +19,8 @@ package logit import ( + "os" + "path/filepath" "strconv" "testing" "time" @@ -36,7 +38,7 @@ func TestNewFileHandler(t *testing.T) { } }() - logger := NewLogger(DebugLevel, NewFileHandler("Z:/test.log", TextEncoder(), "")) + logger := NewLogger(DebugLevel, NewFileHandler(filepath.Join(os.TempDir(), "test.log"), TextEncoder(), "")) for i := 0; i < 100; i++ { logger.Info("我是第 " + strconv.Itoa(i) + " 条日志!") } @@ -46,7 +48,7 @@ func TestNewFileHandler(t *testing.T) { // 测试创建随时间间隔滚动的文件日志处理器 func TestNewDurationRollingHandler(t *testing.T) { - logger := NewLogger(DebugLevel, NewDurationRollingHandler(time.Second, "Z:/", TextEncoder(), "")) + logger := NewLogger(DebugLevel, NewDurationRollingHandler(time.Second, os.TempDir(), TextEncoder(), "")) for i := 0; i < 5; i++ { logger.Info("1. info!!!!!!!! " + strconv.FormatInt(time.Now().Unix(), 10)) time.Sleep(time.Second) @@ -56,7 +58,7 @@ func TestNewDurationRollingHandler(t *testing.T) { // 测试按照文件大小自动划分日志文件的日志处理器 func TestNewSizeRollingHandler(t *testing.T) { - logger := NewLogger(DebugLevel, NewSizeRollingHandler(64*writer.KB, "Z:/", TextEncoder(), "")) + logger := NewLogger(DebugLevel, NewSizeRollingHandler(64*writer.KB, os.TempDir(), TextEncoder(), "")) for i := 0; i < 2000; i++ { logger.Debug("debug...") logger.Info("info...") diff --git a/level_based_handler.go b/level_based_handler.go index 101261e..aa7b449 100644 --- a/level_based_handler.go +++ b/level_based_handler.go @@ -52,7 +52,7 @@ func NewLevelBasedHandler(level Level, handlers ...Handler) Handler { } // Handle handles a log with handlers in lbh. -// Notice that the handle process will be interrupted if one of them +// Notice that the handling process will be interrupted if one of them // returned false. However, this method will always return true, so the handlers // after it will always be used. func (lbh *levelBasedHandler) Handle(log *Log) bool { @@ -101,7 +101,7 @@ func registerDebugLevelHandler() { }) } -// ================================ info level handler ================================ +// ================================ info level handler ================================ // registerInfoLevelHandler registers info level handler which // only handles logs in info level. @@ -127,7 +127,7 @@ func registerInfoLevelHandler() { }) } -// ================================ warn level handler ================================ +// ================================ warn level handler ================================ // registerWarnLevelHandler registers warn level handler which // only handles logs in warn level. diff --git a/level_based_handler_test.go b/level_based_handler_test.go index d38bc08..3ae8bdc 100644 --- a/level_based_handler_test.go +++ b/level_based_handler_test.go @@ -18,11 +18,57 @@ package logit -import "testing" +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +// 创建 LevelBasedHandler 测试案例的配置文件 +func createLevelBasedHandlerTestConfigFile(t *testing.T) string { + + // 创建配置文件 + configFile, err := ioutil.TempFile("", "createLevelBasedHandlerTestConfigFile_*.conf") + if err != nil { + t.Fatal(err) + } + defer configFile.Close() + + // 写入配置内容 + configFile.WriteString(` + "handlers": { + "debug": { + "file": { + "path": "` + escapeString(filepath.Join(os.TempDir(), "debug.log")) + `" + } + }, + "info": { + "file": { + "path": "` + escapeString(filepath.Join(os.TempDir(), "info.log")) + `" + } + }, + "warn": { + "file": { + "path": "` + escapeString(filepath.Join(os.TempDir(), "warn.log")) + `" + } + }, + "error": { + "file": { + "path": "` + escapeString(filepath.Join(os.TempDir(), "error.log")) + `" + } + }, + "console": { + "encoder": "json" + } + } + `) + return configFile.Name() +} // 测试基于 debug 日志级别的日志处理器 func TestDebugLevelHandler(t *testing.T) { - logger := NewLoggerFromPath("./_examples/level_based_handler.conf") + logger := NewLoggerFromPath(createLevelBasedHandlerTestConfigFile(t)) logger.Debug("debug 去哪了?") logger.Info("info 有一条?") logger.Warn("warn 有一条?") @@ -31,7 +77,7 @@ func TestDebugLevelHandler(t *testing.T) { // 测试基于 info 日志级别的日志处理器 func TestInfoLevelHandler(t *testing.T) { - logger := NewLoggerFromPath("./_examples/level_based_handler.conf") + logger := NewLoggerFromPath(createLevelBasedHandlerTestConfigFile(t)) logger.Debug("debug 有一条?") logger.Info("info 去哪了?") logger.Warn("warn 有一条?") @@ -40,7 +86,7 @@ func TestInfoLevelHandler(t *testing.T) { // 测试基于 warn 日志级别的日志处理器 func TestWarnLevelHandler(t *testing.T) { - logger := NewLoggerFromPath("./_examples/level_based_handler.conf") + logger := NewLoggerFromPath(createLevelBasedHandlerTestConfigFile(t)) logger.Debug("debug 有一条?") logger.Info("info 有一条?") logger.Warn("warn 去哪了?") @@ -49,7 +95,7 @@ func TestWarnLevelHandler(t *testing.T) { // 测试基于 debug 日志级别的日志处理器 func TestErrorLevelHandler(t *testing.T) { - logger := NewLoggerFromPath("./_examples/level_based_handler.conf") + logger := NewLoggerFromPath(createLevelBasedHandlerTestConfigFile(t)) logger.Debug("debug 有一条?") logger.Info("info 有一条?") logger.Warn("warn 有一条?") diff --git a/level_shielded_handler.go b/level_shielded_handler.go new file mode 100644 index 0000000..1f59e8f --- /dev/null +++ b/level_shielded_handler.go @@ -0,0 +1,170 @@ +// Copyright 2020 Ye Zi Jie. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: FishGoddess +// Email: fishinlove@163.com +// Created at 2020/05/27 20:50:41 + +package logit + +func init() { + registerNonDebugLevelHandler() + registerNonInfoLevelHandler() + registerNonWarnLevelHandler() + registerNonErrorLevelHandler() +} + +// levelShieldedHandler is a level shielded handler. +// It will shield the specific level and handles logs in other levels, for example, you want debug/info/warn +// level logs are written to log file "xxx.log" and error level logs are written to log file "xxx.error.log", +// then you can use this handler to do it. +type levelShieldedHandler struct { + + // level is the level of log that shielded by this handler. + // See logit.Level. + level Level + + // handlers is all handlers used to handle logs in level. + // See logit.Handler. + handlers []Handler +} + +// NewLevelShieldedHandler returns a handler handled logs in all levels except level. +// You can add more than one handler to this handler. This handler is just like a +// wrapper wrapping some handlers. +func NewLevelShieldedHandler(level Level, handlers ...Handler) Handler { + return &levelShieldedHandler{ + level: level, + handlers: handlers, + } +} + +// Handle handles a log with handlers in lsh. +// Notice that the handling process will be interrupted if one of them +// returned false. However, this method will always return true, so the handlers +// after it will always be used. +func (lsh *levelShieldedHandler) Handle(log *Log) bool { + if log.Level() != lsh.level { + for _, handler := range lsh.handlers { + if !handler.Handle(log) { + break + } + } + } + return true +} + +// ================================ non-debug level handler ================================ + +// registerNonDebugLevelHandler registers non-debug level handler which +// handles logs in all levels except debug level. +// +// For config: +// If you want to use this handler in your logger by config file, try this: +// +// "handlers": { +// "!debug": { +// "console": {} +// } +// } +// +// You should always know that this handler is a wrapper, so you must add some other +// handlers to it otherwise it will do nothing. All registered handlers can be added +// to it, even one more non-debug level handler. Now, you know it is only a filter that filters +// debug level logs. As for what params should be written in handlers inside are dependent +// to different handlers. Check other handlers' documents to know more about information. +// See logit.Handler. +func registerNonDebugLevelHandler() { + RegisterHandler("!debug", func(params map[string]interface{}) Handler { + return NewLevelShieldedHandler(DebugLevel, handlersOf(params)...) + }) +} + +// ================================ non-info level handler ================================ + +// registerNonInfoLevelHandler registers non-info level handler which +// handles logs in all levels except info level. +// +// For config: +// If you want to use this handler in your logger by config file, try this: +// +// "handlers": { +// "!info": { +// "console": {} +// } +// } +// +// You should always know that this handler is a wrapper, so you must add some other +// handlers to it otherwise it will do nothing. All registered handlers can be added +// to it, even one more non-info level handler. Now, you know it is only a filter that filters +// info level logs. As for what params should be written in handlers inside are dependent +// to different handlers. Check other handlers' documents to know more about information. +// See logit.Handler. +func registerNonInfoLevelHandler() { + RegisterHandler("!info", func(params map[string]interface{}) Handler { + return NewLevelShieldedHandler(InfoLevel, handlersOf(params)...) + }) +} + +// ================================ non-warn level handler ================================ + +// registerNonWarnLevelHandler registers non-warn level handler which +// handles logs in all levels except warn level. +// +// For config: +// If you want to use this handler in your logger by config file, try this: +// +// "handlers": { +// "!warn": { +// "console": {} +// } +// } +// +// You should always know that this handler is a wrapper, so you must add some other +// handlers to it otherwise it will do nothing. All registered handlers can be added +// to it, even one more non-warn level handler. Now, you know it is only a filter that filters +// warn level logs. As for what params should be written in handlers inside are dependent +// to different handlers. Check other handlers' documents to know more about information. +// See logit.Handler. +func registerNonWarnLevelHandler() { + RegisterHandler("!warn", func(params map[string]interface{}) Handler { + return NewLevelShieldedHandler(WarnLevel, handlersOf(params)...) + }) +} + +// ================================ non-error level handler ================================ + +// registerNonErrorLevelHandler registers non-error level handler which +// handles logs in all levels except error level. +// +// For config: +// If you want to use this handler in your logger by config file, try this: +// +// "handlers": { +// "!error": { +// "console": {} +// } +// } +// +// You should always know that this handler is a wrapper, so you must add some other +// handlers to it otherwise it will do nothing. All registered handlers can be added +// to it, even one more non-error level handler. Now, you know it is only a filter that filters +// error level logs. As for what params should be written in handlers inside are dependent +// to different handlers. Check other handlers' documents to know more about information. +// See logit.Handler. +func registerNonErrorLevelHandler() { + RegisterHandler("!error", func(params map[string]interface{}) Handler { + return NewLevelShieldedHandler(ErrorLevel, handlersOf(params)...) + }) +} diff --git a/level_shielded_handler_test.go b/level_shielded_handler_test.go new file mode 100644 index 0000000..2a24bb9 --- /dev/null +++ b/level_shielded_handler_test.go @@ -0,0 +1,76 @@ +// Copyright 2020 Ye Zi Jie. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: FishGoddess +// Email: fishinlove@163.com +// Created at 2020/05/27 21:10:13 + +package logit + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +// 创建 TestLevelShieldedHandler 测试案例的配置文件 +func createLevelShieldedHandlerTestConfigFile(t *testing.T) string { + + // 创建配置文件 + configFile, err := ioutil.TempFile("", "createLevelShieldedHandlerTestConfigFile_*.conf") + if err != nil { + t.Fatal(err) + } + defer configFile.Close() + + // 写入配置内容 + configFile.WriteString(` + "handlers": { + "!debug": { + "file": { + "path": "` + escapeString(filepath.Join(os.TempDir(), "non-debug.log")) + `" + } + }, + "!info": { + "file": { + "path": "` + escapeString(filepath.Join(os.TempDir(), "non-info.log")) + `" + } + }, + "!warn": { + "file": { + "path": "` + escapeString(filepath.Join(os.TempDir(), "non-warn.log")) + `" + } + }, + "!error": { + "file": { + "path": "` + escapeString(filepath.Join(os.TempDir(), "non-error.log")) + `" + } + }, + "console": { + "encoder": "json" + } + } + `) + return configFile.Name() +} + +// 测试屏蔽日志级别的日志处理器 +func TestLevelShieldedHandler(t *testing.T) { + logger := NewLoggerFromPath(createLevelShieldedHandlerTestConfigFile(t)) + logger.Debug("debug 有几条?") + logger.Info("info 有几条?") + logger.Warn("warn 有几条?") + logger.Error("error 有几条?") +} diff --git a/logger_test.go b/logger_test.go index 3abf5ee..bb9d1ab 100644 --- a/logger_test.go +++ b/logger_test.go @@ -20,8 +20,10 @@ package logit import ( "fmt" + "io/ioutil" "math/rand" "os" + "path/filepath" "strconv" "strings" "sync" @@ -176,9 +178,38 @@ func TestLoggerInConcurrency(t *testing.T) { group.Wait() } +// 创建 TestNewLoggerFromPath 测试案例的配置文件 +func createNewLoggerFromPathTestConfigFile(t *testing.T) string { + + // 创建配置文件 + configFile, err := ioutil.TempFile("", "TestNewLoggerFromPath_*.conf") + if err != nil { + t.Fatal(err) + } + defer configFile.Close() + + // 写入配置内容 + configFile.WriteString(` + "level": "debug", + + "caller": false, + + "handlers": { + "console": { + "timeFormat": "unix", + "encoder": "json" + }, + "file": { + "path": "` + escapeString(filepath.Join(os.TempDir(), "logit.log")) + `" + } + } + `) + return configFile.Name() +} + // 测试从配置文件中创建一个 logger func TestNewLoggerFromPath(t *testing.T) { - logger := NewLoggerFromPath("./_examples/logger.conf") + logger := NewLoggerFromPath(createNewLoggerFromPathTestConfigFile(t)) logger.Info("Does it work? 这是测试日志信息,实际的日志信息可能比这个长,也可能比这个短!") } diff --git a/writer/duration_rolling_file_test.go b/writer/duration_rolling_file_test.go index 4ca35a6..8d9ee1d 100644 --- a/writer/duration_rolling_file_test.go +++ b/writer/duration_rolling_file_test.go @@ -20,6 +20,7 @@ package writer import ( "os" + "path/filepath" "testing" "time" ) @@ -33,13 +34,11 @@ func TestNewDurationRollingFile(t *testing.T) { } }() - root := "Z:/TestNewDurationRollingFile/" + root := filepath.Join(os.TempDir(), "TestNewDurationRollingFile") os.RemoveAll(root) // 先删除现有文件夹 os.Mkdir(root, 0666) // 再创建测试文件夹 - file := NewDurationRollingFile(time.Second, func(now time.Time) string { - return root + now.Format("20060102150405.000") + ".log" - }) + file := NewDurationRollingFile(time.Second, NextFilename(root)) defer file.Close() for i := 0; i < 5; i++ { @@ -62,6 +61,7 @@ func TestNewDurationRollingFile(t *testing.T) { t.Fatal("文件滚动出现问题!") } + file.Close() file = NewDurationRollingFile(999*time.Millisecond, func(now time.Time) string { return "" }) diff --git a/writer/size_rolling_file_test.go b/writer/size_rolling_file_test.go index c91827a..25cdd80 100644 --- a/writer/size_rolling_file_test.go +++ b/writer/size_rolling_file_test.go @@ -19,6 +19,8 @@ package writer import ( + "os" + "path/filepath" "testing" "time" ) @@ -26,13 +28,41 @@ import ( // 测试创建根据文件大小滚动的文件类型 func TestNewSizeRollingFile(t *testing.T) { - file := NewSizeRollingFile(64*KB, func(now time.Time) string { - return "Z:/" + now.Format("20060102150405.000") + ".log" - }) + defer func() { + if err := recover(); err == nil { + t.Errorf("文件大小限制测试出现问题!") + } + }() + + root := filepath.Join(os.TempDir(), "TestNewSizeRollingFile") + os.RemoveAll(root) // 先删除现有文件夹 + os.Mkdir(root, 0666) // 再创建测试文件夹 + + file := NewSizeRollingFile(64*KB, NextFilename(root)) defer file.Close() b := make([]byte, 1024) for i := 0; i < 1024; i++ { file.Write(b) } + + dir, err := os.Open(root) + if err != nil { + t.Fatal("获取测试文件夹失败!") + } + + fileInfos, err := dir.Readdir(0) + if err != nil { + t.Fatal("获取测试文件夹信息失败!") + } + + // 如果创建的文件数不符合,直接报错 + if len(fileInfos) != 16 { + t.Fatal("文件滚动出现问题!") + } + + file.Close() + file = NewSizeRollingFile(0, func(now time.Time) string { + return "" + }) } diff --git a/writer/writer.go b/writer/writer.go index 3f700a3..aa178a9 100644 --- a/writer/writer.go +++ b/writer/writer.go @@ -21,7 +21,7 @@ package writer import ( "math/rand" "os" - "path" + "path/filepath" "strconv" "time" ) @@ -48,7 +48,7 @@ func NextFilename(directory string) func(now time.Time) string { rand.Seed(time.Now().UnixNano()) return func(now time.Time) string { name := now.Format("20060102-150405") + "-" + strconv.Itoa(rand.Intn(1000)) + SuffixOfLogFile - return path.Join(directory, name) + return filepath.Join(directory, name) } }