Skip to content

Commit

Permalink
Merge pull request #876 from forcedotcom/sm/new-logger
Browse files Browse the repository at this point in the history
Sm/new logger
  • Loading branch information
iowillhoit authored Jul 27, 2023
2 parents 3956511 + 039cc19 commit 1f59ef1
Show file tree
Hide file tree
Showing 47 changed files with 2,277 additions and 4,809 deletions.
4,336 changes: 989 additions & 3,347 deletions CHANGELOG.md

Large diffs are not rendered by default.

64 changes: 64 additions & 0 deletions MIGRATING_V4-V5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Migrating `@salesforce/core` from v4 to v5

v5 contains breaking changes to the Logger class

Prior to v5, the Logger class wrapped a fork of Bunyan. v5 uses [Pino](https://getpino.io/)

You could create the Logger and then make modifications to it (adding streams, changing it to in-memory).

The v5 implementation is much simpler. Once you've created it, you cannot modify the logging destination.

This commit contains the breaking changes: https://github.com/forcedotcom/sfdx-core/commit/c52a29bd4162bc14ebaf690876db6589d21929fe

Most of the methods for manipulating streams, filter or changing the settings of an existing Logger are gone. The only change you can make to an existing Logger is to change the level or to add an additional field to all the outputs.

## MemoryLogging

instead of creating a Logger and then calling `useMemoryLogging` you can now pass the option `useMemoryLogger` when creating the Logger

## Output format

JSON is your only option. LogFmt no longer exists

## Debug

`enableDEBUG` is gone. The logger will use DEBUG and prettified output when `DEBUG=*` etc are in the environment.

## Log file destinations

Previously, logger went to sf.log and then rotated to sf.log.0, sf.log.1, etc.

The new Logger will write to dated files like `sf-2023-06-29.log` so that no rotation is necessary.

## Log file cleanup

When a new logger is instantiated, there's a chance that it kicks off a cleanup process on existing logs. By default, they'll be around 7 days. If you don't use the CLI much, it might take extra time before the log files are cleaned up (but they'd be much smaller in that case)

## Notes

the new `getRawLogger` is similar to the previous `getBunyanLogger. It'll return the underlying Pino instance.

This is an improvement in that it has TypeScript types for the pino methods. Example usage

```ts
// Logger (class) which contains the root pino logger. Will be created if one doesn't exist
// child (class) which contains a pino child logger
// return the pino logger from child class
const childLogger = Logger.childFromRoot('myRootChild', { tag: 'whatever' }).getRawLogger();
// same result, but async
const childLogger = await Logger.child('myRootChild', { tag: 'whatever' }).getRawLogger();

childLogger.debug('foo');
```

This skips all that Class instantiation and hierarchy (get the pino instance from the root Logger class and create a child logger off of that)

```ts
// Logger (class) which contains the root pino logger. Will be created if one doesn't exist
// pino child logger created from the root Logger (class) pino instance
const childLogger = Logger.getRoot().getRawLogger().child({ tag: 'whatever', name: `myRootChild` });
// same result, but async
const childLogger = (await Logger.root()).getRawLogger().child({ tag: 'whatever', name: `myRootChild` });

