Skip to content

Commit 665e941

Browse files
authored
Merge pull request #171 from kevintechie/feature-rawIsoStr
adding placeholder to render raw ISO date string
2 parents edb5edd + db3cb83 commit 665e941

File tree

4 files changed

+101
-86
lines changed

4 files changed

+101
-86
lines changed

README.md

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313
> Powerful, fast and expressive logging for TypeScript and JavaScript
14-
14+
1515
![tslog pretty output](https://raw.githubusercontent.com/fullstack-build/tslog/master/docs/assets/tslog.png "tslog pretty output in browser and Node.js")
1616

1717

@@ -49,13 +49,13 @@ Donations help me allocate more time for my open source work.
4949

5050
## Install
5151

52-
> **`tslog` is a native ES module.**
52+
> **`tslog` is a native ES module.**
5353
5454
```bash
5555
npm install tslog
5656
```
5757

58-
In order to run a native ES module in Node.js, you have to do two things:
58+
In order to run a native ES module in Node.js, you have to do two things:
5959

6060
1) Set `"type": "module"` in `package.json`.
6161
2) For now, start with `--experimental-specifier-resolution=node`
@@ -180,21 +180,21 @@ logger.fatal(new Error("I am a pretty Error with a stacktrace."));
180180

181181
## API documentation
182182

183-
> **`tslog >= v4` is a major rewrite and introduces breaking changes.** <br>
184-
> Please, follow this documentation when migrating.
183+
> **`tslog >= v4` is a major rewrite and introduces breaking changes.** <br>
184+
> Please, follow this documentation when migrating.
185185
186186
### <a name="life_cycle"></a>Lifecycle of a log message
187187

188-
Every incoming log message runs through a number of steps before being displayed or handed over to a "transport". Every step can be overwritten and adjusted.
188+
Every incoming log message runs through a number of steps before being displayed or handed over to a "transport". Every step can be overwritten and adjusted.
189189

