It is very important to follow best practices when programming, different programming languages have their own unique best practices, but some best practices are common for most programming languages. Logger (or Error Logging or maintaining log files) is one such common best practice followed in the industry especially when developing a Back-End or an API.
In this article, I am gonna show how to implement a simple logger in GO. I divided the article in to 2 sections, first section explaining what a logger is, why loggers are used, importance, use and purpose of loggers and the other section is all about coding and getting the logger up and running in GO.
Understanding the Theory behind Loggers..
What is a Log, Logging, a Log File and a Logger, in programming??
- A Log can be said as a simple record of an event during the execution of a program.
- A Log File is one of the most common places where the logs are recorded. It is the most common output stream used during logging.
- Logging is the process of recording the logs (events that happen during execution) to a suitable output stream. There are various locations where logs are written, to log files, to databases, to terminals or command lines, to a dedicated UI (page) in the application when running (example CI tools), etc.
- Then finally, a Logger is the piece of code which is responsible in handling the logging process in a software application (or in programming).
Purpose of Loggers??
Loggers or Logging is really helpful and is very much a recommended practice in the context of programming. The main purpose of Logging is to generate a history of events executed in a software application and it helps any developer to go through the history of events logged and identify what has exactly happened, and it is most useful when an error or unexpected event occurs, developers are able to easily identify the error and trace backwards to identify the root cause of the error. In other words, logging makes the error identification process or debugging process much easier and straight forward for developers.
What to Log??
An interesting question, different people may have different opinions. You can log anything and everything, but you got to understand the purpose of why you need a log for your application and then decide what to log. No real straight forward answer but, depends on the requirement and use-case.
Typically, when it comes to logging the general purpose as mentioned above is to trace back errors. Hence, it is important to log specific and useful event in the program and also focus on not to flood the log with not so useful information and also not to miss-out on useful information.
Formatting the logger, i.e. deciding what information to log, can also be tricky. According to me, it is very helpful to log, the type/level of logger, date and time at which the event occurred, file in which the event occurred, function in which the event occurred (not should have, but nice to have), line of code responsible, developer message, error message given by the program (if logging an error), full error stack-trace given by the program (if logging an error). è Basically says; when, where and what event took place.
** If you wanna add something, please feel free and share your ideas, inputs and thoughts in the comments.
Let’s Dive in to Coding..
Let’s create a new GO project in the GOROOT directory (if you do not know where your GOROOT directory is, then open terminal or command-line and type
go env, you will get a list of environment variables related to GO, from that list you can find your GOROOT directory).
Now navigate to your GOROOT directory and create a new directory and name it “go-logger”. “go-logger” is now our project directory. Now create 2 directories inside the project directory, name one directory “src”, and name the other “log”, then create a new directory inside src directory and name it “utils”, then create a file inside utils directory and name it “helper.go” and as the last step here, create a file and name it “main.go” in the src directory. Now your directory structure should look as shown below:
Open helper.go file and add the following code:
There we define couple of exportable constants on top of the file and name them as “GeneralLogger” and “ErrorLogger”, and then inside the init function, we initialize the 2 loggers. First, we get the absolute path of the directory in which the log file needs to be created and then open or create the log file with required permissions.
generalLog, err := os.OpenFile(absPath+"/general-log.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
The above code snippet is responsible to open or create the file in the mentioned directory. Here I have used the permission “0666” — read and write permissions for all users (no permission to execute) and I have also set the flags to read-write, create and append.
And then we create a new instance for each of the loggers with the required format,
GeneralLogger = log.New(generalLog, "General Logger:\t", log.Ldate|log.Ltime|log.Lshortfile)ErrorLogger = log.New(generalLog, "Error Logger:\t", log.Ldate|log.Ltime|log.Lshortfile)
In the above code snippet, we provide the file, prefix of the logger which is a string to be appended at the beginning of the each line printed in the log file (“General Logger: ” in the first case) and then the required flags to get useful information (example date, time, file name, etc.) — more about flags can be found here: https://golang.org/pkg/log/#pkg-constants.
And then in the main.go file we can call the loggers and make use of them. Here is how the main file would look (a dummy implementation),
Import the utils package to reference the logger instances and then, we can call the Println function to write a new log to the log file.
That’s that and the log file should look as follows:
Hope this was helpful and you like what you just read. Please let me know your comments and suggestions.
** The source code can be found at: https://github.com/BNPrashanth/go-logger
** Similar to the above implementation, you can create multiple log files for different loggers with the above knowledge. In here, I created 2 loggers to log on a single log file. It also can be implemented to write multiple loggers to log to multiple different log files (info logger separately, error logger separately, debug logger separately, etc.), but one logger can write only one file, not multiple files.