inconshreveable / log15

Structured, composable logging for Go
https://godoc.org/github.com/inconshreveable/log15
Other
1.1k stars 145 forks source link

No way to close files opened when a new FileHandler is created. #156

Open jamesjmurtagh opened 5 years ago

jamesjmurtagh commented 5 years ago

A project that I'm working on spawns a Logger with a new FileHandler each time a particular action is performed. When attempting to os.Remove() a file that was generated by a log15.FileHandler on Windows 10, an error returned due to the fact that the file was still in use by a process. This error occurs because, as far as I can tell, there are no ways to close a log15.FileHandler, so my own code never releases/closes the file.

Here's how I resolved this issue, although you might have different opinions about how best to implement a way to close FileHandlers.

I exported the closingHandler struct (rename to ClosingHandler). In my own code, I get the handler of the logger I no longer wish to use, with (*log15.Logger).GetHandler(), and perform a type assertion:

func CloseLogger(l log15.Logger) error {
        x, ok := l.GetHandler().(log15.ClosingHandler)
        if ok {
                err := x.Close()
                if err != nil {
                        return err
                }
        }
        return nil
}

Note that this will not work if the FileHandler has been wrapped in another handler, such as MultiHandler. Ideally, a MultiHandler would loop through each handler that it contains and attempt to perform a type assertion as detailed in the code fragment above, closing where possible.

I don't know the full ramifications of performing a close like this. In my situation, I never use a logger after performing this step, so I don't imagine I'll notice anything that occurs as a result.