Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Update console and network log handlers #2421

Merged
merged 13 commits into from
Jul 2, 2024
2 changes: 2 additions & 0 deletions docs/reference/capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ about capabilities, refer to the [Appium documentation](https://appium.io/docs/e
|`appium:autoWebview`| Move directly into Webview context if available. Default `false`|`true`, `false`|
|`appium:skipTriggerInputEventAfterSendkeys`| If this capability is set to `true`, then whenever you call the Send Keys method in a web context, the driver will not fire an additional `input` event on the input field used for the call. This event, turned on by default, helps in situations where JS frameworks (like React) do not respond to the input events that occur by default when the underlying Selenium atom is executed. Default `false`|`true`, `false`|
|`appium:sendKeyStrategy`| If this capability is set to `oneByOne`, then whenever you call the Send Keys method in a web context, the driver will type each character the given string consists of in serial order to the element. This strategy helps in situations where JS frameworks (like React) update the view for each input. If `appium:skipTriggerInputEventAfterSendkeys` capability is `true`, it will affect every type. For example, when you are going to type the word `appium` with `oneByOne` strategy and `appium:skipTriggerInputEventAfterSendkeys` is enabled, the `appium:skipTriggerInputEventAfterSendkeys` option affects each typing action: `a`, `p`, `p`,`i`, `u` and `m`. Suppose any other value or no value has been provided to the `appium:sendKeyStrategy` capability. In that case, the driver types the given string in the destination input element. `appium` Send Keys input types `appium` if `oneByOne` was not set. |`oneByOne`|
|`appium:showSafariConsoleLog`| Adds Safari JavaScript console events to Appium server logs and writes fully serialized events into the `safariConsole` logs bucket. Default `false`|`true`, `false`|
|`appium:showSafariNetworkLog`| Adds Safari network events to Appium server logs and writes fully serialized events into the `safariNetwork` logs bucket. Default `false`|`true`, `false`|

### Other

Expand Down
4 changes: 2 additions & 2 deletions lib/commands/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -569,12 +569,12 @@ const commands = {
if (name && name !== NATIVE_WIN && this.logs) {
if (this.logs.safariConsole) {
await this.remote.startConsole(
this.logs.safariConsole.addLogLine.bind(this.logs.safariConsole),
this.logs.safariConsole.onConsoleLogEvent.bind(this.logs.safariConsole),
);
}
if (this.logs.safariNetwork) {
await this.remote.startNetwork(
this.logs.safariNetwork.addLogLine.bind(this.logs.safariNetwork),
this.logs.safariNetwork.onNetworkEvent.bind(this.logs.safariNetwork),
);
}
}
Expand Down
23 changes: 13 additions & 10 deletions lib/commands/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,23 +98,28 @@ export default {
sim: this.device,
udid: this.isRealDevice() ? this.opts.udid : undefined,
});

if (this.isRealDevice()) {
this.logs.syslog = new IOSDeviceLog({
this.logs.syslog = this.isRealDevice()
? new IOSDeviceLog({
udid: this.opts.udid,
showLogs: this.opts.showIOSLog,
log: this.log,
});
} else {
this.logs.syslog = new IOSSimulatorLog({
})
: new IOSSimulatorLog({
sim: /** @type {import('appium-ios-simulator').Simulator} */ (this.device),
showLogs: this.opts.showIOSLog,
iosSimulatorLogsPredicate: this.opts.iosSimulatorLogsPredicate,
log: this.log,
});
if (this.opts.showSafariConsoleLog) {
mykola-mokhnach marked this conversation as resolved.
Show resolved Hide resolved
this.logs.safariConsole = new SafariConsoleLog({
log: this.log,
});
}
if (this.opts.showSafariNetworkLog) {
this.logs.safariNetwork = new SafariNetworkLog({
log: this.log,
});
}
this.logs.safariConsole = new SafariConsoleLog(!!this.opts.showSafariConsoleLog);
this.logs.safariNetwork = new SafariNetworkLog(!!this.opts.showSafariNetworkLog);
}

let didStartSyslog = false;
Expand All @@ -130,8 +135,6 @@ export default {
}
})(),
this.logs.crashlog.startCapture(),
this.logs.safariConsole.startCapture(),
this.logs.safariNetwork.startCapture(),
];
await B.all(promises);

Expand Down
6 changes: 3 additions & 3 deletions lib/device-log/ios-device-log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import type { AppiumLogger } from '@appium/types';
export interface IOSDeviceLogOpts {
udid: string;
showLogs?: boolean;
log?: AppiumLogger;
log: AppiumLogger;
}

