docs: add structured logging docs in code formatting rules doc

This commit is contained in:
Elle Mouton committed 2024-12-02 09:23:06 +02:00
1 parent a04f8dfd4f
commit efe08b836e
1 file changed
+89
+89
View File
@@ -178,6 +178,95 @@ be used for calls to formatting functions like `fmt.Errorf`,
But not for statements that are important for the flow or logic of the code, But not for statements that are important for the flow or logic of the code,
like `require.NoErrorf()`. like `require.NoErrorf()`.
#### Exceptions and additional styling for structured logging
When making use of structured logging calls (there are any `btclog.Logger`
methods ending in `S`), a few different rules and exceptions apply.
1) **Static messages:** Structured log calls take a `context.Context` as a first
parameter and a _static_ string as the second parameter (the `msg` parameter).
Formatted strings should ideally not be used for the construction of the `msg`
parameter. Instead, key-value pairs (or `slog` attributes) should be used to
provide additional variables to the log line.
**WRONG**
```go
log.DebugS(ctx, fmt.Sprintf("User %d just spent %.8f to open a channel", userID, 0.0154))
```
**RIGHT**
```go
log.InfoS(ctx, "Channel open performed",
slog.Int("user_id", userID),
btclog.Fmt("amount", "%.8f", 0.00154))
```
2) **Key-value attributes**: The third parameter in any structured log method is
a variadic list of the `any` type but it is required that these are provided in
key-value pairs such that an associated `slog.Attr` variable can be created for
each key-value pair. The simplest way to specify this is to directly pass in the
key-value pairs as raw literals as follows:
```go
log.InfoS(ctx, "Channel open performed", "user_id", userID, "amount", 0.00154)
```
This does work, but it becomes easy to make a mistake and accidentally leave out
a value for each key provided leading to a nonsensical log line. To avoid this,
it is suggested to make use of the various `slog.Attr` helper functions as
follows:
```go
log.InfoS(ctx, "Channel open performed",
slog.Int("user_id", userID),
btclog.Fmt("amount", "%.8f", 0.00154))
```
3) **Line wrapping**: Structured log lines are an exception to the 80-character
line wrapping rule. This is so that the key-value pairs can be easily read and
reasoned about. If it is the case that there is only a single key-value pair
and the entire log line is still less than 80 characters, it is acceptable to
have the key-value pair on the same line as the log message. However, if there
are multiple key-value pairs, it is suggested to use the one line per key-value
pair format. Due to this suggestion, it is acceptable for any single key-value
pair line to exceed 80 characters for the sake of readability.
**WRONG**
```go
// Example 1.
log.InfoS(ctx, "User connected",
"user_id", userID)
// Example 2.
log.InfoS(ctx, "Channel open performed", "user_id", userID,
btclog.Fmt("amount", "%.8f", 0.00154), "channel_id", channelID)
// Example 3.
log.InfoS(ctx, "Bytes received",
"user_id", userID,
btclog.Hex("peer_id", peerID.SerializeCompressed()),
btclog.Hex("message", []bytes{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
})))
```
**RIGHT**
```go
// Example 1.
log.InfoS(ctx, "User connected", "user_id", userID)
// Example 2.
log.InfoS(ctx, "Channel open performed",
slog.Int("user_id", userID),
btclog.Fmt("amount", "%.8f", 0.00154),
slog.String("channel_id", channelID))
// Example 3.
log.InfoS(ctx, "Bytes received",
"user_id", userID,
btclog.Hex("peer_id", peerID.SerializeCompressed()),
btclog.Hex("message", []bytes{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08})))
```
### Wrapping long function definitions ### Wrapping long function definitions
If one is forced to wrap lines of function arguments that exceed the If one is forced to wrap lines of function arguments that exceed the