Skip to content

Commit

Permalink
feat: create a mixin property for open telemtry and metadata support (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcdo29 authored Oct 17, 2023
2 parents 1f0673d + 5113fa3 commit a555c12
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/selfish-garlics-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ogma/logger': minor
---

Create a new `mixin` option for open telemetry and dynamic metadata support
2 changes: 1 addition & 1 deletion apps/docs/src/components/Header/OgmaLogo.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ type Props = {
const { size } = Astro.props as Props;
---

<img src="/logo.svg" alt="Ogma Logo" width={size} heigh={size}/>
<img src="/logo.svg" alt="Ogma Logo" width={size} height={size}/>
8 changes: 8 additions & 0 deletions apps/docs/src/components/RightSidebar/MoreMenu.astro
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ const showMoreSection = CONFIG.COMMUNITY_INVITE_URL;
</a>
</li>
)}
<li class={`heading-link depth-2`}>
<a href={CONFIG.GITHUB_REPO_URL} target="_blank" referrerpolicy="no-referrer">
<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<style>svg{fill:#deddda}</style>
<path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/>
</svg>
<span>View the Source Code</span></a>
</li>
</ul>
<div style="margin: 2rem 0; text-align: center;">
<ThemeToggleButton client:visible />
Expand Down
12 changes: 6 additions & 6 deletions apps/docs/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ export const SITE = {

export const OPEN_GRAPH = {
image: {
src: 'https://github.com/withastro/astro/blob/main/assets/social/banner-minimal.png?raw=true',
alt:
'astro logo on a starry expanse of space,' +
' with a purple saturn-like planet floating in the right foreground',
src: 'https://ogma.jaymcdoniel.dev/logo.svg',
alt: 'ogma logo, a blue book with a purple "O" on the cover',
},
twitter: 'jmcdo29',
};
Expand All @@ -30,11 +28,13 @@ export const KNOWN_LANGUAGES = {
} as const;
export const KNOWN_LANGUAGE_CODES = Object.values(KNOWN_LANGUAGES);

export const GITHUB_EDIT_URL = `https://github.com/jmcdo29/ogma/tree/main/apps/docs`;
export const GITHUB_REPO_URL = 'https://github.com/jmcdo29/ogma';

export const GITHUB_EDIT_URL = `${GITHUB_REPO_URL}/tree/main/apps/docs`;

export const COMMUNITY_INVITE_URL = `https://discord.gg/7cJqcFncAX`;

export const GITHUB_DISCUSSIONS_URL = `https://github.com/jmcdo29/ogma/discussions`;
export const GITHUB_DISCUSSIONS_URL = `${GITHUB_REPO_URL}/discussions`;

// See "Algolia" section of the README for more information.
export const ALGOLIA = {
Expand Down
5 changes: 5 additions & 0 deletions apps/docs/src/pages/en/logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ This option is available in `@ogma/logger@^2.5.0`
| logApplication | boolean | An optional property you can set if you don't want to the the application name. |
| logHostname | boolean | An optional property you can set if you don't want to log the hostname of the machine you're on. |
| each | boolean | An optional property that determines if array values should be printed on separate lines by default or not |
| mixin | function | A utility to add dynamic data to each log. Takes in the log level and the ogma instance and returns an object |

:::note

Expand Down Expand Up @@ -132,6 +133,10 @@ As of version 2, it is suggested to use the separate [`@ogma/styler`](/en/styler

Using the non-JSON mode, color is attempted to be applied by default. This is determined by checking the current environment (if there is a global `process` variable) and if there is, what `stdout.getColorDepth()` returns. If a custom stream is passed instead, a `getColorDepth` method can be added to the stream object which should return a 1, 4, 8, or 24. If no `getColorDepth()` is present, but the `color` option is true, Ogma will set the method to return `4` for you. If you want to disable colors completely, you can either set `color` to be `false` or you can set the `NO_COLOR` environment variable.

### Using a Mixin

There may be times, like with [OpenTelemetry](https://opentelemetry.io) or with adding a correlation id, that you need to add dynamic values to each log. Rather than making a new wrapper around the Ogma instance, Ogma provides an optional `mixin` property that can be used to add extra data to each log without being in `verbose` mode. This property is a function, that takes in the current log level and the Ogma instance, and should return an object of any shape.

## Example of what the logs look like

I said the logs were beautiful, and to me they absolutely are. Each log is matched with a timestamp in ISO format, the log level, a pipe character, and then the message, for easier searching if needed. If a JSON is passed to Ogma, a new line will separate the JSON and the original log line, but the timestamp and level will not be duplicated. Ogma also will print `'[Function]'` if a function is found or `'[Circular]'` is a circular reference is found.
Expand Down
2 changes: 1 addition & 1 deletion packages/logger/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { OgmaOptions, OgmaPrintOptions } from './interfaces';
export { OgmaDefaults, OgmaOptions, OgmaPrintOptions } from './interfaces';
export * from './logger';
11 changes: 10 additions & 1 deletion packages/logger/src/interfaces/ogma-options.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { LogLevel, OgmaStream, OgmaWritableLevel } from '@ogma/common';

import type { Ogma } from '../logger/ogma';
import { initializeStreamOnNodeJs } from '../utils/sonic-boom';

export interface OgmaOptions {
Expand Down Expand Up @@ -105,10 +106,18 @@ export interface OgmaOptions {
*/
masks?: string[];
/**
* Log each member of an array out on a new line. This is a global option tthat can be overridden per call as
* Log each member of an array out on a new line. This is a global option that can be overridden per call as
* desired.
*/
each: boolean;
/**
* A utility method to add dynamic metadata to each log.
* This method will be called __per log__ and will change regular strings
* to JSON objects in the non-json mode. This method is mostly to be used
* to accommodate OpenTelemetry, but feel free to use it for other use cases
* and ask for enhancements as necessary.
*/
mixin?: (logLevel: LogLevel, ogma: Ogma) => Record<string, unknown>;
}

const stream = process
Expand Down
25 changes: 18 additions & 7 deletions packages/logger/src/logger/ogma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,22 +117,33 @@ export class Ogma {
}

private printMessage(
message: any,
message: unknown,
logLevel: LogLevel,
formattedLevel: string,
options?: OgmaPrintOptions,
): void {
const ogmaPrintOptions = options || {};

const ogmaPrintOptions = options ?? {};
let mixin: Record<string, unknown>;
if (logLevel < LogLevel[this.options.logLevel]) {
return;
}

if (this.options.mixin) {
mixin = this.options.mixin(logLevel, this);
}

let logString = '';

if (this.options.json) {
logString = this.formatJSON(message, logLevel, ogmaPrintOptions);
logString = this.formatJSON(message, logLevel, { ...ogmaPrintOptions, ...(mixin ?? {}) });
} else {
if (mixin) {
if (typeof message === 'object') {
message = { ...message, ...mixin };
} else {
message = { message, ...mixin };
}
}
logString = this.formatStream(message, formattedLevel, ogmaPrintOptions);
}

Expand All @@ -143,7 +154,7 @@ export class Ogma {
application: _application,
correlationId: _correlationId,
...meta
} = options;
} = ogmaPrintOptions;
const verboseLogString = this.formatStream(meta, formattedLevel, ogmaPrintOptions);

this.options.stream.write(`${verboseLogString}\n`);
Expand Down Expand Up @@ -202,7 +213,7 @@ export class Ogma {
}

private formatJSON(
message: any,
message: unknown,
level: LogLevel,
{
application = this.application,
Expand Down Expand Up @@ -296,7 +307,7 @@ export class Ogma {
}

private formatStream(
message: any,
message: unknown,
formattedLevel: string,
{ application = '', correlationId = '', context = '', each = this.each }: OgmaPrintOptions,
): string {
Expand Down
50 changes: 50 additions & 0 deletions packages/logger/test/ogma.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,5 +468,55 @@ OgmaSuite('It should not explosively print array values', ({ writeSpy, ogmaFacto
ogma.log(messages, { each: true });
is(writeSpy.calls.size, 1, 'There should only be one calls');
});
OgmaSuite(
'The mixin should be called if for every log if it exists',
({ writeSpy, ogmaFactory }) => {
let val = 0;
const ogma = ogmaFactory({
mixin: () => ({ hello: `mixin ${++val}` }),
logLevel: 'DEBUG',
});
ogma.log('hello');
const expectCallToPass = (callNum: number): void => {
const expectedAddition = `"hello": "mixin ${callNum + 1}"`;
const callString = writeSpy.getCall(callNum).args[0].toString();
match(
callString,
expectedAddition,
`Expected "${callString}" to include string ${expectedAddition}`,
);
};
expectCallToPass(0);
ogma.debug({ with: 'an object' });
expectCallToPass(1);
ogma.warn({ message: 'using the message key' });
expectCallToPass(2);
writeSpy.calls.forEach((c) => console.log(c.args.join(' ')));
},
);
OgmaSuite('The mixin should be called if for every log JSON-mode', ({ writeSpy, ogmaFactory }) => {
let val = 0;
const ogma = ogmaFactory({
mixin: () => ({ hello: `mixin ${++val}` }),
logLevel: 'DEBUG',
json: true,
});
ogma.log('hello');
const expectCallToPass = (callNum: number): void => {
const expectedAddition = `"hello":"mixin ${callNum + 1}"`;
const callString = writeSpy.getCall(callNum).args[0].toString();
match(
callString,
expectedAddition,
`Expected "${callString}" to include string ${expectedAddition}`,
);
};
expectCallToPass(0);
ogma.debug({ with: 'an object' });
expectCallToPass(1);
ogma.warn({ message: 'using the message key' });
expectCallToPass(2);
writeSpy.calls.forEach((c) => console.log(c.args.join(' ')));
});

OgmaSuite.run();

0 comments on commit a555c12

Please sign in to comment.