Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Logging library for Golang inspired by the Python logger.

License

NotificationsYou must be signed in to change notification settings

dl1998/go-logging

Repository files navigation

Go ReferenceGo Report CardCoverage Status

Go logger implements logger for Golang, current implementation is majorly inspired by Python logger.

Installation

go get github.com/dl1998/go-logging

or

go install github.com/dl1998/go-logging@[version]

Note: replace[version] with the version you want to install.

Usage

Check examples provided in theexamples.

Logger supports 11 logging levels + 2 (when not set):

  • All (special level, cannot be used for logging)
  • Trace
  • Debug
  • Verbose
  • Info
  • Notice
  • Warning
  • Severe
  • Error
  • Alert
  • Critical
  • Emergency
  • Null (special level, cannot be used for logging)

Default Logger

Default logger could be used like in the following example:

  • Standard logger

    logger.Warning("Message for logging: %s.","my message")
  • Structured logger

    structuredlogger.Warning("message","My message.")

    or

    structuredlogger.Warning(map[string]string{"message":"My message.",})

By default, root logger prints on console only, and starting from Warning level. It could be changed by setting logginglevel:

  • Standard logger

    logger.Configure(logger.NewConfiguration(logger.WithFromLevel(level.All)))
  • Structured logger

    structuredlogger.Configure(logger.NewConfiguration(logger.WithFromLevel(level.All)))

After changing log level to "All" it will print messages for any level.

You could also change the format of the default structured logger by setting the format (default: json).

structuredlogger.Configure(logger.NewConfiguration(logger.WithFormat("key-value")))

All options available for the configuration are:

For Standard Logger

MethodDefaultDescription
WithErrorLevellevel.ErrorSet logging level used to log raised or captured error.
WithPanicLevellevel.CriticalSet logging level used to log panic.
WithRequestTemplate"Request: [{Method}] {URL}"Set template for the http.Request wrapper.
WithResponseTemplate"Response: [{StatusCode}] {Status}"Set template for the http.Response wrapper.
WithFromLevellevel.WarningSet logging level from which logger should log messages.
WithToLevellevel.NullSet logging level till which logger should log messages.
WithTemplate"%(level):%(name):%(message)"Set template for logging message.
WithFile""Set file where to log messages, if not set, then logging to file will be disabled.
WithName"root"Set logger name.
WithTimeFormattime.RFC3339Set time format for logging message.

For Structured Logger

MethodDefaultDescription
WithErrorLevellevel.ErrorSet logging level used to log raised or captured error.
WithPanicLevellevel.CriticalSet logging level used to log panic.
WithRequestMappingmap[string]string {
"url": "URL",
"method": "Method",
}
Set mapping for the http.Request wrapper.
WithResponseMappingmap[string]string {
"status": "Status",
"status-code": "StatusCode",
}
Set mapping for the http.Response wrapper.
WithFromLevellevel.WarningSet logging level from which logger should log messages.
WithToLevellevel.NullSet logging level till which logger should log messages.
WithTemplatemap[string]string {
"timestamp": "%(timestamp)",
"level": "%(level)",
"name": "%(name)",
}
Set template for logging structure.
WithFile""Set file where to log messages, if not set, then logging to file will be disabled.
WithFormat"json"Set format for structured logging.

Could be one of the following
  • json
  • key-value
WithPrettyfalseSet if json message should be pretty printed.
Option works only with "json" format.
WithKeyValueDelimiter"="Set key-value delimiter (eg. "key=value", where '=' is the delimiter).
Option works only with "key-value" format.
WithPairSeparator" "Set key-value separator (eg. "key1=value1,key2=value2", where ',' is the separator).
Option works only with "key-value" format.
WithName"root"Set logger name.
WithTimeFormattime.RFC3339Set time format for logging message.

Custom Logger

Alternatively you could create application logger. To do this you would need to create a new logger.

  • Standard logger

    applicationLogger:=logger.New("application-logger",time.RFC3339)
  • Standard async logger

    applicationLogger:=logger.NewAsyncLogger("application-logger",time.RFC3339,100)
  • Structured logger

    applicationLogger:=structuredlogger.New("application-logger",time.RFC3339)
  • Structured async logger

    applicationLogger:=structuredlogger.NewAsyncLogger("application-logger",time.RFC3339,100)

After this you need to set up it, for this create a new formatter that says how to log the message by providing atemplate.

Formatter

Available template options:

