nativescript
Version:
Command-line interface for building NativeScript projects
168 lines • 8.11 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogcatHelper = void 0;
const byline = require("byline");
const semver = require("semver");
const yok_1 = require("../../yok");
const device_android_debug_bridge_1 = require("./device-android-debug-bridge");
class LogcatHelper {
constructor($deviceLogProvider, $devicePlatformsConstants, $logger, $injector, $devicesService) {
this.$deviceLogProvider = $deviceLogProvider;
this.$devicePlatformsConstants = $devicePlatformsConstants;
this.$logger = $logger;
this.$injector = $injector;
this.$devicesService = $devicesService;
this.mapDevicesLoggingData = Object.create(null);
}
async start(options) {
const deviceIdentifier = options.deviceIdentifier;
if (deviceIdentifier && !this.mapDevicesLoggingData[deviceIdentifier]) {
this.mapDevicesLoggingData[deviceIdentifier] = {
loggingProcess: null,
lineStream: null,
keepSingleProcess: options.keepSingleProcess,
appStartTrackingProcess: null,
rawLineStream: null,
};
const logcatStream = await this.getLogcatStream(deviceIdentifier, options.pid);
const lineStream = byline(logcatStream.stdout);
this.mapDevicesLoggingData[deviceIdentifier].loggingProcess =
logcatStream;
this.mapDevicesLoggingData[deviceIdentifier].lineStream = lineStream;
logcatStream.stderr.on("data", (data) => {
this.$logger.trace("ADB logcat stderr: " + data.toString());
});
logcatStream.on("close", (code) => {
try {
this.forceStop(deviceIdentifier);
if (code !== 0) {
this.$logger.trace("ADB process exited with code " + code.toString());
}
}
catch (err) {
// Ignore the error, the process is dead.
}
});
lineStream.on("data", (lineBuffer) => {
const lines = (lineBuffer.toString() || "").split("\n");
for (const line of lines) {
this.$deviceLogProvider.logData(line, this.$devicePlatformsConstants.Android, deviceIdentifier);
}
});
const appStartTrackingStream = await this.getAppStartTrackingLogcatStream(deviceIdentifier, options.appId);
this.mapDevicesLoggingData[deviceIdentifier].appStartTrackingProcess =
appStartTrackingStream;
const rawLineStream = byline(appStartTrackingStream.stdout);
this.mapDevicesLoggingData[deviceIdentifier].rawLineStream =
rawLineStream;
rawLineStream.on("data", (lineBuffer) => {
var _a, _b, _c, _d;
if (!((_a = this.mapDevicesLoggingData[deviceIdentifier]) === null || _a === void 0 ? void 0 : _a.loggingProcess))
return;
const lines = (lineBuffer.toString() || "").split("\n");
for (let line of lines) {
// 2024-06-26 16:43:22.286 630-659 ActivityManager system_server I Start proc 8854:org.nativescript.uitestsapp/u0a190 for next-top-activity {org.nativescript.uitestsapp/com.tns.NativeScriptActivity}
const startProc = /Start proc (?<pid>[0-9]+):(?<appId>.+?)\//.exec(line);
if (startProc &&
((_b = startProc.groups) === null || _b === void 0 ? void 0 : _b.appId) === options.appId &&
((_c = startProc.groups) === null || _c === void 0 ? void 0 : _c.pid) !== options.pid) {
this.forceStop(deviceIdentifier);
(_d = options.onAppRestarted) === null || _d === void 0 ? void 0 : _d.call(options);
}
}
});
}
}
async dump(deviceIdentifier) {
const adb = this.$injector.resolve(device_android_debug_bridge_1.DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
const logcatDumpStream = await adb.executeCommand(["logcat", "-d"], {
returnChildProcess: true,
});
const lineStream = byline(logcatDumpStream.stdout);
lineStream.on("data", (line) => {
const lineText = line.toString();
this.$logger.trace(lineText);
});
logcatDumpStream.on("close", (code) => {
logcatDumpStream.removeAllListeners();
lineStream.removeAllListeners();
});
}
/**
* Stops the logcat process for the specified device if keepSingleProcess is not passed on start
*/
stop(deviceIdentifier) {
if (this.mapDevicesLoggingData[deviceIdentifier] &&
!this.mapDevicesLoggingData[deviceIdentifier].keepSingleProcess) {
this.forceStop(deviceIdentifier);
}
}
forceStop(deviceIdentifier) {
var _a, _b, _c, _d, _e;
const loggingData = this.mapDevicesLoggingData[deviceIdentifier];
(_a = loggingData.loggingProcess) === null || _a === void 0 ? void 0 : _a.removeAllListeners();
(_b = loggingData.loggingProcess) === null || _b === void 0 ? void 0 : _b.kill("SIGINT");
(_c = loggingData.lineStream) === null || _c === void 0 ? void 0 : _c.removeAllListeners();
(_d = loggingData.appStartTrackingProcess) === null || _d === void 0 ? void 0 : _d.kill("SIGINT");
(_e = loggingData.lineStream) === null || _e === void 0 ? void 0 : _e.removeAllListeners();
delete this.mapDevicesLoggingData[deviceIdentifier];
}
/**
* @deprecated - we likely don't need this anymore, and can simplify the code...
*/
async isLogcatPidSupported(deviceIdentifier) {
const device = await this.$devicesService.getDevice(deviceIdentifier);
const minAndroidWithLogcatPidSupport = "7.0.0";
return (!!device.deviceInfo.version &&
semver.gte(semver.coerce(device.deviceInfo.version), minAndroidWithLogcatPidSupport));
}
async getLogcatStream(deviceIdentifier, pid) {
const isLogcatPidSupported = await this.isLogcatPidSupported(deviceIdentifier);
const adb = this.$injector.resolve(device_android_debug_bridge_1.DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
// -T 1 - shows only new logs after starting adb logcat
const logcatCommand = ["logcat", "-T", "1"];
const acceptedTags = [
"chromium",
'"Web Console"',
"JS",
"System.err",
"TNS.Native",
"TNS.Java",
];
if (pid && isLogcatPidSupported) {
logcatCommand.push(`--pid=${pid}`);
acceptedTags.forEach((tag) => {
// -s <tag> - shows only logs with the specified tag
logcatCommand.push("-s", tag);
});
}
const logcatStream = await adb.executeCommand(logcatCommand, {
returnChildProcess: true,
});
return logcatStream;
}
async getAppStartTrackingLogcatStream(deviceIdentifier, appId) {
const adb = this.$injector.resolve(device_android_debug_bridge_1.DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
// -b system - shows the system buffer/logs only
// -T 1 - shows only new logs after starting adb logcat
const logcatCommand = [
`logcat`,
`-b`,
`system`,
`-T`,
`1`,
"-s",
"ActivityManager",
];
if (appId) {
logcatCommand.push(`--regex=Start.*${appId}`);
}
const appStartTrackingStream = await adb.executeCommand(logcatCommand, {
returnChildProcess: true,
});
return appStartTrackingStream;
}
}
exports.LogcatHelper = LogcatHelper;
yok_1.injector.register("logcatHelper", LogcatHelper);
//# sourceMappingURL=logcat-helper.js.map
;