status-im / nim-chronicles

A crafty implementation of structured logging for Nim.
Apache License 2.0
161 stars 20 forks source link

Define the Chronicle output styles as nim-serialization formats #72

Open zah opened 4 years ago

zah commented 4 years ago

Chronicles allows you to specify the style of the log output (e.g. textlines, textblocks, json, etc) as explained in the README of the library.

At the moment, the human-readable text formats (textlines and textblocks) suffer from the fact that they rely on Nim's $ operator to produce the logged strings. The user may override this by specifying a filtering function through the chronicles.formatIt API. This reliance on $ has a number of drawbacks:

1) Composite objects may be printed by Nim with characters that must be escaped within the Chronicles output (making the log reading experience less pleasant).

2) A field of an object may have a type for which a custom formatting exists (specified with formatIt), but the $ operator has no way of knowing that (the custom formatting will work only when the value of the particular type was directly used as a key = val property in a log statement).

3) Some specific types (such as Exceptions) are printed in way that's very hard to read. Ideally, the stack trace of the exception should appear as multiple indented lines following the formatted logged properties.

To solve all of these issues, it's possible to define all output types as nim-serialization formats. Please study to implementation of the JsonRecord output type as an example of this. Please note that the code is slightly less trivial due to the existing support for JavaScript compilation.

Each log statement creates a Record instance of the designated output type. Then a series of calls are executed over this instance (initLogRecord, setFirstProperty, setProperty, flushRecord) to send it to its intended destination.

After the suggested refactoring here, it's expected that there will be single generic Record type accepting as a parameter the name of a nim-serialization format. In nim-serialization, each format is associated with a Writer type created over an OutputStream. You use the writer to issue a sequence of calls (beginRecord, writeField(name, value), endRecord) that will buffer in memory the output of the log statement before it's finally sent to the screen with flushRecord(logRecord). If a composite record is passed to writeField, this may result in more recursive calls of the same nature thus implementing the arbitrary nesting possible in json.

The same mechanism should work fine for text lines and text blocks. To implement pretty-printing, the json writer maintains a counter for the current nesting level (the text blocks format can do the same). The exceptions can be buffered in a variable within the writer and appended at the end of the record in endRecord.

Once this refactoring is done, it would be possible to configure Chronicles with arbitrary nim-serialization formats. When the user specifies a sink type such as json or xml, Chronicles could try importing a package with a name such as json_serialization or xml_serialization. Within the imported module, there will be symbols such as SerializationFormat, WriterType and ReaderType. Thus, nim-serialization will become generic on the package level.

JohnAD commented 4 years ago

@zah ,

Since I'm testing and learning about the serialization and faststreams libraries anyway, I figured I'd go ahead and take on a bounty task as you suggested in another conversation. This one sounds interesting. Do you need any kind of notice when a programmer picks up on one of these projects?

zah commented 4 years ago

That's great to hear @JohnAD. Just get started and try to open an work-in-progress PR as soon as possible. I hope the description above is clear enough, but in case you need any help, don't hesitate to contact me on Gitter.

JohnAD commented 4 years ago

When I create the serializations for textLines and textBlocks, would you like those serializations stored in new libraries similar to nim-json-serialization? aka nim-textline-serialization and nim-textblock-serialization? Or would you prefer them embedded in the nim-chronicles repo?

zah commented 4 years ago

I think they will sit fine here. We are also interested only in Writers for these formats, not the full spectrum of features.