OptionScopeDescription
%(name)BothLogger name.
%(level)BothLog level name.
%(levelnr)BothLog level number.
%(datetime)BothCurrent date and/or time formatted using time format. Default: time.RFC3339.
%(timestamp)BothCurrent timestamp.
%(fname)BothName of the file from which logger has been called.
%(fline)BothLine in the file in which logger has been called.
%(message)standard loggerLog message.
  • Standard logger

    applicationFormatter:=formatter.New("%(datetime) [%(level)] %(message)")
  • Structured logger

    • JSON format

      applicationFormatter:=formatter.NewJSON(map[string]string{"time":"%(timestamp)","level":"%(level)",},false)
    • Key-Value format

      applicationFormatter:=formatter.NewKeyValue(map[string]string{"time":"%(timestamp)","level":"%(level)",},"="," ")

After creation of the formatter, you need to create a new handler that tells where to write log messages.

Handler

There are three predefined types of handler (for standard and structured logger each):

  • Console Handler - it takes log level starting from which it would log messages, log level till which it would logmessages, and formatter that tells how to log message. It logs messages to standard output.

    newConsoleHandler:=handler.NewConsoleHandler(level.Debug,level.Null,applicationFormatter)
  • Console Error Handler - it takes log level starting from which it would log messages, log level till which it wouldlog messages, and formatter that tells how to log message. It logs messages to error output.

    newConsoleErrorHandler:=handler.NewConsoleErrorHandler(level.Debug,level.Null,applicationFormatter)
  • File Handler - it takes log level starting from which it would log messages, log level till which it wouldlog messages, formatter that tells how to log message, and path to the file where to log those data.

    newFileHandler:=handler.NewFileHandler(level.Debug,level.Null,applicationFormatter,"system.log")

You could create your custom handler:

customHandler:=handler.New(level.Debug,level.Null,applicationFormatter,os.Stdout)

It takes two additional arguments writer for standard messages and for error messages. Standard message logs till"Error" level, after this error writer is used.

After handler has been created it shall be registered.

// Register console stdout handler.applicationLogger.AddHandler(newConsoleHandler)// Register console stderr handler.applicationLogger.AddHandler(newConsoleErrorHandler)// Register file handler.applicationLogger.AddHandler(newFileHandler)

Now it could be used to log the message, simply by calling respective level of logging and providing message witharguments.

  • Standard logger

    applicationLogger.Info("My message: %s.","logged using application logger")
  • Standard async logger

    applicationLogger.Info("My message: %s.","logged using application async logger")// Wait for all messages to be logged before exiting the program.applicationLogger.WaitToFinishLogging()
  • Structured logger

    • Varargs

      applicationLogger.Info("message","Logged using structured logger with varargs.")
    • Map

      applicationLogger.Info(map[string]string{"message":"Logged using structured logger with map.",})
  • Structured async logger

    • Varargs

      applicationLogger.Info("message","Logged using structured logger with varargs.")// Wait for all messages to be logged before exiting the program.applicationLogger.WaitToFinishLogging()
    • Map

      applicationLogger.Info(map[string]string{"message":"Logged using structured logger with map.",})// Wait for all messages to be logged before exiting the program.applicationLogger.WaitToFinishLogging()

Async Loggers - Additional Information

Async loggers are used to log messages asynchronously. It is useful when you want to log messages without blocking themain thread. However, you need to wait for all messages to be logged before exiting the program. You can do this bycalling theWaitToFinishLogging method, it will block the main thread until all messages are logged. Alternatively,you can close the logger by calling theClose method, it will close the message queue without waiting for all messagesto be logged. This is useful when you want to exit the program without waiting for all messages to be logged. Aftercalling theClose method, you can open the logger again by calling theOpen method, it accepts the new message queuesize as an argument.Open method will open the logger with the new message queue size and start listening for themessages.

Example that waits for all messages to be logged, then close the logger and open it again with a new message queue size:

forindex:=0;index<1000;index++ {applicationLogger.Info("Counter: %d.",index)}// Wait for all messages to be logged before exiting the program.applicationLogger.WaitToFinishLogging()// Close the logger.applicationLogger.Close()// Open the logger with a new message queue size.iferr:=applicationLogger.Open(100);err!=nil {panic(err)}

Note: if you assign a new message queue size that is smaller than the number of messages sent to the queue, the loggerwill add messages to the queue until it is not full, then it will wait (blocking the process) until the message from thequeue will be processed and free up the space in the message queue.

Wrappers

Error / Panic

You could wrap error or raise a new error and log error message using the logger. By default, it will log error messageusing thelevel.Error level. However, it could be changed by setting the error level in the logger configuration.

  • Standard logger

    varerrerror// Raise Error with default error level (level.Error)err=applicationLogger.RaiseError("exit code: %d",1)// Change error levelapplicationLogger.SetErrorLevel(level.Alert)// Capture Error with new error level (level.Alert)applicationLogger.CaptureError(err)
  • Structured logger

    varerrerror// Raise Error with default error level (level.Error) and additional fieldserr=applicationLogger.RaiseError("exit code: 1","hostname","localhost")// Change error levelapplicationLogger.SetErrorLevel(level.Alert)// Capture Error with new error level (level.Alert) and additional fieldsapplicationLogger.CaptureError(err,"hostname","localhost")