190190
![tslog pretty output](https://raw.githubusercontent.com/fullstack-build/tslog/master/docs/assets/tslog_lifesycle.png "tslog: life cycle of a log message")
191191

192192
- **log message** Log message comes in through the `BaseLogger.log()` method
193193
- **mask** If masking is configured, log message gets recursively masked
194-
- **toLogObj** Log message gets transformed into a log object: A default typed log object can be passed to constructor as a second parameter and will be cloned and enriched with the incoming log parameters. Error properties will be handled accordingly. If there is only one log property, and it's an object, both objects (cloned default `logObj` as well as the log property object) will be merged. If there are more than one, they will be put into properties called "0", "1", ... and so on. Alternatively, log message properties can be put into a property with a name configured with the `argumentsArrayName` setting.
194+
- **toLogObj** Log message gets transformed into a log object: A default typed log object can be passed to constructor as a second parameter and will be cloned and enriched with the incoming log parameters. Error properties will be handled accordingly. If there is only one log property, and it's an object, both objects (cloned default `logObj` as well as the log property object) will be merged. If there are more than one, they will be put into properties called "0", "1", ... and so on. Alternatively, log message properties can be put into a property with a name configured with the `argumentsArrayName` setting.
195195
- **addMetaToLogObj** Additional meta information, like the source code position of the log will be gathered and added to the `_meta` property or any other one configured with the setting `metaProperty`.
196-
- **format** In case of "pretty" configuration, a log object will be formatted based on the templates configured in settings. Meta will be formatted by the method `_prettyFormatLogObjMeta` and the actual log payload will be formatted by `prettyFormatLogObj`. Both steps can be overwritten with the settings `formatMeta` and `formatMeta`.
197-
- **transport** Last step is to "transport" a log message to every attached transport from the setting `attachedTransports`. Last step is the actual transport, either JSON (`transportJSON`), formatted (`transportFormatted`) or omitted, if its set to "hidden". Both default transports can also be overwritten by the corresponding setting.
196+
- **format** In case of "pretty" configuration, a log object will be formatted based on the templates configured in settings. Meta will be formatted by the method `_prettyFormatLogObjMeta` and the actual log payload will be formatted by `prettyFormatLogObj`. Both steps can be overwritten with the settings `formatMeta` and `formatMeta`.
197+
- **transport** Last step is to "transport" a log message to every attached transport from the setting `attachedTransports`. Last step is the actual transport, either JSON (`transportJSON`), formatted (`transportFormatted`) or omitted, if its set to "hidden". Both default transports can also be overwritten by the corresponding setting.
198198

199199
### Default log level
200200

@@ -245,16 +245,16 @@ export class CustomLogger<LogObj> extends BaseLogger<LogObj> {
245245
```
246246

247247
### Settings
248-
`tslog` is highly customizable and pretty much every aspect can be either configured or overwritten.
248+
`tslog` is highly customizable and pretty much every aspect can be either configured or overwritten.
249249
A `settings` object is the first parameter passed to the `tslog` constructor:
250250

251-
```typescript
251+
```typescript
252252
const logger = new Logger<ILogObj>({ /* SETTINGS */ }, defaultLogObject);
253253
```
254254

255255
#### Type: pretty, json, hidden
256256

257-
- `pretty` **Default setting** prints out a formatted structured "pretty" log entry.
257+
- `pretty` **Default setting** prints out a formatted structured "pretty" log entry.
258258
- `json` prints out a `JSON` formatted log entry.
259259
- `hidden` suppresses any output whatsoever and can be used with attached loggers for example.
260260

@@ -275,16 +275,16 @@ const hiddenLogger = new Logger({type: "hidden"});
275275

276276
#### name
277277

278-
Each logger has an optional name.
279-
You can find the name of the logger responsible for a log inside the `Meta`-object or printed in `pretty` mode.
280-
Names get also inherited to sub loggers and can be found inside the `Meta`-object `parentNames` as well as printed out with a separator (e.g. `:`) in `pretty` mode.
278+
Each logger has an optional name.
279+
You can find the name of the logger responsible for a log inside the `Meta`-object or printed in `pretty` mode.
280+
Names get also inherited to sub loggers and can be found inside the `Meta`-object `parentNames` as well as printed out with a separator (e.g. `:`) in `pretty` mode.
281281

282282
Simple name example:
283283
```typescript
284284
new Logger({ name: "myLogger" });
285285
```
286286

287-
Sub-loggers with an inherited name:
287+
Sub-loggers with an inherited name:
288288
```typescript
289289
const mainLogger = new Logger({ type: "pretty", name: "MainLogger" });
290290
mainLogger.silly("foo bar");
@@ -296,7 +296,7 @@ const secondSubLogger = firstSubLogger.getSubLogger({ name: "SecondSubLogger" })
296296
secondSubLogger.silly("foo bar 2");
297297
```
298298

299-
Output:
299+
Output:
300300
```bash
301301
2022-11-17 10:45:47.705 SILLY [/examples/nodejs/index2.ts:51 MainLogger] foo bar
302302
2022-11-17 10:45:47.706 SILLY [/examples/nodejs/index2.ts:54 MainLogger:FirstSubLogger] foo bar 1
@@ -318,7 +318,7 @@ suppressSilly.trace("Will be visible");
318318

319319
#### argumentsArrayName
320320

321-
`tslog` < 4 wrote all parameters into an arguments array. In `tslog` >= 4 the main object becomes home for all log parameters, and they get merged with the default `logObj`.
321+
`tslog` < 4 wrote all parameters into an arguments array. In `tslog` >= 4 the main object becomes home for all log parameters, and they get merged with the default `logObj`.
322322
If you still want to put them into a separated parameter, you can do so by defining the `argumentsArrayName`.
323323

324324
```typescript
@@ -344,7 +344,7 @@ Enables you to overwrite the looks of a formatted _"pretty"_ log message by prov
344344
Following settings are available for styling:
345345

346346
- **Templates:**
347-
- `prettyLogTemplate`: template string for log messages. Possible placeholders:
347+
- `prettyLogTemplate`: template string for log messages. Possible placeholders:
348348
- `{{yyyy}}`: year
349349
- `{{mm}}`: month
350350
- `{{dd}}`: day
@@ -353,31 +353,32 @@ Following settings are available for styling:
353353
- `{{ss}}`: seconds
354354
- `{{ms}}`: milliseconds
355355
- `{{dateIsoStr}}`: Shortcut for `{{yyyy}}.{{mm}}.{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}}`
356+
- `{{rawIsoStr}}`: Renders the date and time in ISO format (e.g.: YYYY-MM-DDTHH:mm:ss.SSSZ)
356357
- `{{logLevelName}}`: name of the log level
357358
- `{{name}}`: optional name of the current logger and his parents (e.g. "ParentLogger:ThisLogger")
358359
- `{{fullFilePath}}`: a full path starting from `/` root
359360
- `{{filePathWithLine}}`: a full path below the project path with line number
360361
- `prettyErrorTemplate`: template string for error message. Possible placeholders:
361362
- `{{errorName}}`: name of the error
362363
- `{{errorMessage}}`: error message
363-
- `{{errorStack}}`: Placeholder for all stack lines defined by `prettyErrorStackTemplate`
364+
- `{{errorStack}}`: Placeholder for all stack lines defined by `prettyErrorStackTemplate`
364365
- `prettyErrorStackTemplate`: template string for error stack trace lines. Possible placeholders:
365366
- `{{fileName}}`: name of the file
366367
- `{{filePathWithLine}}`: a full path below the project path with a line number
367368
- `{{method}}`: _optional_ name of the invoking method
368369
- `prettyErrorParentNamesSeparator`: separator to be used when joining names ot the parent logger, and the current one (default: `:`)
369370
- `prettyInspectOptions`: <a href="https://nodejs.org/api/util.html#utilinspectobject-options" target="_blank">Available options</a>
370-
371+
371372
- **Styling:**
372373
- `stylePrettyLogs`: defines whether logs should be styled and colorized
373374
- `prettyLogStyles`: provides colors and styles for different placeholders and can also be dependent on the value (e.g. log level)
374375
- Level 1: template placeholder (defines a style for a certain template placeholder, s. above, without brackets).
375-
- Level 2: Either a string with one style (e.g. `white`), or an array of styles (e.g. `["bold", "white"]`), or a nested object with key being a value.
376+
- Level 2: Either a string with one style (e.g. `white`), or an array of styles (e.g. `["bold", "white"]`), or a nested object with key being a value.
376377
- Level 3: Optional nested style based on placeholder values. Key is the value of the template placeholder and value is either a string of a style, or an array of styles (s. above), e.g. `{ SILLY: ["bold", "white"] }` which means: value "SILLY" should get a style of "bold" and "white". `*` means any value other than the defined.
377378
- `prettyInspectOptions`: When a (potentially nested) object is printed out in Node.js, we use `util.formatWithOptions` under the hood. With `prettyInspectOptions` you can define the output. [Possible values](https://nodejs.org/api/util.html#utilinspectobject-showhidden-depth-colors)
378379

379380
#### Log meta information
380-
`tslog` collects meta information for every log, like runtime, code position etc. The meta information collected depends on the runtime (browser or Node.js) and is accessible through the `LogObj`.
381+
`tslog` collects meta information for every log, like runtime, code position etc. The meta information collected depends on the runtime (browser or Node.js) and is accessible through the `LogObj`.
381382
You can define the property containing this meta information with `metaProperty`, which is "_meta" by default.
382383

383384
#### Pretty templates and styles (color settings)
@@ -467,7 +468,7 @@ like sending messages to _Slack_ or _Telegram_ in case of an urgent error or for
467468

468469
##### Simple transport example
469470

470-
Here is a very simple implementation used in our _jest_ tests.
471+
Here is a very simple implementation used in our _jest_ tests.
471472
This example will suppress logs from being sent to `console` (`type: "hidden"`) and will instead collect them in an `array`.
472473

473474
```typescript
@@ -502,10 +503,10 @@ logger.warn("I am a warn log with a json object:", { foo: "bar" });
502503

503504
##### Storing logs in a file system with rotating files
504505

505-
If you want to limit the file size of the stored logs, a good practice is to use file rotation, where old logs will be deleted automatically.
506+
If you want to limit the file size of the stored logs, a good practice is to use file rotation, where old logs will be deleted automatically.
506507
There is a great library called `rotating-file-stream` solving this problem for us and even adding features like compression, file size limit etc.
507508

508-
1. First you need to install this library:
509+
1. First you need to install this library:
509510
```bash
510511
npm i rotating-file-stream
511512
```
@@ -533,7 +534,7 @@ logger.warn("I am a warn log with a json object:", { foo: "bar" });
533534

534535
```
535536

536-
#### Overwriting default behavior
537+
#### Overwriting default behavior
537538

538539
One of the key advantages of `tslog` >= 4 is that you can overwrite pretty much every aspect of the log processing described in <a href="#life_cycle">"Lifecycle of a log message"</a>.
539540

@@ -567,7 +568,7 @@ For `pretty` logs:
567568
// format LogObj attributes to a string and return it
568569
},
569570
transportFormatted: (logMetaMarkup: string, logArgs: unknown[], logErrors: string[], settings: unknown) => {
570-
// overwrite the default transport for formatted (e.g. pretty) log levels. e.g. replace console with StdOut, write to file etc.
571+
// overwrite the default transport for formatted (e.g. pretty) log levels. e.g. replace console with StdOut, write to file etc.
571572
},
572573
},
573574
});
@@ -590,7 +591,7 @@ As described in <a href="#life_cycle">"Lifecycle of a log message"</a>, every lo
590591
A default logObj can be passed to the `tslog` constructor and will be cloned and merged into the log message. This makes `tslog` >= 4 highly configurable and easy to integrate into any 3rd party service.
591592
The entire `logObj` will be printed out in `JSON` mode and also returned by every log method.
592593

