mirror of
https://github.com/appium/appium.git
synced 2026-05-03 08:51:18 -05:00
Change for #2954: add configurable log levels for different transports
This commit is contained in:
@@ -6,5 +6,5 @@
|
||||
"node": true,
|
||||
"eqeqeq": true,
|
||||
"trailing": true,
|
||||
"indent": 2
|
||||
"indent": 2
|
||||
}
|
||||
|
||||
@@ -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`|
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
@@ -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
@@ -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'], {
|
||||
|
||||
Reference in New Issue
Block a user