export class IOSDeviceLog extends LineConsumingLog {
private udid: string;
private showLogs: boolean;
private readonly udid: string;
private readonly showLogs: boolean;
private service: any | null;

constructor(opts: IOSDeviceLogOpts) {
Expand Down
26 changes: 13 additions & 13 deletions lib/device-log/ios-log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,6 @@ export abstract class IOSLog<
return this._log;
}

broadcast(entry: TRawEntry): void {
let recentIndex = -1;
for (const key of this.logs.rkeys()) {
recentIndex = key;
break;
}
const serializedEntry = this._serializeEntry(entry);
this.logs.set(++recentIndex, serializedEntry);
if (this.listenerCount('output')) {
this.emit('output', this._deserializeEntry(serializedEntry));
}
}

getLogs(): LogEntry[] {
const result: LogEntry[] = [];
let recentLogIndex: number | null = null;
Expand Down Expand Up @@ -82,6 +69,19 @@ export abstract class IOSLog<
protected _clearEntries() {
this.logs.clear();
}

protected broadcast(entry: TRawEntry): void {
let recentIndex = -1;
for (const key of this.logs.rkeys()) {
recentIndex = key;
break;
}
const serializedEntry = this._serializeEntry(entry);
this.logs.set(++recentIndex, serializedEntry);
if (this.listenerCount('output')) {
this.emit('output', this._deserializeEntry(serializedEntry));
}
}
}

export default IOSLog;
28 changes: 9 additions & 19 deletions lib/device-log/ios-performance-log.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import _ from 'lodash';
import { IOSLog } from './ios-log';
import type { LogEntry } from '../commands/types';
import type { AppiumLogger } from '@appium/types';
import { LineConsumingLog } from './line-consuming-log';

const MAX_EVENTS = 5000;

type PerformanceLogEntry = object;
export interface IOSPerformanceLogOptions {
remoteDebugger: any;
maxEvents?: number;
log?: AppiumLogger;
log: AppiumLogger;
}

export class IOSPerformanceLog extends IOSLog<PerformanceLogEntry, PerformanceLogEntry> {
private remoteDebugger: any;
export class IOSPerformanceLog extends LineConsumingLog {
private readonly remoteDebugger: any;
private _started: boolean;

constructor(opts: IOSPerformanceLogOptions) {
Expand All @@ -28,33 +27,24 @@ export class IOSPerformanceLog extends IOSLog<PerformanceLogEntry, PerformanceLo
override async startCapture(): Promise<void> {
this.log.debug('Starting performance (Timeline) log capture');
this._clearEntries();
const result = await this.remoteDebugger.startTimeline(this.onTimelineEvent.bind(this));
await this.remoteDebugger.startTimeline(this.onTimelineEvent.bind(this));
this._started = true;
return result;
}

override async stopCapture(): Promise<void> {
this.log.debug('Stopping performance (Timeline) log capture');
const result = await this.remoteDebugger.stopTimeline();
await this.remoteDebugger.stopTimeline();
this._started = false;
return result;
}

override get isCapturing(): boolean {
return this._started;
}

protected override _serializeEntry(value: PerformanceLogEntry): PerformanceLogEntry {
return value;
}

protected override _deserializeEntry(value: PerformanceLogEntry): LogEntry {
return value as LogEntry;
}

private onTimelineEvent(event: PerformanceLogEntry): void {
this.log.debug(`Received Timeline event: ${_.truncate(JSON.stringify(event))}`);
this.broadcast(event);
const serializedEntry = JSON.stringify(event);
this.broadcast(serializedEntry);
this.log.debug(`Received Timeline event: ${_.truncate(serializedEntry)}`);
}
}

Expand Down
16 changes: 8 additions & 8 deletions lib/device-log/ios-simulator-log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ export interface IOSSimulatorLogOptions {
sim: Simulator;
showLogs?: boolean;
iosSimulatorLogsPredicate?: string;
log?: AppiumLogger;
log: AppiumLogger;
}

export class IOSSimulatorLog extends LineConsumingLog {
private sim: Simulator;
private showLogs: boolean;
private predicate?: string;
private readonly sim: Simulator;
private readonly showLogs: boolean;
private readonly predicate?: string;
private proc: SubProcess | null;

constructor(opts: IOSSimulatorLogOptions) {
Expand Down Expand Up @@ -93,24 +93,24 @@ export class IOSSimulatorLog extends LineConsumingLog {
}
}

private async finishStartingLogCapture() {
private async finishStartingLogCapture(): Promise<void> {
if (!this.proc) {
throw this.log.errorWithException('Could not capture simulator log');
}

for (const streamName of ['stdout', 'stderr']) {
this.proc.on(`lines-${streamName}`, (/** @type {string[]} */ lines) => {
this.proc.on(`lines-${streamName}`, (lines: string[]) => {
for (const line of lines) {
this.onOutput(line, ...(streamName === 'stderr' ? ['STDERR'] : []));
}
});
}

const startDetector = (/** @type {string} */ stdout, /** @type {string} */ stderr) => {
const startDetector = (stdout: string, stderr: string) => {
if (EXECVP_ERROR_PATTERN.test(stderr)) {
throw new Error('iOS log capture process failed to start');
}
return stdout || stderr;
return Boolean(stdout || stderr);
};
await this.proc.start(startDetector, START_TIMEOUT);
}
Expand Down
65 changes: 0 additions & 65 deletions lib/device-log/rotating-log.js

This file was deleted.

96 changes: 0 additions & 96 deletions lib/device-log/safari-console-log.js

This file was deleted.

Loading
Loading