Recording Logs

There are a few ways you might see a Fuchsia program generate log messages:

  • the LogSink service
  • the kernel's debuglog
  • a combination of these, routed through stdout or stderr

LogSink/syslog

Components that want to generate log messages call fuchsia.logger/LogSink.Connect. The fuchsia.logger.LogSink service must be allowlisted in the component manifest.

Connect takes a socket, into which the actual log messages are written by the syslog library.

If the socket's buffer is full, the writing thread will drop logs. Dropped messages on the writer side are counted and that count is sent in the next successful message, after which the counter is reset. log_listener prints a warning when it's aware of dropped messages.

The LogSink service must drain all of the sockets it receives quickly enough to prevent messages being dropped on the writer-side. LogSink is responsible for draining those sockets to fill internal buffers. This can result in high CPU usage in both the writing component and the LogSink when logging heavily.

Different languages use different mechanisms to talk to LogSink. See the relevant pages for more information:

debuglog handles

The kernel allows programs to create debuglog handles from the root resource, each handle allowing its owner to write messages into the kernel's shared ring buffer. Each message has a limit of 224 bytes, with content in excess being truncated.

In addition to being bindable to file descriptors, debuglog handles can be passed to the debuglog_write and debuglog_read syscalls. The read syscall is used to transfer from the debuglog to the system log.

Components that want to send their standard streams to the debuglog gain access through the fuchsia.boot.WriteOnlyLog protocol.

Most logs which are written to debuglog handles are written through stdio forwarding.

Standard streams: stdout and stderr

These concepts are familiar to many from other operating systems but their use in Fuchsia can be complicated to follow because they are routed differently in different parts of the system.

Drivers

stdout and stderr are inherited from devmgr which binds its own stdio fd's to debuglog, forwarding directly to the kernel log.

ddk/debug.h includes the zxlogf macro which prints if the given severity is enabled. Drivers can configure the minimum severity in kernel params.

Processes

The handles are populated in procargs by appmgr when creating processes and are pulled from fuchsia.sys/LaunchInfo if provided. For example, run-test-component provides its own stdout/stderr handles for test components so it can prevent that output from reaching the klog.

If no fd's are provided by the caller of CreateComponent, then the handles are cloned from appmgr's own stdout and stderr. appmgr populates its own stdio with debuglog handles, using the stdout-to-debuglog library to wire up a handle received from fuchsia.boot.WriteOnlyLog.

Forwarding klog to syslog

The Archivist continually reads from the klog and forwards those messages to the main log. Messages from the klog can be dropped by the pipeline if they are rolled out of the klog buffer before the archivist reads them into syslog -- these are not yet tracked.

All kernel log messages are sent to the system log with INFO severity because the debuglog syscalls lack a way to express the severity of a message.