Similarly, you could panic and log panic message using the logger. By default, it will log panic message using thelevel.Critical level. However, it could be changed by setting the panic level in the logger configuration.

  • Standard logger

    // Change panic levelapplicationLogger.SetPanicLevel(level.Emergency)// Raise Panic with new panic level (level.Emergency)applicationLogger.Panic("exit code: %d",1)
  • Structured logger

    // Change panic levelapplicationLogger.SetPanicLevel(level.Emergency)// Raise Panic with new panic level (level.Emergency) and additional fieldsapplicationLogger.Panic("exit code: 1","hostname","localhost")

Struct

You could wrap a struct and log its public fields using the logger. To do this, you need to provide template (standardlogger), mapping (structured logger) of the struct fields to the logger fields. Optionally, for structured logger youcould also provide additional fields that will be logged with the struct fields.

  • Standard logger

    typeMyStructstruct {StringstringIntint}myStruct:=MyStruct{String:"example",Int:10,}applicationLogger.WrapStruct(level.Info,"{String}: {Int}",myStruct)
  • Structured logger

    typeMyStructstruct {StringstringIntint}myStruct:=MyStruct{String:"example",Int:10,}applicationLogger.WrapStruct(level.Info,map[string]string{"log-string":"String","log-int":"Int",},myStruct,"hostname","localhost")

http.Request and http.Response

You could wrap http.Request and http.Response and log their fields using the logger. By default, logger has predefinedtemplate (standard logger), mapping (structured logger) for http.Request and http.Response fields. However, you couldchange it by providing your own template / mapping. Optionally, for structured logger you could also provide additionalfields that will be logged with the http.Request and http.Response fields.

  • Standard logger

    request,_:=http.NewRequest("GET","http://example.com",nil)response,_:=http.Get("http://example.com")// Set custom template for http.Request and http.ResponseapplicationLogger.SetRequestTemplate("[{Method}] {URL}")applicationLogger.SetResponseTemplate("[{StatusCode}] {Status}")applicationLogger.WrapRequest(level.Info,request)applicationLogger.WrapResponse(level.Info,response)
  • Structured logger

    request,_:=http.NewRequest("GET","http://example.com",nil)response,_:=http.Get("http://example.com")// Set custom mapping for http.Request and http.ResponseapplicationLogger.SetRequestMapping(map[string]string{"Method":"Method","Url":"URL",})applicationLogger.SetResponseMapping(map[string]string{"StatusCode":"StatusCode","Status":"Status",})applicationLogger.WrapRequest(level.Info,request,"hostname","localhost")applicationLogger.WrapResponse(level.Info,response,"hostname","localhost")

Reading Configuration from File

You could also read configuration from a file. Configuration file should be in one of the following formats:*.json,*.yaml,*.xml. Configuration file should contain the following fields:

- Loggers (array of loggers)  - Name (string)  - Time Format (string)  - Error Level (string)  - Panic Level (string)  - Request Template (string)  - Response Template (string)  - Request Mapping (map of string to string)  - Response Mapping (map of string to string)  - Message Queue Size (int)  - Handlers (array of handlers)    - Type (string)    - From Level (string)    - To Level (string)    - File (string)    - Formatter (string)      - Type (string)      - Pretty Print (bool)      - Pair Separator (string)      - Key Value Delimiter (string)      - Template (template)        - String Value (string)        - Map Value (map of string to string)

