UNPKG

nativescript

Version:

Command-line interface for building NativeScript projects

168 lines • 8.11 kB
"use strict"; 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