Go: Write Log to a File

Go: Write Log to a File

If you run your application on a server, you need to write your application log to a file. It will help you debug and analyze your application. A good log file will tell you what the error is, when it happened, and where it is come from. This article will show you how to write logs to a file in Go.

Why write logs to a file?

The log is how an application tells its story to the engineer. It keeps track of the events that happened to the application. As an engineer, you need to monitor your application log, especially the error log. An application that runs in the production or even staging environment needs to write the logs to a file. It is to make it easier to find the log and see the logs that are only important to you. It can help you determine whether the error is critical or not. A good log also helps you find the root cause of the error faster.

How to write the log to a file

To write the logs to a file in Go, we need to open a file first and then set the log output to the file. Let’s see the example code below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
    "log"
    "os"
)

func main() {
    file, err := openLogFile("./mylog.log")
    if err != nil {
        log.Fatal(err)
    }
    log.SetOutput(file)
    log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds)

    log.Println("log file created")
}

func openLogFile(path string) (*os.File, error) {
    logFile, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
    if err != nil {
        return nil, err
    }
    return logFile, nil
}
On line 9, we call the function openLogFile which is written on line 19. The function is to open a file in the OS at the given file location path. We do this by calling the function os.OpenFile. The function needs parameters that are file location, flags, and file permission.
The flags that we use are:

  • os.O_WRONLY: open the file write-only
  • os.O_APPEND: append data to the file when writing.
  • os.O_CREATE: create a new file if none exists.

And the file is given permission 644 when created. If you want to read more about file permission, you can read here.

On line 13, we set the log output to the that we have opened.

On line 14, we set flags to the logs, so that it shows the date and time, and the line of code that writes the log.

Below is a sample of the log produced.

2021/10/10 02:38:37.129447 main.go:16: log file created

There we can see main.go:16 is the code that calls log.Println. It is only written the filename because we used flag log.Lshortfile. If you need the complete path of the code, you can use log.Llongfile instead.

Separate logs file

Sometimes we want to separate the file of the logs based on the event that cause it. A sample case is we separate error logs and info logs. We can do this by creating separate loggers for errors and info. See code below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import (
    "log"
    "os"
)

func main() {
    // create info log
    fileInfo, err := openLogFile("./myinfo.log")
    if err != nil {
        log.Fatal(err)
    }
    infoLog := log.New(fileInfo, "[info]", log.LstdFlags|log.Lshortfile|log.Lmicroseconds)
    infoLog.Println("this is info")

    // create error log
    fileError, err := openLogFile("./myerror.log")
    if err != nil {
        log.Fatal(err)
    }
    errorLog := log.New(fileError, "[error]", log.LstdFlags|log.Lshortfile|log.Lmicroseconds)
    errorLog.Println("this is error")
}

func openLogFile(path string) (*os.File, error) {
    logFile, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
    if err != nil {
        return nil, err
    }
    return logFile, nil
}

The result log will be like this.
info.log:

[info]2021/10/10 03:36:38.734009 main.go:15: this is info

error.log:

[error]2021/10/10 03:36:38.735311 main.go:23: this is error

Conclusion

Writing logs to a file is important so that we can see the events that happened to our application. It can be done by setting the output of the logs. We can separate logs into different files to make them easier to monitor.

go  logs  linux 

See also

comments powered by Disqus