logger/README.md

132 lines
5.8 KiB
Markdown
Raw Normal View History

2024-08-09 20:25:34 +00:00
# cse-go-logging
Common golang logging module for use in CSE Go applications
2024-08-09 04:38:50 +00:00
2024-08-09 20:25:34 +00:00
## Overview
This library will help you define a consistent logging experience within your Go applications. In a simple statement...
* This library will define a **Log Message**
* That is at a **Log Level**
* Which is formatted in a defined **Log Format**
* And forwarded to a **Log Destination**
This module is wrapper around Uber's Zap package. It serves more as a quick, consistent configuration than to add any additional functionality. For more details on how to use Zap, you can read the [Uber Documentation](https://pkg.go.dev/go.uber.org/zap)
### Additional Convenience Methods
I, for one, get annoyed with the following code:
~~~
MyObject, err := SomeInitializer(param1, param2)
if err != nil {
panic(err)
}
~~~
Those last three lines are extremely common, and clutter up the code and really do not add to readability. So, I created a set of convenience methods where you can replace the error handling with <ErrorLevel>OnError(err) and have it log your error, and panic or fatal automatically. The above code now becomes:
~~~
MyObject, err := SomeInitializer(param1, param2)
PanicOnError(err)
~~~
Its just athletics, but code is cleaner
### Process Cleanup
Another issue this library is trying to make simpler is proper shutdown on Fatal and Panic.
In many ways GO follows functional not object-oriented patterns. If an object is created, and defer() was defined, it can have unwanted side effects. So, I often avoid it unless the object is created, used, then immediately discarded. So how to we safely handle longer running objects.
This module has a solution, and you can use piggyback this in your own programs if you like.
There is a struct called AtExit that is defined, and it has two methods on it:
* Register
* Cleanup
Register takes one parameter, a function name. The call will register that function to be called any time you run a PanicOnError or FatalOnError. The Cleanup function will call all functions "Registered" before issuing the fatal/panic call.
Usage Example:
~~~
var (
db <pointer to some database connector>
)
func init() {
db = // Insert your favorite database connect string here
AtExit.Register(ShutDownDbConnection)
}
func ShutDownDbConnection() {
logger.ErrorOnError(db.close())
}
~~~
### Log Message
A log message, simply put will contain
* a time and date stamp
* a string indicating the Log Level
* a Log message
Optional items that may appear include
* A locator for where the message was requested in the code
* Name Value pairs the code may want you to note
* A stack trace giving even more detailed trace for error handling
### Log Level
As with many level based logging libraries, this library will define the following log levels:
* **Debug:** Recommendation: Tracing variable Values {user: Joe}
* **Info:** Recommendation: Dev status message {DB Connection successful}
* **Warn:** Recommendation: Non-Critical Errors {Got string, expected int, using 0}
* **Error:** Recommendation: Serious error but not enough to stop program execution {Network Not Found, 404 errors}
* **Fatal:** Recommendation: Serious Errors, program exist with error code 1
* **Panic:** Recommendation: Full panic mode, {divide by 0}
## Log Format
In this library, there will be two different output formats
* **Text:** Single line per message with space delimiters
* **JSON:** JSON format for easy automated processing
Example of Text Log Format:
~~~
2024-01-25T12:33:25.613-0700 INFO cse-go-logging/logging_test.go:25 This is my log message
~~~
Example of JSON Log Format:
~~~
{
"level": "error",
"ts": "2024-01-25T13:10:01.025-0700",
"caller": "cse-go-logging/logging_test.go:25",
"msg": "This is my log message",
"stacktrace": "cse-go-logging.(*LoggingTestSuite).Test_Placeholder\n\t/Users/a846682/GolandProjects/cse-go-logging/logging_test.go:25\nreflect.Value.call\n\t/Users/a846682/.asdf/installs/golang/1.21.6/go/src/reflect/value.go:596\nreflect.Value.Call\n\t/Users/a846682/.asdf/installs/golang/1.21.6/go/src/reflect/value.go:380\ngithub.com/stretchr/testify/suite.Run.func1\n\t/Users/a846682/.asdf/installs/golang/1.21.6/packages/pkg/mod/github.com/stretchr/testify@v1.8.1/suite/suite.go:175\ntesting.tRunner\n\t/Users/a846682/.asdf/installs/golang/1.21.6/go/src/testing/testing.go:1595"
}
~~~
### Log Destination
Depending on the **Log Environment** you have configured your code to use, the log output will be sent to one of three different destinations:
* **StdErr:** Development, Debug, and Production logs will send messages to standard error. These should appear on your output console within your machine
* **LogFile:** Debug and Testing logs will create a file in your running directory named */log/debug*
* If you are running with a Testing log, the library will not use your live file system, but instead will use a memory map backed filesystem called LogFS and will exist as long as the test suite is running.
## Log Environments
This library defines four predefined environments for your logging needs:
* **Development:** for normal development operations. Logs will be text based, and log Info and higher messages. Output will be to StdErr
* **Debug:** To increase the verbosity of logging, a Debug environment will also include Debug log messages, and will capture all logs to a *logs/debug* file within your working directory. In addition, stack traces will be turned on. So, errors can be more easily tracked.
* **Testing:** This environment will operate exactly like Debug, except that it will not send logs to stderr, and will attach a memory backed file system that /logs/debug will be written to. This allows tests to easily pick up the output of log messages and test for proper logging
* **Production:** Unlike the other environments, Production logs are JSON formatted.