Skip to content

roblox-aurora/rbx-log

Repository files navigation

Not associated with BLAMMO ;-)

Structured logging library for Roblox, akin to (and inspired by) serilog. It uses the Message Templates spec for handling logging.

Setup

To begin, you will need to install the package. This can be done via

npm i @rbxts/log

Once installed, to begin logging you will need to configure the logger. (The server/client will need separate configurations, this is the recommended way of doing it)

Basic setup:

import Log, { Logger } from "@rbxts/log";
Log.SetLogger(
    Logger.configure()
        .WriteTo(Log.RobloxOutput()) // WriteTo takes a sink and writes to it
        .Create() // Creates the logger from the configuration
);

Log.Info("Hello, Log!");

The main power of this library comes from the structured event data logging:

const startPoint = new Vector2(0, 0)
const position = new Vector2(25, 134);
const distance = position.sub(startPoint).Magnitude;

Log.Info("Walked to {@Position}, travelling a distance of {Distance}", position, distance);

Log uses message templates, like serilog and will format strings with named parameters (positional coming soon).

The example above has two properties, Position and Distance, in the log event the @ operator in front of position tells Log to serialize the object passed in, rather than using tostring(value). The listed data types this library can serialize is listed below.

Rendered into JSON using HttpService, these properties appear alongside the Timestamp, Level and Template like:

{"Position": {"X": 25, "Y": 134}, "Distance": 136.32 }

The structured nature of the data means that it is easily searched and filtered by external tools (as well as roblox-based libraries like Zircon)

Of course, this data can be logged to the roblox console or another supported console directly if need be, the default Roblox Output sink for example displays the above as such:

08:29:20 [INF] Walked to {"X": 25, "Y": 134}, travelling a distance of 136.32

Features

  • Level-based logging, with levels like Debug, Information, Warning and Error.
  • Support for custom sinks, like logging to your own external server or to a console like the roblox output and Zircon.
  • The ability to enrich logging events using EnrichWithProperty or Enrich. E.g. add the version to your logging events:
    Log.SetLogger(
        Logger.configure()
            // ...
            .EnrichWithProperty("Version", PKG_VERSION) // Will add "Version" to the event data
            // ...
            .Create()
    );
  • A global Log object, with the ability to create individual Logger objects.

Supported Sinks

Sink Name Via Information
Roblox Output Log.RobloxOutput() Built in sink which will write to the output + dev console
Zircon Zircon.Log.Console() Runtime Debugging Console for Roblox

Use with Flamework

Flamework is a very useful dependency injection transformer for roblox-ts, in which we can use @rbxts/log quite extensively like you would with regular DI.

A simple approach to the DI logging is to just use ForContext - however, this is a bit more work and more explicit.

@Service()
export class MyService {
    public readonly logger = Log.ForContext(MyService);
}

Instead, we can use the dependency resolution feature of Flamework so that we can just refer to the Logger object from the constructor :-

(e.g. in index.server.ts & index.client.ts)

import Log, { Logger } from "@rbxts/log";
Modding.registerDependency<Logger>((ctor) => {
    return Log.ForContext(ctor); // will register this under the given DI class
});

Then in our above example:

@Service()
export class MyService {
    public constructor(private readonly logger: Logger) {}
}