Logging features#
Logging features in Octez allow to monitor the execution of Octez binaries, informing in real time about events of interest, such as errors, completion of certain steps, etc. This is why various software components emit events throughout the codebase (see Using The Event Logging Framework), the logging framework dispatches them to an arbitrary number of (active) sinks which can filter print, store, or otherwise handle events.
Note
Log events should not be confused with contract events, which are emitted by smart contracts using specific support in the Michelson language.
The logging framework can be configured with environment variables, which specify how events are mapped to sinks. Some Octez binaries provide additional configurations means.
Events#
Events have:
a name
a section; a hierarchical event classification mechanism, i.e. a path-like list of strings, sometimes the name is appended to make a fully-qualified name,
a level quantifying the relative importance of the event (Debug, Info, Notice, Warning, Error, and Fatal — inspired from the Syslog standard severity levels),
and, as contents, arbitrary structured data. They can be serialized to any format supported by the data-encoding library (e.g. JSON) and pretty-printed for human readers.
Events are by default “lazy”: if no active sink accepts their section and level, they are not emitted at all. This means that outputting more events implies more CPU and memory usage.
“Legacy events” are the events that use the old & deprecated logging API; their contents all have the same structure: they are just human-readable text. The API makes that these events are evaluated even if they are not consumed by a sink; i.e. they are not lazily evaluated. The codebase is in the process of getting rid of them.
Sink Configuration#
The logging framework refers to sinks with URIs (a.k.a. structured strings of
the form schema://path?query): the schema of the URI is used to find the
appropriate sink-implementation, the rest of the URI is used to configure the
particular instance.
File-Descriptor Sinks#
File-descriptor sinks allow to configure loggers that output events to regular Unix file-descriptors. They are duplicatable. They actually consist in a family of four URI-schemes:
file-descriptor-path://outputs to a filefile-descriptor-stdout://outputs tostdout/1file-descriptor-stderr://outputs tostderr/2file-descriptor-syslog://outputs to asyslogfacility
Note: -stdout and -stderr schemes are there for convenience
and for making the API consistent; most Unix-ish systems nowadays have
/dev/std{out,err} and /dev/fd/[0-9]+ special files which can be
used with file-descriptor-path (with some precautions).
The path of the URI is used by file-descriptor-path to choose the
path to write to and ignored for the other three.
The query of the URI is used to further configure the sink instance.
Common options:
level-at-least=<loglevel>the minimal log-level that the sink will output.section-prefixcan be given many times and defines a list of pairs<section-prefix>:<level-threshold>which can be used to setup more precise filters.level-at-least=infocan be understood assection-prefix=:info, the empty section prefix matches all sections. To exclude a specific section use thenonefilter, for examplesection-prefix=p2p:none. To define a filter only for one specific sectionsection-prefix=p2p:debug§ion-prefix=:noneformat=<value>the output format used. Note that syslog output will ignore this option and use the syslog formatting. Possible values are:one-per-line(the default): output JSON objects, one per line,netstring: use the Netstring format (cf. Wikipedia) to separate JSON records,pporpp-rfc5424to output the events pretty-printed, one per line, using a format compatible with RFC-5424 (or Syslog).pp-shortto output the events pretty-printed in a shorter and more user-friendly fashion.
color=trueenables logs coloring. It only works on ttys, in conjunction withformat=pp-short.advertise-levels=trueenables the advertisement of the log-level of each events outputted in the sink.
Options available only for the file-descriptor-path:// case:
with-pid=<bool>whentrueadds the current process-id to the file path provided (for instance, useful for the node when not running in--singleprocessmode).fresh=<bool>whentruesmashes the content of the file if it already exists instead of appending to it.chmod=<int>sets the access-rights of the file at creation time (default is0o600, provided Umask allows it).daily-logs=<int>sets up a rotation for log files, creating a file for each day. The parameter is the number of days these logs should be kept, and hence the number of files. The day of the year with format [“yyyymmdd”] is added as a suffix to the filename, prefixed by a dash. We recomend not to put your tezos logs in/var/logif you use this option, as you system would uselogrotateautomatically.create-dirs=<bool>whentrueallows to create the directory where the log files are stored and all its parents recursively if they don’t exist.
Option available only for file-descriptor-syslog:// case:
facility=<facility>is the targeted syslog output. The possible values are:auth, authpriv, cron, daemon, ftp, kernel, local0, local1, local2, local3, local4, local5, local6, local7, lpr, mail, news, syslog, user, uucp, ntp, security, console.useris the default facility if no value is provided. See RFC-3164 for more information.Examples:
file-descriptor-path:///the/path/to/write.log?format=one-per-line&level-at-least=notice&with-pid=true&chmod=0o640→ Executables will write all log events of level at leastNoticeto a file/the/path/to/write-XXXX.logwhereXXXXis the PID, the file will be also readable by the user’s group (0o640).file-descriptor-stderr://?format=netstring→ Executables will write tostderrJSON blobs “packetized” as Netstrings.file-descriptor-path:///dev/fd/4?section-prefix=rpc:debug→ Executables will write to the file-descriptor4likely opened by a parent monitoring process. The reader will only receive the logs from the sectionrpc(but all of them includingDebug).file-descriptor-path:///the/path/to/write.log?section-prefix=rpc:debug§ion-prefix=validator:debug§ion-prefix=:none"→ Write only sections validator and rpc at debug level but exclude all other sections from the stream."file-descriptor-path:///tmp/node-logs/node.log?daily-logs=5&create-dirs=true§ion-prefix=:info"sets up daily log files with a history of up to 5 days and verbosity levelinfofor all logs. Files will be namednode-19700101.login an example of a file produced in 1970, January, the 1st. The log directorynode-logswill be automatically created if it doesn’t exist.
The format of the events is (usually minified):
{"fd-sink-item.v0":
{"hostname": <host-name>,
"time_stamp": <float-seconds-since-epoch>,
"section":[ <list-of-strings> ],
"event":
<event-specific-json> } }
Additionally, the "hostname" field can be customized with environment
variable TEZOS_EVENT_HOSTNAME; Its default value is the hostname of the
device the node is running on.
To store rotated logs, there is the daily-logs option to create logs files on
a daily basis. However, it is also possible to use logrotate by putting the
log file in /var/log/tezos/sink.log, for exemple. The following
configuration can then be put in /etc/logrotate.d/tezos/sink.log:
/var/log/tezos/sink.log {
daily
copytruncate
rotate 4
compress
}
File-Tree Sink#
This is a sink that dumps events as JSON files (same format as above) in a directory structure guided by the section of the events. It can be useful for testing the logging framework itself, or for off-line post-mortem analysis for instance.
The URI scheme is unix-files, the path is the top-level directory in
which the JSON files will be written.
The query of the URI allows one to filter the events early on.
level-at-least=<loglevel>the minimal log-level that the sink will output.name-matches=<regexps>comma-separated-list of POSIX regular expressions on the name of the events.name=<names>comma-separated-list of event names matched exactly.section=<sections>comma-separated-list of event sections matched exactly.no-section=<bool>when true only catch the events that have an empty section.
Example: unix-files:///the/path/to/write?level-at-least=info (the
path should be inexistent or already a directory).
The directory structure is as follows:
<section-dirname>/<event-name>/<YYYYMMDD>/<HHMMSS-MMMMMM>/<YYYYMMDD-HHMMSS-MMMMMM-xxxx.json>
where <section-dirname> is either no-section or
section-<section-name>.
Global Defaults#
By default, the Octez binaries generate user logs as follows:
file-descriptor-stdout://sink is activated by default and configured to output events of level at leastNoticeto stdout.
The node and the baker additionally generate by default more detailed internal logs as follows:
A file-descriptor-path sink is activated to store logs from last seven days with an
Infolevel. For the node, the path is<node-data-dir>/daily-logs/. For other tools, see the corresponding sections in this page.
Configuration blob#
Configuration blobs are used in various places: node configuration file, logging-configuration RPC, etc.
A configuration blob is a JSON object with one field "active_sinks"
which contains a list of URIs:
{
"active_sinks": [ <list-of-sink-URIs> ]
}
The URIs, which are sink implementations taking any of the forms above, are configured according to their schemes and queries, and activated.
In the following example two sinks are defined.
"active_sinks": [
"file-descriptor-stdout://?format=pp&level-at-least=notice&advertise-levels=true",
"file-descriptor-path://<path_to_log>/daily.log?daily-logs=7&format=one-per-line&level-at-least=info&create-dirs=true&chmod=0o640"
]
The first one defines a sink on stdout that will print the logs at level at least
noticeusing theppformat and with advertise levels:
<005> 2025-10-10T12:33:27.197-00:00 [agnostic-agent.period_status] new block (BLfoQ7p5cV5nyyiSPFenQxmQfvqi8oqZbqvmG1rL3qwcnYD1F5U) on proposal period (remaining period duration 199)
<005> 2025-10-10T12:33:27.198-00:00 [023-PtSeouLo.delegate.denunciation.accuser_processed_block] block BLfoQ7p5cV5nyyiSPFenQxmQfvqi8oqZbqvmG1rL3qwcnYD1F5U registered
The second one defines rotated logs. Daily logs will be written in the
<path_to_log>/directory with a rotation every 7 days. Here, the format will beone-per-lineand level at leastinfogiving more informative logs.
{"fd-sink-item.v0":{"hostname":"host","time_stamp":1759939740.311383,"section":["agnostic-agent"],"event":{"period_status.v0":{"block":"BLkzCnfm6XYth9rZ4axJBAjpc5dnt23b9aZsrHchxAeDVbVMzj6","period":"proposal","remaining":100859}}}}
{"fd-sink-item.v0":{"hostname":"host","time_stamp":1759939748.555863,"section":["agnostic-agent"],"event":{"period_status.v0":{"block":"BMDApJyvZiZKkpgeTfupLGPwxrsYoU2hwaLcdn5H4g4fxRb3zmh","period":"proposal","remaining":100858}}}}
This configuration blob should be included in "internal-events" of node config file and in
"internal_events" for client, accuser, baker config file.
Environment Variables#
The logging framework can be configured with environment variables
before starting an Octez executable (e.g., the node). Those variables work on all the code using the
tezos-stdlib-unix library as long as Internal_event_unix.init is
called; this should include all the regular octez-* binaries.
TEZOS_EVENTS_CONFIGmust be a whitespace-separated list of URIs:URIs that have a schema are activated.
URIs without a schema, i.e. simple paths, are understood as paths to configuration JSON files (format above) to load (which themselves activate sinks).
TEZOS_LOGandLWT_LOG(deprecated and has a lower priority) contain “rules” to configure the defaultfile-descriptor-stdoutsink. The rules are expressed with a DSL:rules are separated by semi-colons
;,each rule has the form
pattern -> level,a pattern is a minimalist glob-expression on the
section.nameof the event, e.g.rpc*for all events whose section.name starts withrpc,rules are ordered, i.e., the first pattern that matches, from left to right, fires the corresponding rule.
TEZOS_EVENT_HOSTNAMEis used by the file-descriptor-sink to tweak the JSON output (see above).
As the Irmin context backend uses an internal and specific logging
system, it is possible to configure it through the TEZOS_CONTEXT
environment variable, see Context.
Node-Specific Configuration#
The node supports some additional means to configure logging, besides environment variables.
Configuration File#
See octez-node config --help for the full schema of the node’s JSON
configuration file.
In particular the fields:
"internal-events"contains a configuration of the sinks (format above)."log"is an object which defines the configuration of the defaultfile-descriptor-stdoutsink; one can redirect the output to a file, set the rules, and change the formatting template. The goal of this configuration field is to be simpler to express thatinternal-eventsfor simpler changes.
Note that log is ignored if internal-events is present.
Command Line Options#
See octez-node run --help, the default file-descriptor-stdout:// sink
configuration can be also be changed with the following options:
-v/-vv: set the global log level toInfoorDebugrespectively.--log-output: set the output file.--log-coloring=<bool>: enable or disable colors in the default stdout logs. The default value istrue.
RPC /config/logging#
The node exposes an administrative PUT endpoint:
/config/logging.
The input schema is the JSON configuration of the sinks. It
deactivates all current sinks and activates the ones provided except
the file-descriptor-stdout:// sink that is left untouched.
Example: (assuming the file-descriptor-stdout:// is active not to miss other
events) this call adds a sink to suddenly start pretty-printing all
rpc events to a /tmp/rpclogs file:
octez-client rpc put /config/logging with \
'{ "active_sinks": [ "file-descriptor-path:///tmp/rpclogs?section-prefix=rpc:debug&format=pp&fresh=true" ] }'
Client and baker configuration#
Both octez-client and octez-{baker,accuser} can be configured either
using environment variables or using internal-events in the client configuration
file, with the file-descriptor sinks described above.
There is also one common option --log-requests which can be used to trace
all the interactions with the node (but it does not use the logging
framework).
By default, the baker also generates internal logs, which are stored at
<client-base-dir>/logs/octez-baker/*. Hence, running two bakers
(for two different accounts) with the same base
directory is not recommended.
Processing Structured Events#
This is work-in-progress, see:
octez-admin-client show event-loggingoutputs the configuration currently understood byoctez-admin-client(hence through theTEZOS_EVENTS_CONFIGvariable) and lists all the events it knows about.octez-admin-client output schema of <Event-Name> to <File-path>get the JSON-Schema for an event.
Example:
octez-admin-client output schema of block-seen-alpha to block-seen-alpha.json