user3002512
user3002512

Reputation: 399

Implement a log file appender in Golang

I have a Golang application which uses the go-logging library (https://github.com/op/go-logging). A log file is correctly generated but when I stop and relaunch the Go application then this logfile is overwrited by a new log file. It is not a bug, Golang does what it asked to do. But if possible I would like that the new logs be appended in the existent log file.

First, an excerpt of my main.go :

package main

import (

"utils"
"webapp"
"odbc"
"constants"
"github.com/op/go-logging"
)

var config = &Configuration{}

var log = logging.MustGetLogger("main")

func main() {

     // Load the configuration file
    utils.Load(constants.CONFIG_PATH, config)

    utils.InitLog(config.LOG)

    ...
    }

My appUtils.go where the utilitary functions are defined :

package utils

import (
"github.com/op/go-logging"
"os"
"fmt"
 )

 func InitLog(config LOG) {

 f, err := os.Create(config.LogFile)

 backend := logging.NewLogBackend(f, "", 0)

 format := logging.MustStringFormatter(config.FORMAT,)

backendFormatter := logging.NewBackendFormatter(backend, format)

// Only errors and more severe messages should be sent to backend1 logging.Level
logging.SetBackend(backendFormatter)


  level, err :=  logging.LogLevel(config.LEVEL)
  if err != nil {
     logging.SetLevel(logging.ERROR, "")
  } else{
    logging.SetLevel( level, "")
   }
 }

type LOG struct {
  FORMAT    string
  LEVEL    string
  LogFile  string
}

If needed I also put the content of my config.json :

{
  "LOG":{
      "LEVEL": "DEBUG",
      "FORMAT": "%{color}%{time:15:04:05.000} %{shortfunc} => %{level:.4s} %{id:03x}%{color:reset} %{message}",
      "LogFile": "logfile.log"
      }
 }

Is what I want feasible? I have understood that the problem comes from this line :

 f, err := os.Create(config.LogFile)

A new file is created after a (re)launch of the application. To avoid that I tried this :

  var f *os.File
  if _, err := os.Stat(config.LogFile); os.IsNotExist(err) {
      f, err := os.Create(config.LogFile)
  }
  else {
     f, err := os.OpenFile(config.LogFile, os.O_APPEND|os.O_WRONLY,   0600)    
  }

but it's quite bullsh*t, it does not work at all.

If it's not feasible, should I modify my config.json in order to generate files that have in their name the date with the milliseconds, for instance?

Upvotes: 3

Views: 1184

Answers (1)

Mr_Pink
Mr_Pink

Reputation: 109405

Your version doesn't work because you're shadowing the f variable in the if blocks. If you declared err first and use a simple assignment, this would appear to work in most cases.

However, stat'ing a file then trying to create or open it is inherently racy. Just open it with the correct flags in one try. If you want "write only", "append", and "create", then:

os.OpenFile(name, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600)

Upvotes: 3

Related Questions