593-
> **Tip:** All properties of the default `LogObj` containing function calls will be executed for every log message making use cases possible like `requestId` (s. below).
594+
> **Tip:** All properties of the default `LogObj` containing function calls will be executed for every log message making use cases possible like `requestId` (s. below).
594595
595596
```typescript
596597
interface ILogObj {
@@ -602,7 +603,7 @@ const defaultLogObject: ILogObj = {
602603
};
603604

604605
const logger = new Logger<ILogObj>({ type: "json" }, defaultLogObject);
605-
const logMsg = logger.info("Test");
606+
const logMsg = logger.info("Test");
606607

607608
// logMsg: {
608609
// '0': 'Test',
@@ -648,24 +649,24 @@ Some providers (e.g. `Heroku`) already set a `X-Request-ID` header, which we are
648649
import Koa from "koa";
649650
import { customAlphabet } from "nanoid";
650651
import { Logger } from "tslog";
651-
652+
652653
interface ILogObj {
653654
requestId?: string | (() => string | undefined);
654655
}
655-
656+
656657
const asyncLocalStorage: AsyncLocalStorage<{ requestId: string }> = new AsyncLocalStorage();
657-
658+
658659
const defaultLogObject: ILogObj = {
659660
requestId: () => asyncLocalStorage.getStore()?.requestId,
660661
};
661-
662+
662663
const logger = new Logger<ILogObj>({ type: "json" }, defaultLogObject);
663664
export { logger };
664-
665+
665666
logger.info("Test log without requestId");
666-
667+
667668
const koaApp = new Koa();
668-
669+
669670
/** START AsyncLocalStorage requestId middleware **/
670671
koaApp.use(async (ctx: Koa.Context, next: Koa.Next) => {
671672
// use x-request-id or fallback to a nanoid
@@ -676,21 +677,21 @@ Some providers (e.g. `Heroku`) already set a `X-Request-ID` header, which we are
676677
});
677678
});
678679
/** END AsyncLocalStorage requestId middleware **/
679-
680+
680681
// example middleware
681682
koaApp.use(async (ctx: Koa.Context, next) => {
682-
683+
683684
// log request
684685
logger.silly({ originalUrl: ctx.originalUrl, status: ctx.response.status, message: ctx.response.message });
685-
686+
686687
// also works with a sub logger
687688
const subLogger = logger.getSubLogger();
688689
subLogger.info("Log containing requestId"); // <-- will contain a requestId
689-
690+
690691
return await next();
691692
});
692-
693+
693694
koaApp.listen(3000);
694-
695+
695696
logger.info("Server running on port 3000");
696697
```

0 commit comments

Comments
 (0)