fix(base-driver): Update/simplify the logic for logger prefix
MODIFY
packages/base-driver/lib/basedriver/core.js
packages/base-driver/lib/basedriver/core.js
@@ -102,9 +102,9 @@ class DriverCore {
eventEmitter = new EventEmitter();
/**
- * @type {AppiumLogger?}
+ * @type {AppiumLogger}
*/
- _log = null;
+ _log;
/**
* @protected
@@ -134,6 +134,8 @@ class DriverCore {
opts = /** @type {DriverOpts} */ ({}),
shouldValidateCaps = true,
) {
+ this._log = logger.getLogger(helpers.generateDriverLogPrefix(this));
+
// setup state
this.opts = opts;
@@ -152,17 +154,6 @@ class DriverCore {
}
get log () {
- if (!this._log) {
- const instanceName = `${this.constructor.name}@${node
- .getObjectId(this)
- .substring(0, 4)}`;
- this._log = logger.getLogger(() =>
- this.sessionId
- ? `${instanceName} (${this.sessionId.substring(0, 8)})`
- : instanceName,
- );
- }
-
return this._log;
}

MODIFY
packages/base-driver/lib/basedriver/driver.js
packages/base-driver/lib/basedriver/driver.js
@@ -15,6 +15,7 @@ import {
promoteAppiumOptions
} from './capabilities';
import { createBaseDriverClass } from './commands';
+import helpers from './helpers';
const EVENT_SESSION_INIT = 'newSessionRequested';
const EVENT_SESSION_START = 'newSessionStarted';
@@ -311,6 +312,8 @@ export class BaseDriverCore extends DriverCore {
this.newCommandTimeoutMs = this.caps.newCommandTimeout * 1000;
}
+ this._log.prefix = helpers.generateDriverLogPrefix(this, this.sessionId);
+
this.log.info(`Session created with session id: ${this.sessionId}`);
return [this.sessionId, caps];
@@ -333,6 +336,7 @@ export class BaseDriverCore extends DriverCore {
}
}
this.sessionId = null;
+ this._log.prefix = helpers.generateDriverLogPrefix(this);
}
}

MODIFY
packages/base-driver/lib/basedriver/helpers.js
packages/base-driver/lib/basedriver/helpers.js
@@ -2,7 +2,7 @@ import _ from 'lodash';
import path from 'path';
import url from 'url';
import logger from './logger';
-import { tempDir, fs, util, zip, net, timing } from '@appium/support';
+import { tempDir, fs, util, zip, net, timing, node } from '@appium/support';
import LRU from 'lru-cache';
import AsyncLock from 'async-lock';
import axios from 'axios';
@@ -546,6 +546,22 @@ function parseCapsArray (cap) {
throw new Error(`must provide a string or JSON Array; received ${cap}`);
}
+/**
+ * Generate a string that uniquely describes driver instance
+ *
+ * @param {import('@appium/types').Core} obj driver instance
+ * @param {string?} sessionId session identifier (if exists)
+ * @returns {string}
+ */
+function generateDriverLogPrefix (obj, sessionId = null) {
+ const instanceName = `${obj.constructor.name}@${node.getObjectId(obj).substring(0, 4)}`;
+ return sessionId ? `${instanceName} (${sessionId.substring(0, 8)})` : instanceName;
+}
+
/** @type {import('@appium/types').DriverHelpers} */
-export default {configureApp, isPackageOrBundle, duplicateKeys, parseCapsArray};
-export {configureApp, isPackageOrBundle, duplicateKeys, parseCapsArray};
+export default {
+ configureApp, isPackageOrBundle, duplicateKeys, parseCapsArray, generateDriverLogPrefix
+};
+export {
+ configureApp, isPackageOrBundle, duplicateKeys, parseCapsArray, generateDriverLogPrefix
+};

