Tutorial - Logging
What you’ll learn
- How Granitic handles logging from your code.
 - How to adjust which messages are logged.
 - How to change logging behaviour at runtime.
 
Prerequisites
- Follow the Granitic installation instructions
 - Read the before you start tutorial
 - Either have completed tutorial 2 or clone the
tutorial repo and navigate to 
json/003/recordstorein your terminal. 
Logging
Logging in Granitic gives developers fine-grained control over which components output logging information. There are two main concepts for you to become familiar with:
- Loggers - the components that format log messages and choose whether or not to write them to a console or file, based on the severity assigned to the message.
 - Severity - the importance of a message to be logged.
 
Severities are (in ascending order of importance)  TRACE, DEBUG, INFO, WARN, ERROR, FATAL.
See the GoDoc for more detail
Your code will log messages through a Granitic component called a Logger. Granitic has two built-in Loggers
the ApplicationLogger and the FrameworkLogger.
As the names suggest, the FrameworkLogger
is used by internal Granitic components and the ApplicationLogger is for your application’s code.
As the majority of components that you build will need access to the ApplicationLogger, Granitic has a built-in
ComponentDecorator that automatically
injects a reference to the ApplicationLogger into any of your components with a struct field that is exactly:
    Log logging.Logger
To see this in action, modify the file artist/get.go so it looks like:
package artist
import (
	"context"
	"fmt"
	"github.com/graniticio/granitic/v2/logging"
	"github.com/graniticio/granitic/v2/ws"
)
type GetLogic struct {
	EnvLabel string
	Log      logging.Logger
}
func (gl *GetLogic) Process(ctx context.Context, req *ws.Request, res *ws.Response) {
	an := fmt.Sprintf("Hello, %s!", gl.EnvLabel)
	res.Body = Info{
		Name: an,
	}
	log := gl.Log
	log.LogInfof("Environment is set to '%s'", gl.EnvLabel)
	log.LogTracef("Request served")
}
type Info struct {
	Name string
}
Open your terminal and run:
grnc-bind && go build && ./recordstore
Keep the terminal window visible and visit http://localhost:8080/artist and you’ll see a line appear in your terminal similar to:
07/Aug/2023:18:37:16 Z INFO [artistHandlerLogic] Environment is set to 'TEST'
This line shows:
- The timestamp of when the message was logged
 - The severity of the message (INFO)
 - The name of the component issuing the message (artistHandlerLogic)
 - The message itself
 
Unit tests
You may find the type logging.ConsoleErrorLogger useful when writing unit tests for code that needs a logging.Logger
Global log level
You may have noticed that the INFO level message is shown but the TRACE message is not.
This is because the global log level for the ApplicationLogger is also set to INFO in the facility configuration
file 
facility/config/logging.jsonwhich looks something like:
{
  "LogWriting": {
    "EnableConsoleLogging": true,
    "EnableFileLogging": false,
    "File": {
      "LogPath": "./granitic.log",
      "BufferSize": 50
    },
    "Format": {
      "UtcTimes":     true,
      "Unset": "-"
    }
  },
  "FrameworkLogger":{
    "GlobalLogLevel": "INFO"
  },
  "ApplicationLogger":{
    "GlobalLogLevel": "INFO"
  }
}
The global log level means that only messages with a severity equal to or greater than the global log level with be logged.
You can override the global log level for you own application. Open config/base.json and set the contents to:
{
  "Facilities": {
    "HTTPServer": true,
    "JSONWs": true
  },
  "ApplicationLogger":{
    "GlobalLogLevel": "ERROR"
  },
  "environment": {
    "label": "DEV"
  }
}
If you stop and restart your recordstore application and refresh or re-visit
http://localhost:8080/artist, you’ll see that the INFO message is no longer displayed.
Notice that you are still seeing other INFO messages from components whose names start grnc. These components
are built-in Granitic components and use the FrameworkLogger component which has its own GlobalLogLevel
File logging
By default Granitic only logs messages to the console. Look at the file facility/config/logging.json to
see how you can enable logging to a file.
Component specific log levels
Sometimes you want to allow a single component to log messages that are below the global log level (to aid debugging) or to
squelch a component that is too noisy. This can be achieved by setting a log level for a specific component. Modify your
config/base.json file so that the ApplicationLogger section looks like:
"ApplicationLogger": {
    "GlobalLogLevel": "ERROR",
    "ComponentLogLevels": {
        "artistHandlerLogic": "TRACE"
    }
}
If you stop and restart your recordstore application and refresh or re-visit http://localhost:8080/artist,
you’ll see an additional message displayed:
07/Aug/2023:18:43:03 Z INFO [artistHandlerLogic] Environment is set to 'UNSET' 07/Aug/2023:18:43:03 Z TRACE [artistHandlerLogic] Request served
Runtime control of logging
When investigating problems with production code it can be very helpful to enable lower-priority messages without having
to restart or re-deploy an application. Granitic supports this through the RuntimeCtl facility.
Stop your instance of recordstore and change 
config/base.jsonso that the
Facilities
section looks like:
"Facilities": {
    "HTTPServer": true,
    "JSONWs": true,
    "RuntimeCtl": true
}
Restart recordstore and you will see a new line in the startup logs:
07/Aug/2023:18:44:05 Z INFO [grncCtlServer] Listening on 9099
You can now use the grnc-ctrl command line tool to issue
commands to recordstore while it is running.
To get a list of the high level actions you can perform with this tool, open a new terminal and run:
grnc-ctl help
and for more detailled help about the commands relating to log-level management:
grnc-ctl help global-level grnc-ctl help log-level
for more information on the commands related to logging.
Try running:
grnc-ctl log-level artistHandlerLogic FATAL
to raise the logging threshold for the artistHandlerLogic component to FATAL
Any changes you make with the grnc-ctl tool are non-permanent and will be reset the next time you start
your application.
Recap
- Granitic can automatically inject a 
Loggerinto your application code. - You can log at different levels of severity.
 - You can set the global severity level at which messages will be logged in configuration.
 - You can override this global level for individual components.
 - You can change both the global and component-specific levels at runtime using 
grnc-ctl 
Further reading
Next
The next tutorial covers the capture of data from web-service calls
