class Log
Overview
TheLog class provides a logging utility that you can use to output messages.
The messages, orLog::Entry have associated levels, such asInfo orError
that indicate their importance. SeeLog::Severity.
To log a message use the#trace,#debug,#info,#notice,#warn,
#error, and#fatal methods. They expect a block that will evaluate to the
message of the entry:
NOTE To useLog, you must explicitly import it withrequire "log"
require "log"
Log.info { "Program started" }
Data can be associated with a log entry via theLog::Emitter yielded in the logging methods.
Log.info &.emit("User logged in", user_id: 42)
If you want to log an exception, you can indicate it in theexception: named argument.
Log.warn(exception: e) { "Oh no!" }
Log.warn exception: e, &.emit("Oh no!", user_id: 42)
The block is only evaluated if the current message is to be emitted to someLog::Backend.
To add structured information to the message you can use theLog::Context.
When creating log messages they belong to asource. If the top-levelLog is used
as in the above examples its source is the empty string.
The source can be used to identify the module or part of the application that is logging. You can configure for each source a different level to filter the messages.
A recommended pattern is to declare aLog constant in the namespace of your shard or module as follows:
module DB
Log = ::Log.for("db") # Log for db source
def do_something
Log.info { "this is logged in db source" }
end
end
DB::Log.info { "this is also logged in db source" }
Log.for("db").info { "this is also logged in db source" }
Log.info { "this is logged in top-level source" }
That way, anyLog.info call within theDB module will use thedb source. And not the top-level::Log.info.
Sources can be nested. Continuing the last example, to declare aLog constantdb.pool source you can do as follows:
class DB::Pool
Log = DB::Log.for("pool") # Log for db.pool source
end
ALog will emit the messages to theLog::Backends attached to it as long as
the configured severity filter#level permits it.
Logs can also be created from a type directly. For the typeDB::Pool the sourcedb.pool will be used.
For generic types asFoo::Bar(Baz) the sourcefoo.bar will be used (i.e. without generic arguments).
module DB
Log = ::Log.for(self) # Log for db source
end
Default logging configuration
By default entries from all sources withInfo and above severity will
be logged toSTDOUT using theLog::IOBackend.
If you need to change the default level, backend or sources callLog.setup upon startup.
NOTE Calling.setup will override previous.setup calls.
Log.setup(:debug) # Log debug and above for all sources to STDOUT
Log.setup("myapp.*, http.*", :notice) # Log notice and above for myapp.* and http.* sources only, and log nothing for any other source.
backend_with_formatter = Log::IOBackend.new(formatter: custom_formatter)
Log.setup(:debug, backend_with_formatter) # Log debug and above for all sources to using a custom backend
Configure logging explicitly in the code
UseLog.setup methods to indicate which sources should go to which backends.
You can indicate actual sources or patterns.
- the empty string matches only the top-level source
*matches all the sourcesfoo.bar.*matchesfoo.barand every nested sourcefoo.barmatchesfoo.bar, but not its nested sources- Any comma separated combination of the above
The following configuration will setup for all sources to emit
warnings (or higher) toSTDOUT, allow any of thedb.* and
nested source to emit debug (or higher), and to also emit for all
sources errors (or higher) to an elasticsearch backend.
Log.setup do |c|
backend = Log::IOBackend.new
c.bind "*", :warn, backend
c.bind "db.*", :debug, backend
c.bind "*", :error, ElasticSearchBackend.new("http://localhost:9200")
end
Configure logging from environment variables
Include the following line to allow configuration from environment variables.
Log.setup_from_env
The environment variableLOG_LEVEL is used to indicate which severity level to emit.
By default entries from all sources withInfo and above severity will
be logged toSTDOUT using theLog::IOBackend.
To change the level and sources change the environment variable value:
$ LOG_LEVEL=DEBUG ./bin/app
You can tweak the default values (used whenLOG_LEVEL variable is not defined):
Log.setup_from_env(default_level: :error)
Defined in:
log.crlog/dispatch.cr
log/format.cr
log/log.cr
log/main.cr
log/setup.cr
log/spec.cr
Constructors
-
.for(source : String, level : Severity | Nil = nil) : Log
Creates a
Logfor the given source. -
.for(type : Class, level : Severity | Nil = nil) : Log
Creates a
Logfor the given type.
Class Method Summary
-
.builder : Log::Builder
Returns the default
Log::Builderused forLog.forcalls. -
.capture(source : String = "*", level : Severity = Log::Severity::Trace, *, builder = Log.builder, &)
Returns and yields an
EntriesCheckerthat allows checking specific log entries were emitted. -
.capture(level : Log::Severity = Log::Severity::Trace, *, builder : Log::Builder = Log.builder, &)
Returns and yields an
EntriesCheckerthat allows checking specific log entries were emitted. -
.context : Log::Context
Returns the current fiber logging context.
-
.context=(value : Log::Metadata) : Log::Metadata
Sets the current fiber logging context.
-
.context=(value : Log::Context) : Log::Metadata
Sets the current fiber logging context.
-
.debug(*, exception : Exception) : Nil
See
Log#debug. -
.debug(*, exception : Exception | Nil = nil, &)
See
Log#debug. -
.error(*, exception : Exception) : Nil
See
Log#error. -
.error(*, exception : Exception | Nil = nil, &)
See
Log#error. -
.fatal(*, exception : Exception) : Nil
See
Log#fatal. -
.fatal(*, exception : Exception | Nil = nil, &)
See
Log#fatal. -
.info(*, exception : Exception) : Nil
See
Log#info. -
.info(*, exception : Exception | Nil = nil, &)
See
Log#info. -
.notice(*, exception : Exception) : Nil
See
Log#notice. -
.notice(*, exception : Exception | Nil = nil, &)
See
Log#notice. -
.progname
The program name used for log entries
-
.progname=(progname : String)
The program name used for log entries
-
.setup(*, builder : Log::Builder = Log.builder, &)
Setups logging bindings discarding all previous configurations.
-
.setup(sources : String = "*", level : Log::Severity = Log::Severity::Info, backend : Log::Backend = IOBackend.new, *, builder : Log::Builder = Log.builder) : Nil
Setups logging forsources using the specifiedlevel,backend.
-
.setup(level : Log::Severity = Log::Severity::Info, backend : Log::Backend = IOBackend.new, *, builder : Log::Builder = Log.builder)
Setups logging for all sources using the specifiedlevel,backend.
-
.setup_from_env(*, builder : Log::Builder = Log.builder, default_level : Log::Severity = Log::Severity::Info, default_sources : String = "*", log_level_env : String = "LOG_LEVEL", backend : Log::Backend = Log::IOBackend.new)
Setups logging based on
LOG_LEVELenvironment variable. -
.trace(*, exception : Exception) : Nil
See
Log#trace. -
.trace(*, exception : Exception | Nil = nil, &)
See
Log#trace. -
.warn(*, exception : Exception) : Nil
See
Log#warn. -
.warn(*, exception : Exception | Nil = nil, &)
See
Log#warn. -
.with_context(values, &)
Method to save and restore the current logging context.
-
.with_context(**kwargs, &)
Method to save and restore the current logging context.
Macro Summary
-
define_formatter(name, pattern)
Generate subclasses of
Log::StaticFormatterfrom a string with interpolations
Instance Method Summary
- #backend : Backend | Nil
-
#context : Log::Context
Returns the current fiber logging context.
-
#context=(value : Log::Metadata | Log::Context)
Sets the current fiber logging context.
-
#debug(*, exception : Exception) : Nil
Logs the givenexception if the logger's current severity is lower than or equal to
Severity::Debug. -
#debug(*, exception : Exception | Nil = nil, &)
Logs a message if the logger's current severity is lower than or equal to
Severity::Debug. -
#error(*, exception : Exception) : Nil
Logs the givenexception if the logger's current severity is lower than or equal to
Severity::Error. -
#error(*, exception : Exception | Nil = nil, &)
Logs a message if the logger's current severity is lower than or equal to
Severity::Error. -
#fatal(*, exception : Exception) : Nil
Logs the givenexception if the logger's current severity is lower than or equal to
Severity::Fatal. -
#fatal(*, exception : Exception | Nil = nil, &)
Logs a message if the logger's current severity is lower than or equal to
Severity::Fatal. - #finalize : Nil
-
#for(child_source : String, level : Severity | Nil = nil) : Log
Creates a
Logfor the given nested source. -
#for(type : Class, level : Severity | Nil = nil) : Log
Creates a
Logfor the given type. -
#info(*, exception : Exception) : Nil
Logs the givenexception if the logger's current severity is lower than or equal to
Severity::Info. -
#info(*, exception : Exception | Nil = nil, &)
Logs a message if the logger's current severity is lower than or equal to
Severity::Info. - #level : Severity
-
#level=(value : Severity) : Log::Severity
Change this log severity level filter.
-
#notice(*, exception : Exception) : Nil
Logs the givenexception if the logger's current severity is lower than or equal to
Severity::Notice. -
#notice(*, exception : Exception | Nil = nil, &)
Logs a message if the logger's current severity is lower than or equal to
Severity::Notice. - #source : String
-
#trace(*, exception : Exception) : Nil
Logs the givenexception if the logger's current severity is lower than or equal to
Severity::Trace. -
#trace(*, exception : Exception | Nil = nil, &)
Logs a message if the logger's current severity is lower than or equal to
Severity::Trace. -
#warn(*, exception : Exception) : Nil
Logs the givenexception if the logger's current severity is lower than or equal to
Severity::Warn. -
#warn(*, exception : Exception | Nil = nil, &)
Logs a message if the logger's current severity is lower than or equal to
Severity::Warn. -
#with_context(values, &)
Method to save and restore the current logging context.
-
#with_context(**kwargs, &)
Method to save and restore the current logging context.
Instance methods inherited from class Reference
==(other : self)==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil) same?, to_s(io : IO) : Nil to_s
Constructor methods inherited from class Reference
new
new,
unsafe_construct(address : Pointer, *args, **opts) : self
unsafe_construct
Class methods inherited from class Reference
pre_initialize(address : Pointer)
pre_initialize
Instance methods inherited from class Object
! : Bool
!,
!=(other)
!=,
!~(other)
!~,
==(other)
==,
===(other : JSON::Any)===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as
Class methods inherited from class Object
from_json(string_or_io : String | IO, root : String)from_json(string_or_io : String | IO) from_json, from_yaml(string_or_io : String | IO) from_yaml
Macros inherited from class Object
class_getter(*names, &block)
class_getter,
class_getter!(*names)
class_getter!,
class_getter?(*names, &block)
class_getter?,
class_property(*names, &block)
class_property,
class_property!(*names)
class_property!,
class_property?(*names, &block)
class_property?,
class_setter(*names)
class_setter,
def_clone
def_clone,
def_equals(*fields)
def_equals,
def_equals_and_hash(*fields)
def_equals_and_hash,
def_hash(*fields)
def_hash,
delegate(*methods, to object)
delegate,
forward_missing_to(delegate)
forward_missing_to,
getter(*names, &block)
getter,
getter!(*names)
getter!,
getter?(*names, &block)
getter?,
property(*names, &block)
property,
property!(*names)
property!,
property?(*names, &block)
property?,
setter(*names)
setter
Constructor Detail
Creates aLog for the given type.
A typeFoo::Bar(Baz) corresponds to the sourcefoo.bar.
Iflevel is given, it will override the configuration.
Class Method Detail
Returns and yields anEntriesChecker that allows checking specific log entries
were emitted.
This capture will even work if there are currently no backends configured, effectively adding a temporary backend.
require "spec"
require "log"
require "log/spec"
Log.setup(:none)
def greet(name)
Log.info { "Greeting #{name}" }
end
it "greets" do
Log.capture do |logs|
greet("Harry")
greet("Hermione")
greet("Ron")
logs.check(:info, /greeting harry/i)
logs.next(:info, /greeting hermione/i)
end
end
By default logs of all sources and severities will be captured.
Uselevel to only capture of the given severity or above.
Usesource to narrow which source are captured. Values that represent single pattern likehttp.* are allowed.
TheEntriesChecker will hold a list of emitted entries.
EntriesChecker#check will find the next entry which matches the level and message.
EntriesChecker#next will validate that the following entry in the list matches the given level and message.
EntriesChecker#clear will clear the emitted and captured entries.
With these methods it is possible to express expected traces in either a strict or loose way, while checking ordering.
EntriesChecker#entry returns the last matchedEntry. Useful to check additional entry properties other than the message.
EntriesChecker#empty validates there are no pending entries to match.
Using the yieldedEntriesChecker allows clearing the entries between statements.
Invocations can be nested in order to capture each source in their ownEntriesChecker.
Returns and yields anEntriesChecker that allows checking specific log entries
were emitted.
This capture will even work if there are currently no backends configured, effectively adding a temporary backend.
require "spec"
require "log"
require "log/spec"
Log.setup(:none)
def greet(name)
Log.info { "Greeting #{name}" }
end
it "greets" do
Log.capture do |logs|
greet("Harry")
greet("Hermione")
greet("Ron")
logs.check(:info, /greeting harry/i)
logs.next(:info, /greeting hermione/i)
end
end
By default logs of all sources and severities will be captured.
Uselevel to only capture of the given severity or above.
Usesource to narrow which source are captured. Values that represent single pattern likehttp.* are allowed.
TheEntriesChecker will hold a list of emitted entries.
EntriesChecker#check will find the next entry which matches the level and message.
EntriesChecker#next will validate that the following entry in the list matches the given level and message.
EntriesChecker#clear will clear the emitted and captured entries.
With these methods it is possible to express expected traces in either a strict or loose way, while checking ordering.
EntriesChecker#entry returns the last matchedEntry. Useful to check additional entry properties other than the message.
EntriesChecker#empty validates there are no pending entries to match.
Using the yieldedEntriesChecker allows clearing the entries between statements.
Invocations can be nested in order to capture each source in their ownEntriesChecker.
The program name used for log entries
Defaults to the executable name
Setups logging bindings discarding all previous configurations.
Setups logging forsources using the specifiedlevel,backend.
Setups logging for all sources using the specifiedlevel,backend.
Setups logging based onLOG_LEVEL environment variable.
Method to save and restore the current logging context. Temporary context for the duration of the block can be set via arguments.
Log.context.set a: 1
Log.info { %(message with {"a" => 1} context) }
Log.with_context(b: 2) do
Log.context.set c: 3
Log.info { %(message with {"a" => 1, "b" => 2, "c" => 3} context) }
end
Log.info { %(message with {"a" => 1} context) }
Method to save and restore the current logging context. Temporary context for the duration of the block can be set via arguments.
Log.context.set a: 1
Log.info { %(message with {"a" => 1} context) }
Log.with_context(b: 2) do
Log.context.set c: 3
Log.info { %(message with {"a" => 1, "b" => 2, "c" => 3} context) }
end
Log.info { %(message with {"a" => 1} context) }
Macro Detail
Generate subclasses ofLog::StaticFormatter from a string with interpolations
Example:
Log.define_formatter MyFormat, "- #{severity}: #{message}"
SeeLog::StaticFormatter for the available methods that can
be called within the interpolations.
Instance Method Detail
Logs a message if the logger's current severity is lower than or equal to
Severity::Debug.
The block is not called unless the current severity level would emit a message.
Blocks which returnnil do not emit anything:
Log.debug do
if false
"Nothing will be logged."
end
end
Logs a message if the logger's current severity is lower than or equal to
Severity::Error.
The block is not called unless the current severity level would emit a message.
Blocks which returnnil do not emit anything:
Log.error do
if false
"Nothing will be logged."
end
end
Logs a message if the logger's current severity is lower than or equal to
Severity::Fatal.
The block is not called unless the current severity level would emit a message.
Blocks which returnnil do not emit anything:
Log.fatal do
if false
"Nothing will be logged."
end
end
Creates aLog for the given type.
A typeFoo::Bar(Baz) corresponds to the sourcefoo.bar.
Iflevel is given, it will override the configuration.
Logs a message if the logger's current severity is lower than or equal to
Severity::Info.
The block is not called unless the current severity level would emit a message.
Blocks which returnnil do not emit anything:
Log.info do
if false
"Nothing will be logged."
end
end
Logs a message if the logger's current severity is lower than or equal to
Severity::Notice.
The block is not called unless the current severity level would emit a message.
Blocks which returnnil do not emit anything:
Log.notice do
if false
"Nothing will be logged."
end
end
Logs a message if the logger's current severity is lower than or equal to
Severity::Trace.
The block is not called unless the current severity level would emit a message.
Blocks which returnnil do not emit anything:
Log.trace do
if false
"Nothing will be logged."
end
end
Logs a message if the logger's current severity is lower than or equal to
Severity::Warn.
The block is not called unless the current severity level would emit a message.
Blocks which returnnil do not emit anything:
Log.warn do
if false
"Nothing will be logged."
end
end
Method to save and restore the current logging context. Temporary context for the duration of the block can be set via arguments.
Log.context.set a: 1
Log.info { %(message with {"a" => 1} context) }
Log.with_context(b: 2) do
Log.context.set c: 3
Log.info { %(message with {"a" => 1, "b" => 2, "c" => 3} context) }
end
Log.info { %(message with {"a" => 1} context) }
Method to save and restore the current logging context. Temporary context for the duration of the block can be set via arguments.
Log.context.set a: 1
Log.info { %(message with {"a" => 1} context) }
Log.with_context(b: 2) do
Log.context.set c: 3
Log.info { %(message with {"a" => 1, "b" => 2, "c" => 3} context) }
end
Log.info { %(message with {"a" => 1} context) }