MODIFY
packages/base-driver/test/basedriver/driver-tests.js
packages/base-driver/test/basedriver/driver-tests.js
@@ -18,6 +18,28 @@ function baseDriverUnitTests (DriverClass, defaultCaps = {}) {
});
});
+ describe('Log prefix', function () {
+
+ it('should setup log prefix', async function () {
+ const d = new DriverClass();
+ const previousPrefix = d.log.prefix;
+ await d.createSession({
+ alwaysMatch: Object.assign({}, defaultCaps, {
+ platformName: 'Fake',
+ 'appium:deviceName': 'Commodore 64',
+ }),
+ firstMatch: [{}],
+ });
+ try {
+ previousPrefix.should.not.eql(d.log.prefix);
+ } finally {
+ await d.deleteSession();
+ previousPrefix.should.eql(d.log.prefix);
+ }
+ });
+
+ });
+
describe(`BaseDriver (as ${className})`, function () {
let d, w3cCaps;

MODIFY
packages/support/lib/logging.js
packages/support/lib/logging.js
@@ -49,20 +49,20 @@ function _getLogger () {
}
/**
- * @param {Prefix} prefix
- * @param {boolean} [logTimestamp]
+ * @param {Prefix?} prefix
+ * @param {boolean} logTimestamp whether to include timestamps into log prefixes
+ * @returns {string}
*/
function getActualPrefix (prefix, logTimestamp = false) {
- let actualPrefix = _.isFunction(prefix) ? prefix() : prefix;
- if (logTimestamp) {
- actualPrefix = `[${moment().format(PREFIX_TIMESTAMP_FORMAT)}] ${actualPrefix}`;
- }
- return actualPrefix;
+ const result = (_.isFunction(prefix) ? prefix() : prefix) ?? '';
+ return logTimestamp
+ ? `[${moment().format(PREFIX_TIMESTAMP_FORMAT)}] ${result}`
+ : result;
}
/**
*
- * @param {Prefix} [prefix]
+ * @param {Prefix?} prefix
* @returns {AppiumLogger}
*/
function getLogger (prefix = null) {
@@ -71,7 +71,8 @@ function getLogger (prefix = null) {
// wrap the logger so that we can catch and modify any logging
let wrappedLogger = {
unwrap: () => logger,
- levels: NPM_LEVELS
+ levels: NPM_LEVELS,
+ prefix,
};
// allow access to the level of the underlying logger
@@ -91,7 +92,7 @@ function getLogger (prefix = null) {
// add all the levels from `npmlog`, and map to the underlying logger
for (const level of NPM_LEVELS) {
wrappedLogger[level] = function (...args) {
- const actualPrefix = getActualPrefix(prefix, logTimestamp);
+ const actualPrefix = getActualPrefix(this.prefix, logTimestamp);
for (const arg of args) {
const out = (_.isError(arg) && arg.stack) ? arg.stack : `${arg}`;
for (const line of out.split('\n')) {
@@ -154,12 +155,7 @@ export { log, patchLogger, getLogger, loadSecureValuesPreprocessingRules };
export default log;
/**
- * @callback PrefixCallback
- * @returns {string}
- */
-
-/**
- * @typedef {PrefixCallback|string?} Prefix
+ * @typedef {import('@appium/types').Prefix} Prefix
*/
/**

MODIFY
packages/types/src/index.ts
packages/types/src/index.ts
@@ -376,6 +376,7 @@ export interface DriverHelpers {
isPackageOrBundle: (app: string) => boolean;
duplicateKeys: <T>(input: T, firstKey: string, secondKey: string) => T;
parseCapsArray: (cap: string | string[]) => string[];
+ generateDriverLogPrefix: (obj: Core, sessionId?: string) => string;
}
export type SettingsUpdateListener<
@@ -492,10 +493,13 @@ export interface EventHistoryCommand {
}
export type HTTPMethod = _Method;
+export type Prefix = string|(() => string);
+
export interface AppiumLogger {
unwrap(): Logger;
level: string;
levels: string[];
+ prefix?: Prefix,
debug: (...args: any[]) => void;
info: (...args: any[]) => void;
warn: (...args: any[]) => void;

fix(base-driver): Update/simplify the logic for logger prefix (#16683)