childLogger.debug('foo');
```
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@salesforce/core",
"version": "4.3.11",
"version": "5.0.1-v5-beta.1",
"description": "Core libraries to interact with SFDX projects, orgs, and APIs.",
"main": "lib/exported",
"types": "lib/exported.d.ts",
Expand Down Expand Up @@ -39,20 +39,21 @@
"messageTransformer/messageTransformer.ts"
],
"dependencies": {
"@salesforce/bunyan": "^2.0.0",
"@salesforce/kit": "^3.0.4",
"@salesforce/schemas": "^1.6.0",
"@salesforce/ts-types": "^2.0.2",
"@types/semver": "^7.5.0",
"ajv": "^8.12.0",
"change-case": "^4.1.2",
"debug": "^3.2.7",
"faye": "^1.4.0",
"form-data": "^4.0.0",
"js2xmlparser": "^4.0.1",
"jsforce": "^2.0.0-beta.27",
"jsonwebtoken": "9.0.1",
"jszip": "3.10.1",
"pino": "^8.14.1",
"pino-abstract-transport": "^1.0.0",
"pino-pretty": "^10.0.0",
"proper-lockfile": "^4.1.2",
"ts-retry-promise": "^0.7.0"
},
Expand All @@ -63,7 +64,6 @@
"@salesforce/ts-sinon": "^1.4.9",
"@types/benchmark": "^2.1.2",
"@types/chai-string": "^1.4.2",
"@types/debug": "0.0.31",
"@types/jsonwebtoken": "9.0.2",
"@types/lodash": "^4.14.195",
"@types/proper-lockfile": "^4.1.2",
Expand Down Expand Up @@ -174,4 +174,4 @@
]
}
}
}
}
2 changes: 1 addition & 1 deletion src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import * as fs from 'fs';
import { keyBy, parseJsonMap, set } from '@salesforce/kit';
import { Dictionary, ensure, isString, JsonPrimitive, Nullable } from '@salesforce/ts-types';
import { Global } from '../global';
import { Logger } from '../logger';
import { Logger } from '../logger/logger';
import { Messages } from '../messages';
import { validateApiVersion } from '../util/sfdc';
import { SfdcUrl } from '../util/sfdcUrl';
Expand Down
2 changes: 1 addition & 1 deletion src/config/configFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { dirname as pathDirname, join as pathJoin } from 'path';
import { isPlainObject } from '@salesforce/ts-types';
import { parseJsonMap } from '@salesforce/kit';
import { Global } from '../global';
import { Logger } from '../logger';
import { Logger } from '../logger/logger';
import { SfError } from '../sfError';
import { resolveProjectPath, resolveProjectPathSync } from '../util/internal';
import { BaseConfigStore, ConfigContents } from './configStore';
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as os from 'os';
import { join as pathJoin } from 'path';
import { ensure, Nullable, Optional } from '@salesforce/ts-types';
import { AsyncOptionalCreatable, env } from '@salesforce/kit';
import { Logger } from '../logger';
import { Logger } from '../logger/logger';
import { Messages } from '../messages';
import { Cache } from '../util/cache';
import { Global } from '../global';
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/keyChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { env } from '@salesforce/kit';
import { Logger } from '../logger';
import { Logger } from '../logger/logger';
import { Messages } from '../messages';
import { KeyChain, keyChainImpl } from './keyChainImpl';

Expand Down
2 changes: 1 addition & 1 deletion src/deviceOauthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { AsyncCreatable, Duration, parseJsonMap } from '@salesforce/kit';
import { HttpRequest, OAuth2Config } from 'jsforce';
import { ensureString, JsonMap, Nullable } from '@salesforce/ts-types';
import * as FormData from 'form-data';
import { Logger } from './logger';
import { Logger } from './logger/logger';
import { AuthInfo, DEFAULT_CONNECTED_APP_INFO, SFDX_HTTP_HEADERS } from './org';
import { SfError } from './sfError';
import { Messages } from './messages';
Expand Down
11 changes: 1 addition & 10 deletions src/exported.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,7 @@ export { SfdcUrl } from './util/sfdcUrl';

export { getJwtAudienceUrl } from './util/getJwtAudienceUrl';

export {
Fields,
FieldValue,
LoggerLevel,
LoggerLevelValue,
LogLine,
LoggerOptions,
LoggerStream,
Logger,
} from './logger';
export { Fields, FieldValue, LoggerLevel, LoggerLevelValue, LogLine, LoggerOptions, Logger } from './logger/logger';

export { Messages, StructuredMessage } from './messages';

Expand Down
7 changes: 0 additions & 7 deletions src/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,6 @@ export class Global {
return path.join(os.homedir(), Global.SFDX_STATE_FOLDER);
}

/**
* The full system path to the global log file.
*/
// member ordering conflicts with the TS use-before-declaration error
// eslint-disable-next-line @typescript-eslint/member-ordering
public static readonly LOG_FILE_PATH: string = path.join(Global.SF_DIR, 'sf.log');

/**
* Gets the current mode environment variable as a {@link Mode} instance.
*
Expand Down
14 changes: 10 additions & 4 deletions src/lifecycleEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
*/

import { AnyJson, Dictionary } from '@salesforce/ts-types';
import * as Debug from 'debug';
import { compare } from 'semver';
// needed for TS to not put everything inside /lib/src
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import * as pjson from '../package.json';
import { Logger } from './logger/logger';

// Data of any type can be passed to the callback. Can be cast to any type that is given in emit().
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -45,7 +45,7 @@ declare const global: {
export class Lifecycle {
public static readonly telemetryEventName = 'telemetry';
public static readonly warningEventName = 'warning';
private debug = Debug(`sfdx:${this.constructor.name}`);
private logger?: Logger;

private constructor(private readonly listeners: Dictionary<callback[]> = {}) {}

Expand Down Expand Up @@ -154,7 +154,10 @@ export class Lifecycle {
public on<T = AnyJson>(eventName: string, cb: (data: T) => Promise<void>): void {
const listeners = this.getListeners(eventName);
if (listeners.length !== 0) {
this.debug(
if (!this.logger) {
this.logger = Logger.childFromRoot('Lifecycle');
}
this.logger.debug(
`${
listeners.length + 1
} lifecycle events with the name ${eventName} have now been registered. When this event is emitted all ${
Expand Down Expand Up @@ -196,7 +199,10 @@ export class Lifecycle {
public async emit<T = AnyJson>(eventName: string, data: T): Promise<void> {
const listeners = this.getListeners(eventName);
if (listeners.length === 0 && eventName !== Lifecycle.warningEventName) {
this.debug(
if (!this.logger) {
this.logger = Logger.childFromRoot('Lifecycle');
}
this.logger.debug(
`A lifecycle event with the name ${eventName} does not exist. An event must be registered before it can be emitted.`
);
} else {
Expand Down
Loading

0 comments on commit 1f59ef1

Please sign in to comment.