# cse-go-logging Common golang logging module for use in CSE Go applications ## 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 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 ) 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.