···172172173173See [Building A Logger](#building-a-logger) for more information.
174174175175+#### Colorizing Docker Logs
176176+177177+Color output to STD out/err is normally automatically detected by [colorette](https://github.com/jorgebucaran/colorette) or can manually be set using `colorize` anywhere [PrettyOptions](https://foxxmd.github.io/logging/interfaces/factory._internal_.PrettyOptions_.html) are accepted. However docker output can be hard to detect as supporting colorizing, or the output may not be TTY at the container interface but is viewed by a terminal or web app that does support colorizing.
178178+179179+Therefore `@foxxmd/logging` will look for a `COLORED_STD` environmental variable and, if no other `colorize` option is set _and the ENV is not empty_, will use the truthy value of this variable to set `colorize` **for any `buildDestinationStdout` or `buildDestinationStderr` transports.** This includes the built-in stdout transports for `loggerApp` and `loggerAppRolling`.
180180+181181+Thus you could set `COLORED_STD=true` in your Dockerfile to coerce colored output to docker logs. If a user does not want colored output for any reason they can simply override the environmental variable like `COLORED_STD=false`
182182+175183## Usage
176184177185### Child Loggers
···88import {destination, DestinationStream} from "pino";
99import {build, prettyFactory} from "pino-pretty"
1010import {PRETTY_OPTS_FILE, prettyOptsConsoleFactory, prettyOptsFileFactory} from "./pretty.js";
1111-import {fileOrDirectoryIsWriteable} from "./util.js";
1111+import {fileOrDirectoryIsWriteable, parseBool} from "./util.js";
1212import path from "path";
1313import {Transform, TransformCallback} from "node:stream";
1414import pump from 'pump';
···185185 }
186186}
187187188188+// docker stdout/err only colorizes if run with `-it` flag or `tty: true` in docker-compose
189189+// but most common outputs and web log viewers (portainer, dozzle) support colors and using those flags/options is not common for most users
190190+// so
191191+// can use COLORED_STD=true hint in Dockerfile to coerce colorizing output when running in a docker container.
192192+// and using this instead of FORCE_COLOR (used by colorette) so that we only affect console output instead of all streams
193193+// and value must evaluate to a truthy value to allow users to disable easily
194194+const coloredEnv = process.env.COLORED_STD;
195195+const coloredConsole = (coloredEnv === undefined || coloredEnv === '') ? undefined : parseBool(coloredEnv);
196196+const prettyColorizeEnv: {colorize?: boolean} = {};
197197+// colorette only does autodetection if `colorize` prop is not present *at all*, rather than just being undefined
198198+// so need to use default object and only add if we detect there is a non-empty value
199199+if(coloredConsole !== undefined) {
200200+ prettyColorizeEnv.colorize = coloredConsole;
201201+}
202202+188203/**
189204 * Creates a `LogLevelStreamEntry` stream that writes to STDOUT at or above the minimum `level`
190205 *
···192207 * @see buildDestinationStream
193208 * */
194209export const buildDestinationStdout = (level: LogLevel, options: Omit<StreamDestination, 'destination'> = {}): LogLevelStreamEntry => {
195195- const opts = {...options, destination: destination({dest: 1, sync: true})}
210210+ const opts = {...prettyColorizeEnv, ...options, destination: destination({dest: 1, sync: true})}
196211 return buildDestinationStream(level, opts);
197212}
198213···203218 * @see buildDestinationStream
204219 * */
205220export const buildDestinationStderr = (level: LogLevel, options: Omit<StreamDestination, 'destination'> = {}): LogLevelStreamEntry => {
206206- const opts = {...options, destination: destination({dest: 2, sync: true})};
221221+ const opts = {...prettyColorizeEnv, ...options, destination: destination({dest: 2, sync: true})};
207222 return buildDestinationStream(level, opts);
208223}
+12
src/util.ts
···6060 }
6161 return longest;
6262}
6363+6464+export function parseBool<T = undefined>(value: any, defaultVal: T = undefined): boolean | T {
6565+ if (value === undefined || value === '') {
6666+ return defaultVal
6767+ }
6868+ if (typeof value === 'string') {
6969+ return ['1','true','yes'].includes(value.toLocaleLowerCase().trim());
7070+ } else if (typeof value === 'boolean') {
7171+ return value;
7272+ }
7373+ throw new Error(`'${value.toString()}' is not a boolean value.`);
7474+}