Rho Rho language and toolchain

rho-log

Structured logging for Rho components.

rho log -level info -subject registry -message started -field port=8080
[2026-09-27T06:27:11.826Z] [info] [registry] started port=8080

A record is a timestamp, a level, a subject and a message with fields. The
subject is what says who wrote it, and it is aligned so a column of records
reads as a column.

Levels

trace, debug, info, warn, error, fatal. The names are the library's
own: a project that logs through this component and a service that logs through
the port write the same shape of record, so one reader can read both.

The command

rho log -format text|json -level info -subject registry -message started -field port=8080
FlagWhat it does
-formattext or json
-levelThe level, as named above
-subjectWho is writing the record
-messageThe message
-fieldA key=value field, repeatable, comma-separated
-no-levelOmit the level, for a compact line
-stampA pre-rendered timestamp, for a source with no clock

Using it from Rho

A project declares the component and asks for the logemit port:

deps:
  rho-log: ">=0.1.0"
build:
  targets:
    - id: go
      ports:
        - logemit

and calls the library:

import rho.log

fn main() void {
    info("registry", "started");
}

The port supplies the implementation and writes the record in the shape the
formatter produces, which is why a device writing to a serial console and a
server writing to standard output cannot drift apart.

Where the records go

Standard error carries the process's own records, which a service manager
already collects. An application log is for the program's own domain events —
what it decided and why — and RHO_LOG_FILE sends them to a file as well, so
they survive independently of whoever captured the process output.

A log that cannot be opened never stops the program: the record still goes to
standard error, and the reason is reported there.