@xenon-device-management/xenon 2.15.0 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -26
- package/lib/package.json +2 -1
- package/lib/public/assets/{AnnotationOverlay-Btq3dZRI.js → AnnotationOverlay-CjmMCS0S.js} +1 -1
- package/lib/public/assets/{ApiKeyGate-C9OoAgg_.js → ApiKeyGate-B4Ob0v3C.js} +1 -1
- package/lib/public/assets/{DeviceMosaicView-DBC_xczB.js → DeviceMosaicView-DTVOB_NO.js} +1 -1
- package/lib/public/assets/{EmptyState-DqWU2-vM.js → EmptyState-DcEG-oAi.js} +1 -1
- package/lib/public/assets/{FieldGroup-CveQ3xrA.js → FieldGroup-CtnCDshE.js} +1 -1
- package/lib/public/assets/{FilterMenu-BfKDSfHz.js → FilterMenu-BK0dE9cc.js} +1 -1
- package/lib/public/assets/{Menu-CtdCybzA.js → Menu-eKsmLpKS.js} +1 -1
- package/lib/public/assets/{Modal-Bsvj1tm2.js → Modal-DPwop3Lz.js} +1 -1
- package/lib/public/assets/{RecordingPage-CRofOiyx.js → RecordingPage-CfgSkZkB.js} +1 -1
- package/lib/public/assets/{RecordingsPage-jNQHb2IR.js → RecordingsPage-Bzl9pTUY.js} +1 -1
- package/lib/public/assets/{SegmentedControl-C8HtTha-.js → SegmentedControl-B_TZTrPm.js} +1 -1
- package/lib/public/assets/{SettingCard-D8K1LZNo.js → SettingCard-DlmvZJPM.js} +1 -1
- package/lib/public/assets/{Table-zNTX92Pn.js → Table-BigPWKXi.js} +1 -1
- package/lib/public/assets/{activity-CJ8LwZq9.js → activity-CvuZdQYu.js} +1 -1
- package/lib/public/assets/{ai-settings-CgxQZqrc.js → ai-settings-lI2UJ2n7.js} +1 -1
- package/lib/public/assets/{api-keys-ECpo-zTo.js → api-keys-CPgf9XJM.js} +1 -1
- package/lib/public/assets/{apps-BjGymyf3.js → apps-DIzOvtUp.js} +1 -1
- package/lib/public/assets/{arrow-left-BWfCbeHP.js → arrow-left-DiP5ywBT.js} +1 -1
- package/lib/public/assets/{arrow-right-DC7UGf_n.js → arrow-right-DtW_8hm5.js} +1 -1
- package/lib/public/assets/{arrow-up-right-BOjwybDk.js → arrow-up-right-C89FbNU0.js} +1 -1
- package/lib/public/assets/{auth-shell-CxMTo9aH.js → auth-shell-B7sUDb--.js} +2 -2
- package/lib/public/assets/{builds-page-DOCm4HkA.js → builds-page-BBhvrMfA.js} +1 -1
- package/lib/public/assets/{button-Cg08-EMT.js → button-DugsdUw1.js} +1 -1
- package/lib/public/assets/{calendar-CA1ikLJs.js → calendar-grKd08ZH.js} +1 -1
- package/lib/public/assets/{check-BMTaH72W.js → check-ORjyNfnX.js} +1 -1
- package/lib/public/assets/{chevron-right-B2QOv9Nx.js → chevron-right-Ei2FxUXq.js} +1 -1
- package/lib/public/assets/{circle-check-CYXBoUqT.js → circle-check-Day0HjW4.js} +1 -1
- package/lib/public/assets/{circle-x-DTwnSAnl.js → circle-x-CHxSRLHp.js} +1 -1
- package/lib/public/assets/{clock-C8_HViQP.js → clock-BDHewWTx.js} +1 -1
- package/lib/public/assets/{copy-Be7LNMXV.js → copy-CTwT4I3D.js} +1 -1
- package/lib/public/assets/{device-explorer-BOqtfGXz.js → device-explorer-DlhrKJ-g.js} +1 -1
- package/lib/public/assets/{download-B56lwxWP.js → download-D3bjz_vr.js} +1 -1
- package/lib/public/assets/{forgot-password-CCU6bzLn.js → forgot-password-BNBLi023.js} +1 -1
- package/lib/public/assets/{h264Stream-C-OtmIuk.js → h264Stream-C51Au2i_.js} +1 -1
- package/lib/public/assets/index-Dk5J6HB1.js +219 -0
- package/lib/public/assets/{index-B9KQ6LsY.js → index-DncSz5LG.js} +1 -1
- package/lib/public/assets/{index-CfxsUslp.js → index-Z7_BY3pJ.js} +1 -1
- package/lib/public/assets/{input-CZHFjbSg.js → input-bTXM4l09.js} +1 -1
- package/lib/public/assets/{line-chart-Gl_Dz3X_.js → line-chart-B3YmVYyr.js} +1 -1
- package/lib/public/assets/{list-checks-CCgjeyGY.js → list-checks-BClKEj1-.js} +1 -1
- package/lib/public/assets/{lock-CkOwgDcx.js → lock-CZsenX3D.js} +1 -1
- package/lib/public/assets/{login-D5cc4w7M.js → login-B6A6tOp9.js} +1 -1
- package/lib/public/assets/{maintenance-settings-t7qr3fvX.js → maintenance-settings-CmCJGy7O.js} +1 -1
- package/lib/public/assets/{monitor-DEJixKQO.js → monitor-BdTNEglU.js} +1 -1
- package/lib/public/assets/{mouse-pointer-2-CtOrk4M8.js → mouse-pointer-2-BM8CaLtt.js} +1 -1
- package/lib/public/assets/{network-Dii9qdvk.js → network-BS6vUc1x.js} +1 -1
- package/lib/public/assets/{overview-rolAACrO.js → overview-Yfk_Y7g3.js} +1 -1
- package/lib/public/assets/{page-header-COQZxJfR.js → page-header-DhXCwpml.js} +1 -1
- package/lib/public/assets/{play-DrN1Se_R.js → play-D08gP1td.js} +1 -1
- package/lib/public/assets/{plus-5aq-9uRx.js → plus-BKboorfa.js} +1 -1
- package/lib/public/assets/{profile-page-6i5kY6kF.js → profile-page-Cd9NodrA.js} +1 -1
- package/lib/public/assets/{reset-password-sp2IBrc7.js → reset-password-acLDyyDW.js} +1 -1
- package/lib/public/assets/{runbook-page-DJDjeopU.js → runbook-page-CWLkC1Fd.js} +153 -102
- package/lib/public/assets/{select-Bpyn7rWO.js → select-DZoRKNti.js} +1 -1
- package/lib/public/assets/{selector-detail-redirect-BH74vmKv.js → selector-detail-redirect-DS4qrt84.js} +1 -1
- package/lib/public/assets/{selector-health-page-Cw_g218H.js → selector-health-page-TpmN61G3.js} +1 -1
- package/lib/public/assets/session-detail-page-C0wYaXqy.js +4 -0
- package/lib/public/assets/{settings-C3uyGhyc.js → settings-CxPGEY2j.js} +1 -1
- package/lib/public/assets/{stat-tile-xVqAKIlI.js → stat-tile-DUpyYgl-.js} +1 -1
- package/lib/public/assets/{tablet-BxUScAeO.js → tablet-SA02BJNQ.js} +1 -1
- package/lib/public/assets/{teams-B5ljGkY2.js → teams-jamD0Kxr.js} +1 -1
- package/lib/public/assets/{trash-2-B701i8sy.js → trash-2-DO8fv6w4.js} +1 -1
- package/lib/public/assets/{upload-C2gr44RS.js → upload-CaiGCStb.js} +1 -1
- package/lib/public/assets/{use-builds-data-NeQOFEoy.js → use-builds-data-jS-fcvVf.js} +1 -1
- package/lib/public/assets/{use-password-reset-mode-DEzJq5ef.js → use-password-reset-mode-BzoenegM.js} +1 -1
- package/lib/public/assets/{users-MY6eNe6s.js → users-Bnw7Vs_B.js} +1 -1
- package/lib/public/assets/{users-D_vv_yz4.js → users-DHvDrriG.js} +1 -1
- package/lib/public/assets/{video-off-OK1lNZQn.js → video-off-FEvy0w5U.js} +1 -1
- package/lib/public/assets/{webhook-settings-BU-C9lBf.js → webhook-settings-CBVB5lxi.js} +1 -1
- package/lib/public/assets/{zap-DO9ry1iz.js → zap-BMrTJO6M.js} +1 -1
- package/lib/public/index.html +1 -1
- package/lib/schema.json +11 -7
- package/lib/src/InternalHttpClient.js +27 -5
- package/lib/src/XenonCapabilityManager.js +10 -3
- package/lib/src/app/index.js +2 -0
- package/lib/src/app/openapi/grid.yaml +102 -0
- package/lib/src/app/openapi/sessions.yaml +7 -5
- package/lib/src/app/routers/auth.js +2 -1
- package/lib/src/app/routers/users.js +2 -1
- package/lib/src/app/ws/nodeSocketRelay.js +77 -11
- package/lib/src/dashboard/commandLogFields.js +42 -0
- package/lib/src/dashboard/event-manager.js +23 -154
- package/lib/src/dashboard/services/failure-analysis-service.js +8 -86
- package/lib/src/dashboard/services/failureCategories.js +264 -0
- package/lib/src/device-managers/AndroidDeviceManager.js +61 -23
- package/lib/src/device-managers/IOSDeviceManager.js +10 -0
- package/lib/src/device-utils.js +25 -8
- package/lib/src/gateway/forwardToNode.js +4 -11
- package/lib/src/gateway/hubSessionToken.js +27 -4
- package/lib/src/gateway/nodeAsk.js +57 -0
- package/lib/src/gateway/nodeSessionDeviceLogs.js +35 -0
- package/lib/src/gateway/nodeWebDriverUrl.js +3 -5
- package/lib/src/helpers/outboundProxy.js +219 -0
- package/lib/src/index.js +21 -0
- package/lib/src/interceptors/CommandInterceptor.js +13 -15
- package/lib/src/interceptors/xenonScripts.js +28 -7
- package/lib/src/logger.js +3 -1
- package/lib/src/plugin.js +12 -4
- package/lib/src/scripts/database-check.js +3 -3
- package/lib/src/scripts/initialize-database.js +29 -33
- package/lib/src/scripts/run-migrations.js +320 -25
- package/lib/src/services/ApiKeyService.js +16 -5
- package/lib/src/services/InterceptorService.js +6 -2
- package/lib/src/services/OrphanSweeper.js +6 -0
- package/lib/src/services/SelectorStateService.js +11 -7
- package/lib/src/services/SelectorVerificationJob.js +6 -2
- package/lib/src/services/SessionLifecycleService.js +52 -23
- package/lib/src/services/SocketClient.js +11 -0
- package/lib/src/services/SocketServer.js +361 -42
- package/lib/src/services/TeamService.js +5 -1
- package/lib/src/services/TracingService.js +171 -60
- package/lib/src/services/UserService.js +14 -3
- package/lib/src/services/UserSessionService.js +16 -4
- package/lib/src/services/healing/HealingOrchestrator.js +3 -1
- package/lib/src/services/identity/identityChanges.js +41 -0
- package/lib/src/services/interceptor/CertManager.js +50 -16
- package/lib/src/services/logcat/NodeDeviceLogStore.js +99 -0
- package/lib/src/services/logcat/NodeDeviceLogsCollector.js +164 -0
- package/lib/src/services/logcat/SessionDeviceLogs.js +279 -37
- package/lib/src/services/logcat/deviceLogBook.js +5 -4
- package/lib/src/services/logcat/iosDriverLog.js +178 -0
- package/lib/src/services/logcat/nodeDeviceLogs.js +91 -0
- package/lib/src/services/metrics/nodeMetrics.js +20 -49
- package/lib/src/services/selector-health/SelectorVisibilityResolver.js +121 -0
- package/lib/src/services/token/JwtKeyService.js +8 -2
- package/lib/src/services/token/mcpTokenTtl.js +27 -0
- package/lib/src/sessions/LocalSession.js +29 -1
- package/lib/src/sessions/RemoteSession.js +23 -4
- package/lib/src/sessions/SessionManager.js +33 -9
- package/lib/test/helpers/driver-log.js +38 -0
- package/lib/test/helpers/fake-http-proxy.js +106 -0
- package/lib/test/helpers/fake-logcat.js +80 -0
- package/lib/test/helpers/hub-node-pair.js +227 -0
- package/lib/test/helpers/otlp-probe.js +107 -0
- package/lib/test/integration/androidDevices.spec.js +1 -1
- package/lib/test/integration/ios/01iOSSimulator.spec.js +1 -1
- package/lib/test/integration/ios/02iOSDevices.spec.js +1 -1
- package/lib/test/integration/selector-state-flow.spec.js +5 -5
- package/lib/test/unit/XenonCapabilityManager.spec.js +23 -0
- package/lib/test/unit/android-adb-retry.spec.js +112 -0
- package/lib/test/unit/command-log-network-capture.spec.js +191 -0
- package/lib/test/unit/dashboard-events-device-logs.spec.js +74 -11
- package/lib/test/unit/dashboard-events-team-scope.spec.js +6 -3
- package/lib/test/unit/database-check.spec.js +1 -0
- package/lib/test/unit/device-utils.spec.js +13 -4
- package/lib/test/unit/event-log-session-data.spec.js +11 -4
- package/lib/test/unit/failure-analysis.spec.js +22 -8
- package/lib/test/unit/failure-categories.spec.js +24 -22
- package/lib/test/unit/failure-categorization.spec.js +393 -0
- package/lib/test/unit/healing-tier-gate.spec.js +3 -2
- package/lib/test/unit/hub-node-gateway-appium-server.spec.js +72 -1
- package/lib/test/unit/hub-node-iphone-readiness.spec.js +134 -0
- package/lib/test/unit/hub-node-session-device-logs.spec.js +194 -0
- package/lib/test/unit/hub-node-session-metrics.spec.js +24 -192
- package/lib/test/unit/hub-remote-session-heartbeat.spec.js +8 -1
- package/lib/test/unit/interceptor/CertManager.spec.js +89 -0
- package/lib/test/unit/ios-driver-log.spec.js +168 -0
- package/lib/test/unit/ios-simulator-session-readiness.spec.js +187 -0
- package/lib/test/unit/ios-simulator-session-teardown.spec.js +158 -0
- package/lib/test/unit/logcat-ws.spec.js +78 -37
- package/lib/test/unit/logger-json-levels.spec.js +44 -0
- package/lib/test/unit/mcp-token-ttl.spec.js +38 -0
- package/lib/test/unit/node-device-log-store.spec.js +102 -0
- package/lib/test/unit/node-device-logs-collector.spec.js +343 -0
- package/lib/test/unit/node-gateway-create-appium-server.spec.js +8 -1
- package/lib/test/unit/node-hub-session-owner.spec.js +8 -1
- package/lib/test/unit/node-session-device-logs-route.spec.js +103 -0
- package/lib/test/unit/observability-example-loki.spec.js +25 -0
- package/lib/test/unit/openapi-for-site.spec.js +80 -0
- package/lib/test/unit/outbound-proxy.spec.js +320 -0
- package/lib/test/unit/port-exhaustion.spec.js +2 -1
- package/lib/test/unit/proxy-option.spec.js +358 -0
- package/lib/test/unit/run-migrations-database.spec.js +440 -0
- package/lib/test/unit/run-migrations-fail-fast.test.js +41 -27
- package/lib/test/unit/run-migrations.test.js +264 -0
- package/lib/test/unit/selector-health-actions.spec.js +3 -1
- package/lib/test/unit/selector-state-service.spec.js +72 -23
- package/lib/test/unit/selector-verification-clean-build.spec.js +1 -1
- package/lib/test/unit/selector-verification-job.spec.js +15 -6
- package/lib/test/unit/selector-verification-missed-regression.spec.js +2 -2
- package/lib/test/unit/selector-visibility-resolver.spec.js +209 -0
- package/lib/test/unit/session-device-logs-hub-node.spec.js +340 -0
- package/lib/test/unit/session-device-logs-ios.spec.js +180 -0
- package/lib/test/unit/session-device-logs-lifecycle.spec.js +137 -0
- package/lib/test/unit/session-device-logs.spec.js +43 -96
- package/lib/test/unit/session-end-failure-analysis.spec.js +5 -5
- package/lib/test/unit/session-log-indexes.spec.js +16 -1
- package/lib/test/unit/socket-team-scope.integration.spec.js +749 -0
- package/lib/test/unit/socketServer.scopedEmit.spec.js +237 -5
- package/lib/test/unit/tracing-export-routing.spec.js +137 -0
- package/lib/test/unit/tracing-session-spans.spec.js +337 -0
- package/lib/test/unit/unexpected-shutdown-reason.spec.js +2 -2
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/schema.json +11 -7
- package/scripts/dev/readme-screenshots.js +276 -23
- package/scripts/dev/screenshot-fixtures/logcat.js +157 -0
- package/scripts/dev/screenshot-fixtures/phone-screen.html +469 -0
- package/scripts/dev/screenshot-fixtures/session.js +242 -0
- package/scripts/export-openapi.js +32 -0
- package/scripts/lib/openapi-for-site.js +79 -0
- package/lib/public/assets/index-BOxe43p1.js +0 -219
- package/lib/public/assets/session-detail-page-AZJE6XXE.js +0 -4
- package/lib/src/scripts/prepare-prisma.js +0 -89
|
@@ -39,6 +39,10 @@ const log = logger_1.default.scope('SelectorVerification');
|
|
|
39
39
|
* selector that was never found again was verified as fixed.
|
|
40
40
|
*/
|
|
41
41
|
const CLEAN_BUILDS_TO_RESOLVE = 3;
|
|
42
|
+
/** The selector a row is about, as the socket server's scoped emit names it. */
|
|
43
|
+
function keyOfRow(row) {
|
|
44
|
+
return { strategy: row.original_strategy, selector: row.original_selector };
|
|
45
|
+
}
|
|
42
46
|
/**
|
|
43
47
|
* Periodically scans Pending SelectorState rows and promotes them to Resolved
|
|
44
48
|
* once enough clean CI builds have been observed (no heals on the selector
|
|
@@ -180,7 +184,7 @@ let SelectorVerificationJob = class SelectorVerificationJob {
|
|
|
180
184
|
return promoted;
|
|
181
185
|
}));
|
|
182
186
|
log.info(`[${row.id}] promoted to resolved (${row.original_strategy}=${row.original_selector})`);
|
|
183
|
-
this.socket.
|
|
187
|
+
void this.socket.emitToDashboardForSelector(SocketEvents_1.SocketEvents.SELECTOR_RESOLVED, this.serialize(updated), keyOfRow(row));
|
|
184
188
|
});
|
|
185
189
|
}
|
|
186
190
|
updateProgress(row, cleanBuildCount) {
|
|
@@ -189,7 +193,7 @@ let SelectorVerificationJob = class SelectorVerificationJob {
|
|
|
189
193
|
where: { id: row.id },
|
|
190
194
|
data: { clean_builds_count: cleanBuildCount, last_event_at: new Date() },
|
|
191
195
|
});
|
|
192
|
-
this.socket.
|
|
196
|
+
void this.socket.emitToDashboardForSelector(SocketEvents_1.SocketEvents.SELECTOR_PROGRESS, this.serialize(updated), keyOfRow(row));
|
|
193
197
|
});
|
|
194
198
|
}
|
|
195
199
|
serialize(row) {
|
|
@@ -56,8 +56,6 @@ const typedi_1 = require("typedi");
|
|
|
56
56
|
const uuid_1 = require("uuid");
|
|
57
57
|
const lodash_1 = __importDefault(require("lodash"));
|
|
58
58
|
const axios_1 = __importDefault(require("axios"));
|
|
59
|
-
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
60
|
-
const http_proxy_agent_1 = require("http-proxy-agent");
|
|
61
59
|
const logger_1 = __importDefault(require("../logger"));
|
|
62
60
|
const helpers_1 = require("../helpers");
|
|
63
61
|
const InternalHttpClient_1 = require("../InternalHttpClient");
|
|
@@ -81,6 +79,7 @@ const appVisibility_1 = require("./device-access/appVisibility");
|
|
|
81
79
|
const LiveSessionOwners_1 = require("./device-access/LiveSessionOwners");
|
|
82
80
|
const sessionMemory_1 = require("../sessions/sessionMemory");
|
|
83
81
|
const SessionMetricsService_1 = require("./metrics/SessionMetricsService");
|
|
82
|
+
const SessionDeviceLogs_1 = require("./logcat/SessionDeviceLogs");
|
|
84
83
|
const appCapability_1 = require("./session/appCapability");
|
|
85
84
|
const CircuitBreaker_1 = require("../data-service/CircuitBreaker");
|
|
86
85
|
const nodeWebDriverUrl_1 = require("../gateway/nodeWebDriverUrl");
|
|
@@ -848,7 +847,7 @@ let SessionLifecycleService = class SessionLifecycleService {
|
|
|
848
847
|
}
|
|
849
848
|
finalizeSession(session_1, device_1, caps_1, driver_1, isRemote_1) {
|
|
850
849
|
return __awaiter(this, arguments, void 0, function* (session, device, caps, driver, isRemote, apiKeyId = null, userId = null, allocatedAt) {
|
|
851
|
-
var _a;
|
|
850
|
+
var _a, _b;
|
|
852
851
|
const sessionId = session.value[0];
|
|
853
852
|
const sessionResponse = session.value[1];
|
|
854
853
|
const requestedCaps = Object.assign({}, ((_a = caps.firstMatch) === null || _a === void 0 ? void 0 : _a[0]) || {}, caps.alwaysMatch || {});
|
|
@@ -865,6 +864,23 @@ let SessionLifecycleService = class SessionLifecycleService {
|
|
|
865
864
|
'xenon.udid': device.udid,
|
|
866
865
|
});
|
|
867
866
|
}
|
|
867
|
+
try {
|
|
868
|
+
yield this.registerSession(sessionId, sessionResponse, device, xenonCapabilities, driver, isRemote, apiKeyId, userId, allocatedAt);
|
|
869
|
+
}
|
|
870
|
+
catch (err) {
|
|
871
|
+
// The create fails, so no ending of the session will come to end it.
|
|
872
|
+
tracingService.endSessionSpan(sessionId, {
|
|
873
|
+
failed: true,
|
|
874
|
+
reason: `Xenon could not finish creating the session: ${(_b = err === null || err === void 0 ? void 0 : err.message) !== null && _b !== void 0 ? _b : err}`,
|
|
875
|
+
});
|
|
876
|
+
throw err;
|
|
877
|
+
}
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
/** The rest of finalizeSession, once the session's span has started. */
|
|
881
|
+
registerSession(sessionId, sessionResponse, device, xenonCapabilities, driver, isRemote, apiKeyId, userId, allocatedAt) {
|
|
882
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
883
|
+
const context = typedi_1.Container.get(PluginContext_1.PluginContext);
|
|
868
884
|
// The session takes over the pending claim its phone was allocated with.
|
|
869
885
|
yield (0, device_service_1.claimDeviceForSession)(device, sessionId, {
|
|
870
886
|
session_id: sessionId,
|
|
@@ -889,15 +905,26 @@ let SessionLifecycleService = class SessionLifecycleService {
|
|
|
889
905
|
if (sessionInstance instanceof LocalSession_1.LocalSession) {
|
|
890
906
|
typedi_1.Container.get(LiveSessionOwners_1.LiveSessionOwners).record(sessionId, userId);
|
|
891
907
|
}
|
|
892
|
-
// A node samples its own phones for its hub,
|
|
893
|
-
//
|
|
894
|
-
//
|
|
908
|
+
// A node samples its own phones for its hub, and records their device
|
|
909
|
+
// log unless the session turned it off, whatever its dashboard setting
|
|
910
|
+
// (the hub collects both). A hub and a standalone server start them in
|
|
911
|
+
// EventManager.onSessionStarted, once the row exists.
|
|
895
912
|
if (!this.isHub(context.pluginArgs) && sessionInstance instanceof LocalSession_1.LocalSession) {
|
|
896
913
|
typedi_1.Container.get(SessionMetricsService_1.SessionMetricsService).start({
|
|
897
914
|
sessionId,
|
|
898
915
|
device: freshDevice,
|
|
899
916
|
capabilities: sessionResponse,
|
|
900
917
|
});
|
|
918
|
+
if (xenonCapabilities[XenonCapabilityManager_1.XENON_CAPABILITIES.SAVE_DEVICE_LOGS] !== false) {
|
|
919
|
+
void typedi_1.Container.get(SessionDeviceLogs_1.SessionDeviceLogs).start({
|
|
920
|
+
sessionId,
|
|
921
|
+
device: freshDevice,
|
|
922
|
+
since: allocatedAt,
|
|
923
|
+
// An iPhone's or simulator's: the log its driver captures.
|
|
924
|
+
driverLog: sessionInstance.deviceLog(),
|
|
925
|
+
appUnderTest: sessionInstance.appUnderTest(),
|
|
926
|
+
});
|
|
927
|
+
}
|
|
901
928
|
}
|
|
902
929
|
yield this.applyPostSessionLogic(sessionInstance, xenonCapabilities, freshDevice);
|
|
903
930
|
});
|
|
@@ -1063,19 +1090,8 @@ let SessionLifecycleService = class SessionLifecycleService {
|
|
|
1063
1090
|
timeout: exports.REMOTE_CREATE_TIMEOUT_MS,
|
|
1064
1091
|
retry: false,
|
|
1065
1092
|
};
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
const proxyUrl = typeof context.pluginArgs.proxy === 'string'
|
|
1069
|
-
? context.pluginArgs.proxy
|
|
1070
|
-
: `http://${context.pluginArgs.proxy.host}:${context.pluginArgs.proxy.port}`;
|
|
1071
|
-
config.httpsAgent = new https_proxy_agent_1.HttpsProxyAgent(proxyUrl, {
|
|
1072
|
-
rejectUnauthorized: context.pluginArgs.tlsRejectUnauthorized,
|
|
1073
|
-
});
|
|
1074
|
-
config.httpAgent = new http_proxy_agent_1.HttpProxyAgent(proxyUrl, {
|
|
1075
|
-
rejectUnauthorized: context.pluginArgs.tlsRejectUnauthorized,
|
|
1076
|
-
});
|
|
1077
|
-
config.proxy = false;
|
|
1078
|
-
}
|
|
1093
|
+
// Its proxy is InternalHttpClient's, by Xenon's one rule: the `proxy`
|
|
1094
|
+
// option, else the environment's (helpers/outboundProxy.ts).
|
|
1079
1095
|
const createdSession = yield this.invokeSessionRequest(config, context.pluginArgs.tlsRejectUnauthorized);
|
|
1080
1096
|
if (createdSession instanceof Error) {
|
|
1081
1097
|
return createdSession;
|
|
@@ -1207,10 +1223,18 @@ let SessionLifecycleService = class SessionLifecycleService {
|
|
|
1207
1223
|
if (sessionId) {
|
|
1208
1224
|
typedi_1.Container.get(LiveSessionOwners_1.LiveSessionOwners).forget(sessionId);
|
|
1209
1225
|
(0, sessionMemory_1.forgetSessionMemory)(sessionId);
|
|
1226
|
+
// Whether or not SESSION_MANAGER holds the session (a local one with
|
|
1227
|
+
// the dashboard off), and once: a second delete finds no span.
|
|
1228
|
+
typedi_1.Container.get(TracingService_1.TracingService).endSessionSpan(sessionId, {
|
|
1229
|
+
failed: status === SessionStatus_1.SessionStatus.FAILED,
|
|
1230
|
+
reason,
|
|
1231
|
+
});
|
|
1210
1232
|
// Before the lock's "still in memory?" check, which a dashboard-off
|
|
1211
|
-
// node fails. On a node this ends the figures
|
|
1212
|
-
// on a hub it collects a node session's last ones
|
|
1233
|
+
// node fails. On a node this ends the figures and device log it
|
|
1234
|
+
// holds for its hub; on a hub it collects a node session's last ones,
|
|
1235
|
+
// before onSessionStopped's failure analysis reads the log. Idempotent.
|
|
1213
1236
|
yield typedi_1.Container.get(SessionMetricsService_1.SessionMetricsService).stop(sessionId);
|
|
1237
|
+
yield typedi_1.Container.get(SessionDeviceLogs_1.SessionDeviceLogs).stop(sessionId);
|
|
1214
1238
|
yield sessionCleanupLock.acquire(sessionId, () => __awaiter(this, void 0, void 0, function* () {
|
|
1215
1239
|
const session = SessionManager_1.SESSION_MANAGER.getSession(sessionId);
|
|
1216
1240
|
if (!session) {
|
|
@@ -1240,8 +1264,11 @@ let SessionLifecycleService = class SessionLifecycleService {
|
|
|
1240
1264
|
logger_1.default.warn(`Port release failed: ${err.message}`);
|
|
1241
1265
|
}
|
|
1242
1266
|
}
|
|
1243
|
-
// 1. iOS Profiling Archival
|
|
1244
|
-
|
|
1267
|
+
// 1. iOS Profiling Archival. Only on an iPhone, the one place
|
|
1268
|
+
// EventManager.onSessionStarted starts it. A simulator's driver refuses
|
|
1269
|
+
// the stop without relaxed security, and the refused stop counted as a
|
|
1270
|
+
// failed command of the session: every simulator session ended failed.
|
|
1271
|
+
if (device && ((_a = device.platform) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'ios' && device.realDevice === true) {
|
|
1245
1272
|
this.logger.info(`[${sessionId}] Stopping iOS profiling for asset archival`);
|
|
1246
1273
|
try {
|
|
1247
1274
|
const traceBase64 = yield session.stopPerformanceRecording();
|
|
@@ -1323,7 +1350,9 @@ let SessionLifecycleService = class SessionLifecycleService {
|
|
|
1323
1350
|
SessionManager_1.SESSION_MANAGER.removeSession(sessionId);
|
|
1324
1351
|
typedi_1.Container.get(LiveSessionOwners_1.LiveSessionOwners).forget(sessionId);
|
|
1325
1352
|
(0, sessionMemory_1.forgetSessionMemory)(sessionId);
|
|
1353
|
+
typedi_1.Container.get(TracingService_1.TracingService).endSessionSpan(sessionId, { failed: true, reason });
|
|
1326
1354
|
yield typedi_1.Container.get(SessionMetricsService_1.SessionMetricsService).stop(sessionId);
|
|
1355
|
+
yield typedi_1.Container.get(SessionDeviceLogs_1.SessionDeviceLogs).stop(sessionId);
|
|
1327
1356
|
}));
|
|
1328
1357
|
});
|
|
1329
1358
|
}
|
|
@@ -15,6 +15,7 @@ const typedi_1 = require("typedi");
|
|
|
15
15
|
const logger_1 = __importDefault(require("../logger"));
|
|
16
16
|
const config_1 = require("../config");
|
|
17
17
|
const SocketEvents_1 = require("../enums/SocketEvents");
|
|
18
|
+
const outboundProxy_1 = require("../helpers/outboundProxy");
|
|
18
19
|
let SocketClient = class SocketClient {
|
|
19
20
|
constructor() {
|
|
20
21
|
this.socket = null;
|
|
@@ -46,6 +47,16 @@ let SocketClient = class SocketClient {
|
|
|
46
47
|
reconnectionDelay: 1000,
|
|
47
48
|
reconnectionDelayMax: 5000,
|
|
48
49
|
auth: socketAuth,
|
|
50
|
+
// The proxy the node's other calls to its hub take (its phone reports,
|
|
51
|
+
// its JWKS fetch); it used to go straight to the hub whatever the
|
|
52
|
+
// environment said. Polling goes as plain requests, as axios sends
|
|
53
|
+
// them; only the WebSocket upgrade needs a CONNECT tunnel, and when the
|
|
54
|
+
// proxy refuses one (a stock Squid allows port 443 only) the
|
|
55
|
+
// connection stays on polling.
|
|
56
|
+
transportOptions: {
|
|
57
|
+
polling: { agent: (0, outboundProxy_1.proxyAgentFor)(normalizedHubUrl) },
|
|
58
|
+
websocket: { agent: (0, outboundProxy_1.socketProxyAgentFor)(normalizedHubUrl) },
|
|
59
|
+
},
|
|
49
60
|
});
|
|
50
61
|
this.socket.on('connect', () => {
|
|
51
62
|
var _a, _b, _c;
|