Change for #2954: add configurable log levels for different transports

This commit is contained in:
Eric Millin
2014-09-02 14:09:46 -04:00
parent 898284cc50
commit fe2335e311
6 changed files with 145 additions and 120 deletions
+1 -1
View File
@@ -6,5 +6,5 @@
"node": true,
"eqeqeq": true,
"trailing": true,
"indent": 2
"indent": 2
}
+13 -12
View File
@@ -1,8 +1,8 @@
## Appium server arguments
# Appium server arguments
Usage: `node . [flags]`
### Server flags
## Server flags
All flags are optional, but some are required in conjunction with certain others.
@@ -15,13 +15,13 @@ All flags are optional, but some are required in conjunction with certain others
|`--localizable-strings-dir`|en.lproj|IOS only: the relative path of the dir where Localizable.strings file resides |`--localizable-strings-dir en.lproj`|
|`--app`|null|IOS: abs path to simulator-compiled .app file or the bundle_id of the desired target on device; Android: abs path to .apk file|`--app /abs/path/to/my.app`|
|`--ipa`|null|(IOS-only) abs path to compiled .ipa file|`--ipa /abs/path/to/my.ipa`|
|`-q`, `--quiet`|false|Don't use verbose logging output (deprecated, use --log-level instead)||
|`-U`, `--udid`|null|Unique device identifier of the connected physical device|`--udid 1adsf-sdfas-asdf-123sdf`|
|`-a`, `--address`|0.0.0.0|IP Address to listen on|`--address 0.0.0.0`|
|`-p`, `--port`|4723|port to listen on|`--port 4723`|
|`-ca`, `--callback-address`|(same as --address)|IP Address to use to for http callback|`--callback-address 127.0.0.1`|
|`-cp`, `--callback-port`|(same as --port)|port to use to for http callback|`--port 4723`|
|`-ca`, `--callback-address`|null|callback IP Address (default: same as address)|`--callback-address 127.0.0.1`|
|`-cp`, `--callback-port`|null|callback port (default: same as port)|`--callback-port 4723`|
|`-bp`, `--bootstrap-port`|4724|(Android-only) port to use on device to talk to Appium|`--bootstrap-port 4724`|
|`-k`, `--keep-artifacts`|false|deprecated, no effect, trace is now in tmp dir by default and is cleared before each run. Please also refer to the --trace-dir flag.||
|`-r`, `--backend-retries`|3|(iOS-only) How many times to retry launching Instruments before saying it crashed or timed out|`--backend-retries 3`|
|`--session-override`|false|Enables session override (clobbering)||
|`--full-reset`|false|(iOS) Delete the entire simulator folder. (Android) Reset app state by uninstalling app instead of clearing app data. On Android, this will also remove the app after the session is complete.||
@@ -29,7 +29,7 @@ All flags are optional, but some are required in conjunction with certain others
|`-l`, `--pre-launch`|false|Pre-launch the application before allowing the first session (Requires --app and, for Android, --app-pkg and --app-activity)||
|`-lt`, `--launch-timeout`|90000|(iOS-only) how long in ms to wait for Instruments to launch||
|`-g`, `--log`|null|Also send log output to this file|`--log /path/to/appium.log`|
|`--log-level`|debug|log level (default: debug)|`--log-level debug`|
|`--log-level`|debug|log level; default (console[:file]): debug[:debug]|`--log-level debug`|
|`--log-timestamp`|false|Show timestamps in console output||
|`--local-timezone`|false|Use local timezone for timestamps||
|`--log-no-colors`|false|Don't use colors in console output||
@@ -43,10 +43,6 @@ All flags are optional, but some are required in conjunction with certain others
|`--avd`|null|(Android-only) Name of the avd to launch|`--avd @default`|
|`--avd-args`|null|(Android-only) Additional emulator arguments to launch the avd|`--avd-args -no-snapshot-load`|
|`--device-ready-timeout`|5|(Android-only) Timeout in seconds while waiting for device to become ready|`--device-ready-timeout 5`|
|`--intent-action`|`android.intent.action.MAIN`|(Android-only) Intent action which will be used to start activity|`android.intent.action.VIEW`|
|`--intent-category`|`android.intent.category.LAUNCHER`|(Android-only) Intent category which will be used to start activity|`android.intent.category.APP_CONTACTS`|
|`--intent-flags`|`0x10200000`|(Android-only) Flags that will be used to start activity|`0x10200000`|
|`--intent-args`|null|(Android-only) Additional intent arguments that will be used to start activity. See [Intent arguments](http://developer.android.com/tools/help/adb.html#IntentSpec)|`--esn <EXTRA_KEY>`, `--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE>`|
|`--safari`|false|(IOS-Only) Use the safari app||
|`--device-name`|null|Name of the mobile device to use|`--device-name iPhone Retina (4-inch), Android Emulator`|
|`--platform-name`|null|Name of the mobile platform: iOS, Android, or FirefoxOS|`--platform-name iOS`|
@@ -61,6 +57,7 @@ All flags are optional, but some are required in conjunction with certain others
|`--calendar-format`|null|(IOS-only) calendar format for the iOS simulator|`--calendar-format gregorian`|
|`--orientation`|null|(IOS-only) use LANDSCAPE or PORTRAIT to initialize all requests to this orientation|`--orientation LANDSCAPE`|
|`--tracetemplate`|null|(IOS-only) .tracetemplate file to use with Instruments|`--tracetemplate /Users/me/Automation.tracetemplate`|
|`--show-sim-log`|false|(IOS-only) if set, the iOS simulator log will be written to the console||
|`--show-ios-log`|false|(IOS-only) if set, the iOS system log will be written to the console||
|`--nodeconfig`|null|Configuration JSON file to register appium with selenium grid|`--nodeconfig /abs/path/to/nodeconfig.json`|
|`-ra`, `--robot-address`|0.0.0.0|IP Address of robot|`--robot-address 0.0.0.0`|
@@ -69,7 +66,7 @@ All flags are optional, but some are required in conjunction with certain others
|`--chromedriver-port`|9515|Port upon which ChromeDriver will run|`--chromedriver-port 9515`|
|`--chromedriver-executable`|null|ChromeDriver executable full path||
|`--use-keystore`|false|(Android-only) When set the keystore will be used to sign apks.||
|`--keystore-path`|/Users/user/.android/debug.keystore|(Android-only) Path to keystore||
|`--keystore-path`|/Users/saucelabs/.android/debug.keystore|(Android-only) Path to keystore||
|`--keystore-password`|android|(Android-only) Password to keystore||
|`--key-alias`|androiddebugkey|(Android-only) Key alias||
|`--key-password`|android|(Android-only) Key password||
@@ -79,4 +76,8 @@ All flags are optional, but some are required in conjunction with certain others
|`--keep-keychains`|false|(iOS) Whether to keep keychains (Library/Keychains) when reset app between sessions||
|`--strict-caps`|false|Cause sessions to fail if desired caps are sent in that Appium does not recognize as valid for the selected device||
|`--tmp`|null|Absolute path to directory Appium can use to manage temporary files, like built-in iOS apps it needs to move around. On *nix/Mac defaults to /tmp, on Windows defaults to C:\Windows\Temp||
|`--trace-dir`|`<tmpDir>/appium-instruments`|Absolute path to directory Appium uses to store trace.|`--trace-dir "/tmp/directory"`|
|`--trace-dir`|null|Absolute path to directory Appium use to save ios instruments traces, defaults to <tmp dir>/appium-instruments||
|`--intent-action`|android.intent.action.MAIN|(Android-only) Intent action which will be used to start activity|`--intent-action android.intent.action.MAIN`|
|`--intent-category`|android.intent.category.LAUNCHER|(Android-only) Intent category which will be used to start activity|`--intent-category android.intent.category.APP_CONTACTS`|
|`--intent-flags`|0x10200000|(Android-only) Flags that will be used to start activity|`--intent-flags 0x10200000`|
|`--intent-args`|null|(Android-only) Additional intent arguments that will be used to start activity|`--intent-args 0x10200000`|
+1 -1
View File
@@ -432,7 +432,7 @@ IOS.prototype.setInitialOrientation = function (cb) {
IOS.prototype.configureBootstrap = function (cb) {
logger.debug("Setting bootstrap config keys/values");
var autoAcceptAlerts = !(!this.args.autoAcceptAlerts || this.args.autoAcceptAlerts === 'false');
var isVerbose = logger.appiumLoglevel === 'debug';
var isVerbose = logger.transports.console.level === 'debug';
var cmd = '';
cmd += 'target = $.target();\n';
cmd += 'au = $;\n';
+6 -1
View File
@@ -231,7 +231,12 @@ module.exports.startListening = function (server, args, parser, appiumVer, appiu
if (_.size(deprecatedArgs)) {
logger.warn("Deprecated server args: " + JSON.stringify(deprecatedArgs));
}
logger.info('LogLevel:', logger.appiumLoglevel);
logger.info('Console LogLevel: ' + logger.transports.console.level);
if (logger.transports.file) {
logger.info('File LogLevel: ' + logger.transports.file.level);
}
});
server.on('error', function (err) {
if (err.code === 'EADDRNOTAVAIL') {
+116 -92
View File
@@ -1,8 +1,10 @@
"use strict";
var winston = require('winston');
var winston = require('winston'),
fs = require('fs');
require('date-utils');
var levels = {
debug: 1
, info: 2
@@ -18,108 +20,130 @@ var colors = {
};
var logger = null;
var serverArgs = null;
var timeZone = null;
var timestamp = function () {
var date = new Date();
if (!serverArgs.localTimezone) {
if (!timeZone) {
date = new Date(date.valueOf() + date.getTimezoneOffset() * 60000);
}
return date.toFormat("YYYY-MM-DD HH24:MI:SS:LL");
};
module.exports.init = function (args) {
serverArgs = args;
var loglevel = args.logLevel ? args.logLevel :
(args.quiet ? 'warn' : 'debug');
winston.addColors(colors);
winston.loggers.add('appium', {
console: {
timestamp: args.logTimestamp ? timestamp : false
, colorize: args.logNoColors ? false : true
, handleExceptions: true
, exitOnError: false
, json: false
, level: loglevel
}
});
logger = winston.loggers.get('appium');
logger.setLevels(levels);
logger.stripColors = args.logNoColors;
logger.appiumLoglevel = loglevel;
// 8/19/14 this is a hack to force Winston to print debug messages to stdout rather than stderr.
// TODO: remove this if winston provides an API for directing streams.
if (levels[loglevel] === levels.debug) {
logger.debug = function (msg) { logger.info('[debug] ' + msg); };
}
var fileLogger = null;
if (args.log) {
try {
winston.loggers.add('appium-file', {
file: {
timestamp: timestamp
, colorize: false
, filename: args.log
, maxFiles: 1
, level: loglevel
, handleExceptions: true
, exitOnError: false
, json: false
}
}
);
fileLogger = winston.loggers.get('appium-file');
fileLogger.setLevels(levels);
fileLogger.stripColors = true;
} catch (e) {
logger.debug("Tried to attach logging to file " + args.log +
" but an error occurred");
}
}
var webhookLogger = null;
if (args.webhook) {
var host = args.webhook;
var port = 9003;
if (host.indexOf(':') > -1) {
try {
host = host.substring(0, host.indexOf(':'));
port = args.webhook.substring(args.webhook.indexOf(':') + 1);
port = parseInt(port, 10);
} catch (e) {
}
}
host = host || '127.0.0.1';
port = port || 9003;
try {
winston.loggers.add('appium-webhook', { webhook: {
host: host
, port: port
, path: '/'
, level: loglevel
, handleExceptions: true
, exitOnError: false
, json: false
}
});
webhookLogger = winston.loggers.get('appium-webhook');
webhookLogger.setLevels(levels);
webhookLogger.stripColors = true;
} catch (e) {
logger.debug("Tried to attach logging to webhook at " + host +
" but an error occurred");
}
}
logger.on('logging', function (transport, level, msg, meta) {
if (fileLogger) fileLogger.log(level, msg, meta);
if (webhookLogger) webhookLogger.log(level, msg, meta);
var _createConsoleTransport = function (args, logLvl) {
return new (winston.transports.Console)({
name: "console"
, timestamp: args.logTimestamp ? timestamp : undefined
, colorize: !args.logNoColors
, handleExceptions: true
, exitOnError: false
, json: false
, level: logLvl
});
};
var _createFileTransport = function (args, logLvl) {
return new (winston.transports.File)({
name: "file"
, timestamp: timestamp
, filename: args.log
, maxFiles: 1
, handleExceptions: true
, exitOnError: false
, json: false
, level: logLvl
}
);
};
var _createWebhookTransport = function (args, logLvl) {
var host = null,
port = null;
if (args.webhook.match(':')) {
var hostAndPort = args.webhook.split(':');
host = hostAndPort[0];
port = parseInt(hostAndPort[1], 10);
}
return new (winston.transports.Webhook)({
name: "webhook"
, host: host || '127.0.0.1'
, port: port || 9003
, path: '/'
, handleExceptions: true
, exitOnError: false
, json: false
, level: logLvl
});
};
var _createTransports = function (args) {
var transports = [];
var consoleLogLevel = null,
fileLogLevel = null;
if (args.loglevel && args.loglevel.match(":")) {
// --log-level arg can optionally provide diff logging levels for console and file separated by a colon
var lvlPair = args.loglevel.split(':');
consoleLogLevel = lvlPair[0] || consoleLogLevel;
fileLogLevel = lvlPair[1] || fileLogLevel;
} else {
consoleLogLevel = fileLogLevel = args.loglevel;
}
transports.push(_createConsoleTransport(args, consoleLogLevel));
if (args.log) {
try {
// if we don't delete the log file, winston will always append and it will grow infinitely large;
// winston allows for limiting log file size, but as of 9.2.14 there's a serious bug when using
// maxFiles and maxSize together. https://github.com/flatiron/winston/issues/397
if (fs.existsSync(args.log)) {
fs.unlinkSync(args.log);
}
transports.push(_createFileTransport(args, fileLogLevel));
} catch (e) {
console.log("Tried to attach logging to file " + args.log +
" but an error occurred: " + e.msg);
}
}
if (args.webhook) {
try {
transports.push(_createWebhookTransport(args, fileLogLevel));
} catch (e) {
console.log("Tried to attach logging to webhook at " + args.webhook +
" but an error occurred. " + e.msg);
}
}
return transports;
};
module.exports.init = function (args) {
// set de facto param passed to timestamp function
timeZone = args.localTimezone;
// by not adding colors here and not setting 'colorize' in transports
// when logNoColors === true, console output is fully stripped of color.
if (!args.logNoColors) {
winston.addColors(colors);
}
logger = new (winston.Logger)({
transports: _createTransports(args)
});
logger.setLevels(levels);
// 8/19/14 this is a hack to force Winston to print debug messages to stdout rather than stderr.
// TODO: remove this if winston provides an API for directing streams.
if (levels[logger.transports.console.level] === levels.debug) {
logger.debug = function (msg) { logger.info('[debug] ' + msg); };
}
};
module.exports.get = function () {
if (logger === null) {
+8 -13
View File
@@ -34,14 +34,6 @@ var args = [
, example: "/abs/path/to/my.ipa"
}],
[['-q', '--quiet'], {
required: false
, defaultValue: false
, action: 'storeTrue'
, help: "Don't use verbose logging output (deprecated, use --log-level instead)"
, nargs: 0
}],
[['-U', '--udid'], {
required: false
, defaultValue: null
@@ -159,19 +151,22 @@ var args = [
[['-g', '--log'], {
defaultValue: null
, dest: 'log'
, required: false
, example: "/path/to/appium.log"
, help: 'Also send log output to this file'
}],
[['--log-level'], {
choices: ['debug','info','warn', 'error']
// TODO: enable this once we got rid of --quiet
//, defaultValue: 'info'
, dest: 'logLevel'
choices: [ 'info', 'info:debug', 'info:info', 'info:warn', 'info:error'
, 'warn', 'warn:debug', 'warn:info', 'warn:warn', 'warn:error'
, 'error', 'error:debug', 'error:info', 'error:warn', 'error:error'
, 'debug', 'debug:debug', 'debug:info', 'debug:warn', 'debug:error']
, defaultValue: 'debug'
, dest: 'loglevel'
, required: false
, example: "debug"
, help: 'log level (default: debug)'
, help: 'log level; default (console[:file]): debug[:debug]'
}],
[['--log-timestamp'], {