Example of the configuration files:

  • JSON

    {"loggers": [    {"name":"example-logger","time-format":"2006-01-02 15:04:05","error-level":"error","panic-level":"critical","request-template":"Request: [{Method}] {URL}","response-template":"Response: [{StatusCode}] {Status}","request-mapping": {"method":"Method","url":"URL"      },"response-mapping": {"status-code":"StatusCode","status":"Status"      },"message-queue-size":100,"handlers": [        {"type":"stdout","from-level":"all","to-level":"severe","formatter": {"type":"json","pretty-print":false,"template": {"string":"%(datetime) - %(level) - %(message)","map": {"timestamp":"%(datetime)","level":"%(level)","name":"%(name)"              }            }          }        },        {"type":"stderr","from-level":"error","to-level":"null","formatter": {"type":"key-value","pair-separator":"","key-value-delimiter":":","template": {"string":"%(datetime) - %(level) - %(message)","map": {"timestamp":"%(datetime)","level":"%(level)","name":"%(name)"              }            }          }        },        {"type":"file","from-level":"all","to-level":"null","file":"example.log","formatter": {"type":"json","pretty-print":true,"template": {"string":"%(datetime) - %(level) - %(message)","map": {"timestamp":"%(datetime)","level":"%(level)","name":"%(name)"              }            }          }        }      ]    }  ]}
  • YAML

    loggers:  -name:example-loggertime-format:"2006-01-02 15:04:05"error-level:errorpanic-level:criticalrequest-template:"Request: [{Method}] {URL}"response-template:"Response: [{StatusCode}] {Status}"request-mapping:method:Methodurl:URLresponse-mapping:status-code:StatusCodestatus:Statusmessage-queue-size:100handlers:      -type:stdoutfrom-level:allto-level:severeformatter:type:jsonpretty-print:falsetemplate:string:"%(datetime) - %(level) - %(message)"map:timestamp:"%(datetime)"level:"%(level)"name:"%(name)"      -type:stderrfrom-level:errorto-level:"null"formatter:type:key-valuepair-separator:""key-value-delimiter:":"template:string:"%(datetime) - %(level) - %(message)"map:timestamp:"%(datetime)"level:"%(level)"name:"%(name)"      -type:filefrom-level:allto-level:"null"file:example.logformatter:type:jsonpretty-print:truetemplate:string:"%(datetime) - %(level) - %(message)"map:timestamp:"%(datetime)"level:"%(level)"name:"%(name)"
  • XML

    <root>  <loggers>    <logger>      <name>example-logger</name>      <time-format>2006-01-02 15:04:05</time-format>      <error-level>error</error-level>      <panic-level>critical</panic-level>      <request-template>Request: [{Method}] {URL}</request-template>      <response-template>Response: [{StatusCode}] {Status}</response-template>      <request-mapping>        <method>Method</method>        <url>URL</url>      </request-mapping>      <response-mapping>        <status-code>StatusCode</status-code>        <status>Status</status>      </response-mapping>      <message-queue-size>100</message-queue-size>      <handlers>        <handler>          <type>stdout</type>          <from-level>all</from-level>          <to-level>severe</to-level>          <formatter>            <type>json</type>            <pretty-print>false</pretty-print>            <template>              <string>%(datetime) - %(level) - %(message)</string>              <map>                <timestamp>%(datetime)</timestamp>                <level>%(level)</level>                <name>%(name)</name>              </map>            </template>          </formatter>        </handler>        <handler>          <type>stderr</type>          <from-level>error</from-level>          <to-level>null</to-level>          <formatter>            <type>key-value</type>            <pair-separator> </pair-separator>            <key-value-delimiter>:</key-value-delimiter>            <template>              <string>%(datetime) - %(level) - %(message)</string>              <map>                <timestamp>%(datetime)</timestamp>                <level>%(level)</level>                <name>%(name)</name>              </map>            </template>          </formatter>        </handler>        <handler>          <type>file</type>          <from-level>all</from-level>          <to-level>null</to-level>          <file>example.log</file>          <formatter>            <type>json</type>            <pretty-print>true</pretty-print>            <template>              <string>%(datetime) - %(level) - %(message)</string>              <map>                <timestamp>%(datetime)</timestamp>                <level>%(level)</level>                <name>%(name)</name>              </map>            </template>          </formatter>        </handler>      </handlers>    </logger>  </loggers></root>

To create a logger from the configuration file, you need to:

  1. Create a new Parser with the Configuration object. You shall use parser from thelogger orstructuredlogger.

    1. Create a new Configuration object manually and initialize parser with it.

      1. Parse configuration file to receive the Configuration. You could do this by calling theReadFromJSON,ReadFromYAML,ReadFromXML methods respectively, it will return the Configuration object.

        // Parse configuration from JSON file.newConfiguration,err:=parser.ReadFromJSON("path/to/configuration/file.json")iferr!=nil {panic(err)}// Parse configuration from YAML file.newConfiguration,err:=parser.ReadFromYAML("path/to/configuration/file.yaml")iferr!=nil {panic(err)}// Parse configuration from XML file.newConfiguration,err:=parser.ReadFromXML("path/to/configuration/file.xml")iferr!=nil {panic(err)}
      2. Create a new Parser with the Configuration object. You shall use parser from thelogger orstructuredloggerpackages respectively, depending on which one you need.

        newParser:=parser.NewParser(newConfiguration)
    2. Create Parser from the configuration file directly.

      // Create a new Parser from JSON configuration file.newParser,err:=parser.ParseJSON("path/to/configuration/file.json")iferr!=nil {panic(err)}// Create a new Parser from YAML configuration file.newParser,err:=parser.ParseYAML("path/to/configuration/file.yaml")iferr!=nil {panic(err)}// Create a new Parser from XML configuration file.newParser,err:=parser.ParseXML("path/to/configuration/file.xml")iferr!=nil {panic(err)}
  2. Get a logger from the Parser.

    // Standard LoggernewLogger:=newParser.GetLogger("example-logger")// Async LoggernewLogger:=newParser.GetAsyncLogger("example-logger")

[8]ページ先頭

©2009-2025 Movatter.jp