@unbrained/pm-cli 2026.5.3 → 2026.5.5
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/CHANGELOG.md +63 -0
- package/README.md +11 -1
- package/dist/cli/commands/config.js +2 -2
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/main.js +269 -15
- package/dist/cli/main.js.map +1 -1
- package/dist/core/item/item-format.js +24 -1
- package/dist/core/item/item-format.js.map +1 -1
- package/dist/core/sentry/helpers.d.ts +15 -2
- package/dist/core/sentry/helpers.js +73 -3
- package/dist/core/sentry/helpers.js.map +1 -1
- package/dist/core/shared/constants.js +3 -0
- package/dist/core/shared/constants.js.map +1 -1
- package/dist/core/store/item-format-migration.js +35 -23
- package/dist/core/store/item-format-migration.js.map +1 -1
- package/dist/core/telemetry/observability.d.ts +24 -0
- package/dist/core/telemetry/observability.js +185 -0
- package/dist/core/telemetry/observability.js.map +1 -0
- package/dist/core/telemetry/runtime.d.ts +6 -0
- package/dist/core/telemetry/runtime.js +132 -7
- package/dist/core/telemetry/runtime.js.map +1 -1
- package/docs/CONFIGURATION.md +0 -2
- package/docs/QUICKSTART.md +8 -0
- package/docs/RELEASING.md +52 -43
- package/package.json +6 -1
- package/scripts/install.ps1 +12 -1
- package/scripts/install.sh +17 -1
package/dist/cli/main.js
CHANGED
|
@@ -12,6 +12,7 @@ import { PmCliError } from "../core/shared/errors.js";
|
|
|
12
12
|
import { printError, printResult, writeStdout } from "../core/output/output.js";
|
|
13
13
|
import { maybeRunFirstUseTelemetryPrompt } from "../core/telemetry/consent.js";
|
|
14
14
|
import { emitTelemetryErrorEvent, finishTelemetryCommand, startTelemetryCommand, } from "../core/telemetry/runtime.js";
|
|
15
|
+
import { deriveTelemetryCommandResolution, } from "../core/telemetry/observability.js";
|
|
15
16
|
import { sentryCaptureCliError, sentryFinishCommandSpan, sentryFlush, sentryLogCliUsageError, sentrySetCommandContext, sentryStartCommandSpan, } from "../core/sentry/helpers.js";
|
|
16
17
|
import { getSettingsPath, resolvePmRoot } from "../core/store/paths.js";
|
|
17
18
|
import { readSettings } from "../core/store/settings.js";
|
|
@@ -38,6 +39,20 @@ if (typeof process.env[PM_PACKAGE_ROOT_ENV] !== "string" || process.env[PM_PACKA
|
|
|
38
39
|
}
|
|
39
40
|
let activeExtensionHookContext = null;
|
|
40
41
|
let activeTelemetryCommandContext = null;
|
|
42
|
+
const TELEMETRY_COMMAND_RESOLUTION_SET = new Set([
|
|
43
|
+
"success",
|
|
44
|
+
"nonexistent_command",
|
|
45
|
+
"invalid_option",
|
|
46
|
+
"missing_required_option",
|
|
47
|
+
"missing_required_argument",
|
|
48
|
+
"invalid_usage",
|
|
49
|
+
"validation_failed",
|
|
50
|
+
"conflict",
|
|
51
|
+
"runtime_failed",
|
|
52
|
+
"unknown_failed",
|
|
53
|
+
]);
|
|
54
|
+
const TELEMETRY_RESOLUTION_STAGE_SET = new Set(["parse", "preflight", "execute", "unknown"]);
|
|
55
|
+
const TELEMETRY_ERROR_CATEGORY_SET = new Set(["usage", "validation", "conflict", "runtime", "unknown"]);
|
|
41
56
|
let runtimeExtensionSnapshotCache = null;
|
|
42
57
|
let activeRuntimeExtensionCommandDescriptors = new Map();
|
|
43
58
|
function describeUnknownError(error) {
|
|
@@ -49,6 +64,163 @@ function describeUnknownError(error) {
|
|
|
49
64
|
}
|
|
50
65
|
return "Unknown failure";
|
|
51
66
|
}
|
|
67
|
+
function asRecord(value) {
|
|
68
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
function readRecordString(record, ...keys) {
|
|
74
|
+
if (!record) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
for (const key of keys) {
|
|
78
|
+
const candidate = record[key];
|
|
79
|
+
if (typeof candidate === "string") {
|
|
80
|
+
const normalized = candidate.trim();
|
|
81
|
+
if (normalized.length > 0) {
|
|
82
|
+
return normalized;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
function readRecordBoolean(record, ...keys) {
|
|
89
|
+
if (!record) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
for (const key of keys) {
|
|
93
|
+
const candidate = record[key];
|
|
94
|
+
if (typeof candidate === "boolean") {
|
|
95
|
+
return candidate;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
function readRecordNumber(record, ...keys) {
|
|
101
|
+
if (!record) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
for (const key of keys) {
|
|
105
|
+
const candidate = record[key];
|
|
106
|
+
if (typeof candidate === "number" && Number.isFinite(candidate)) {
|
|
107
|
+
return Math.max(0, Math.trunc(candidate));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
function normalizeTelemetryCommandResolution(value) {
|
|
113
|
+
if (!value) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
const normalized = value.trim().toLowerCase();
|
|
117
|
+
if (!TELEMETRY_COMMAND_RESOLUTION_SET.has(normalized)) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
return normalized;
|
|
121
|
+
}
|
|
122
|
+
function normalizeTelemetryResolutionStage(value) {
|
|
123
|
+
if (!value) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
const normalized = value.trim().toLowerCase();
|
|
127
|
+
if (!TELEMETRY_RESOLUTION_STAGE_SET.has(normalized)) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
return normalized;
|
|
131
|
+
}
|
|
132
|
+
function normalizeTelemetryErrorCategory(value) {
|
|
133
|
+
if (!value) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
const normalized = value.trim().toLowerCase();
|
|
137
|
+
if (!TELEMETRY_ERROR_CATEGORY_SET.has(normalized)) {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
return normalized;
|
|
141
|
+
}
|
|
142
|
+
function inferPostActionFailureMessage(result) {
|
|
143
|
+
const explicit = readRecordString(result, "error", "message");
|
|
144
|
+
if (explicit) {
|
|
145
|
+
return explicit;
|
|
146
|
+
}
|
|
147
|
+
const warnings = result?.warnings;
|
|
148
|
+
if (Array.isArray(warnings)) {
|
|
149
|
+
const firstWarning = warnings.find((value) => typeof value === "string" && value.trim().length > 0);
|
|
150
|
+
if (typeof firstWarning === "string") {
|
|
151
|
+
return firstWarning.trim();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const skippedTriggered = readRecordBoolean(result, "fail_on_skipped_triggered", "failOnSkippedTriggered");
|
|
155
|
+
if (skippedTriggered) {
|
|
156
|
+
return "linked_test_fail_on_skipped_triggered";
|
|
157
|
+
}
|
|
158
|
+
const failedCount = readRecordNumber(result, "failed");
|
|
159
|
+
if (typeof failedCount === "number" && failedCount > 0) {
|
|
160
|
+
return `failed_runs:${failedCount}`;
|
|
161
|
+
}
|
|
162
|
+
const runResults = result?.run_results;
|
|
163
|
+
if (Array.isArray(runResults)) {
|
|
164
|
+
const failedRuns = runResults.filter((entry) => {
|
|
165
|
+
const row = asRecord(entry);
|
|
166
|
+
return row?.status === "failed";
|
|
167
|
+
}).length;
|
|
168
|
+
if (failedRuns > 0) {
|
|
169
|
+
return `failed_runs:${failedRuns}`;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
function inferPostActionErrorCode(ok, exitCode) {
|
|
175
|
+
if (ok) {
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
if (exitCode === EXIT_CODE.USAGE) {
|
|
179
|
+
return "invalid_command_usage";
|
|
180
|
+
}
|
|
181
|
+
if (exitCode === EXIT_CODE.NOT_FOUND) {
|
|
182
|
+
return "item_not_found";
|
|
183
|
+
}
|
|
184
|
+
if (exitCode === EXIT_CODE.CONFLICT) {
|
|
185
|
+
return "lock_conflict";
|
|
186
|
+
}
|
|
187
|
+
if (exitCode === EXIT_CODE.DEPENDENCY_FAILED) {
|
|
188
|
+
return "dependency_failed";
|
|
189
|
+
}
|
|
190
|
+
return "command_failed";
|
|
191
|
+
}
|
|
192
|
+
function buildPostActionTelemetryOutcome() {
|
|
193
|
+
const result = asRecord(getActiveCommandResult());
|
|
194
|
+
const processExitCode = typeof process.exitCode === "number" && Number.isFinite(process.exitCode)
|
|
195
|
+
? Math.max(0, Math.trunc(process.exitCode))
|
|
196
|
+
: undefined;
|
|
197
|
+
const resultExitCode = readRecordNumber(result, "exit_code", "exitCode");
|
|
198
|
+
const exitCode = processExitCode ?? resultExitCode ?? EXIT_CODE.SUCCESS;
|
|
199
|
+
const resultOk = readRecordBoolean(result, "ok");
|
|
200
|
+
const ok = resultOk ?? exitCode === EXIT_CODE.SUCCESS;
|
|
201
|
+
const errorCode = readRecordString(result, "error_code", "errorCode") ?? inferPostActionErrorCode(ok, exitCode);
|
|
202
|
+
const errorCategory = normalizeTelemetryErrorCategory(readRecordString(result, "error_category", "errorCategory")) ??
|
|
203
|
+
(!ok ? resolveTelemetryErrorCategory(errorCode) : undefined);
|
|
204
|
+
const errorMessage = !ok
|
|
205
|
+
? inferPostActionFailureMessage(result) ?? `command_exit_${exitCode}`
|
|
206
|
+
: undefined;
|
|
207
|
+
const commandResolution = normalizeTelemetryCommandResolution(readRecordString(result, "command_resolution", "commandResolution")) ??
|
|
208
|
+
deriveTelemetryCommandResolution({
|
|
209
|
+
ok,
|
|
210
|
+
errorCode,
|
|
211
|
+
errorCategory,
|
|
212
|
+
});
|
|
213
|
+
const resolutionStage = normalizeTelemetryResolutionStage(readRecordString(result, "resolution_stage", "resolutionStage")) ?? "execute";
|
|
214
|
+
return {
|
|
215
|
+
ok,
|
|
216
|
+
error: errorMessage,
|
|
217
|
+
exit_code: exitCode,
|
|
218
|
+
error_code: errorCode,
|
|
219
|
+
error_category: errorCategory,
|
|
220
|
+
command_resolution: commandResolution,
|
|
221
|
+
resolution_stage: resolutionStage,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
52
224
|
async function runAndClearAfterCommandHooks(outcome) {
|
|
53
225
|
const telemetryRuntime = activeTelemetryCommandContext;
|
|
54
226
|
activeTelemetryCommandContext = null;
|
|
@@ -59,6 +231,8 @@ async function runAndClearAfterCommandHooks(outcome) {
|
|
|
59
231
|
exit_code: outcome.exit_code,
|
|
60
232
|
error_code: outcome.error_code,
|
|
61
233
|
error_category: outcome.error_category,
|
|
234
|
+
command_resolution: outcome.command_resolution,
|
|
235
|
+
resolution_stage: outcome.resolution_stage,
|
|
62
236
|
});
|
|
63
237
|
const runtime = activeExtensionHookContext;
|
|
64
238
|
activeExtensionHookContext = null;
|
|
@@ -640,7 +814,10 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
640
814
|
global: globalOptions,
|
|
641
815
|
pm_root: fallbackPmRoot,
|
|
642
816
|
});
|
|
643
|
-
sentrySetCommandContext(commandPath, commandArgs, commandOptions
|
|
817
|
+
sentrySetCommandContext(commandPath, commandArgs, commandOptions, {
|
|
818
|
+
source_context: activeTelemetryCommandContext?.source_context,
|
|
819
|
+
source_context_source: activeTelemetryCommandContext?.source_context_source,
|
|
820
|
+
});
|
|
644
821
|
sentryStartCommandSpan(commandPath);
|
|
645
822
|
await enforceItemFormatWriteGateAndPreflightMigration(commandPath, commandOptions, fallbackPmRoot, defaultPreflightDecision());
|
|
646
823
|
return;
|
|
@@ -716,7 +893,10 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
716
893
|
global: globalOptions,
|
|
717
894
|
pm_root: runtimeExtensions.pmRoot,
|
|
718
895
|
});
|
|
719
|
-
sentrySetCommandContext(commandPath, commandArgs, commandOptions
|
|
896
|
+
sentrySetCommandContext(commandPath, commandArgs, commandOptions, {
|
|
897
|
+
source_context: activeTelemetryCommandContext?.source_context,
|
|
898
|
+
source_context_source: activeTelemetryCommandContext?.source_context_source,
|
|
899
|
+
});
|
|
720
900
|
sentryStartCommandSpan(commandPath);
|
|
721
901
|
const hookWarnings = await runBeforeCommandHooks(runtimeExtensions.hooks, {
|
|
722
902
|
command: commandPath,
|
|
@@ -733,8 +913,15 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
733
913
|
}
|
|
734
914
|
});
|
|
735
915
|
program.hook("postAction", async () => {
|
|
736
|
-
|
|
737
|
-
|
|
916
|
+
const outcome = buildPostActionTelemetryOutcome();
|
|
917
|
+
sentryFinishCommandSpan(outcome.ok, outcome.error, {
|
|
918
|
+
error_code: outcome.error_code,
|
|
919
|
+
error_category: outcome.error_category,
|
|
920
|
+
exit_code: outcome.exit_code,
|
|
921
|
+
command_resolution: outcome.command_resolution,
|
|
922
|
+
resolution_stage: outcome.resolution_stage,
|
|
923
|
+
});
|
|
924
|
+
await runAndClearAfterCommandHooks(outcome);
|
|
738
925
|
});
|
|
739
926
|
registerSetupCommands(program);
|
|
740
927
|
registerListQueryCommands(program);
|
|
@@ -762,6 +949,11 @@ async function main() {
|
|
|
762
949
|
const attemptedCommand = parseBootstrapCommandName(invocationArgv) ?? "<unknown>";
|
|
763
950
|
const emitTelemetryCommandError = async (params) => {
|
|
764
951
|
const errorCategory = resolveTelemetryErrorCategory(params.errorCode);
|
|
952
|
+
const commandResolution = deriveTelemetryCommandResolution({
|
|
953
|
+
ok: false,
|
|
954
|
+
errorCode: params.errorCode,
|
|
955
|
+
errorCategory,
|
|
956
|
+
});
|
|
765
957
|
await emitTelemetryErrorEvent({
|
|
766
958
|
command: params.command,
|
|
767
959
|
args: invocationArgv,
|
|
@@ -773,8 +965,13 @@ async function main() {
|
|
|
773
965
|
error_message: params.errorMessage,
|
|
774
966
|
exit_code: params.exitCode,
|
|
775
967
|
error_category: errorCategory,
|
|
968
|
+
command_resolution: commandResolution,
|
|
969
|
+
resolution_stage: params.resolutionStage,
|
|
776
970
|
});
|
|
777
|
-
return
|
|
971
|
+
return {
|
|
972
|
+
errorCategory,
|
|
973
|
+
commandResolution,
|
|
974
|
+
};
|
|
778
975
|
};
|
|
779
976
|
if (!bootstrapGlobal.noExtensions) {
|
|
780
977
|
const bootstrapSnapshot = await loadRuntimeExtensionSnapshot(bootstrapPmRoot);
|
|
@@ -782,7 +979,7 @@ async function main() {
|
|
|
782
979
|
}
|
|
783
980
|
if (error instanceof PmCliError) {
|
|
784
981
|
const classification = classifyPmCliError(error.message, error.context);
|
|
785
|
-
const errorCategory = await emitTelemetryCommandError({
|
|
982
|
+
const { errorCategory, commandResolution } = await emitTelemetryCommandError({
|
|
786
983
|
command: attemptedCommand,
|
|
787
984
|
errorCode: classification.code,
|
|
788
985
|
errorMessage: classification.detail,
|
|
@@ -790,6 +987,7 @@ async function main() {
|
|
|
790
987
|
options: {
|
|
791
988
|
bootstrap_global_options: bootstrapGlobal,
|
|
792
989
|
},
|
|
990
|
+
resolutionStage: "execute",
|
|
793
991
|
});
|
|
794
992
|
sentryLogCliUsageError({
|
|
795
993
|
command: attemptedCommand,
|
|
@@ -797,14 +995,25 @@ async function main() {
|
|
|
797
995
|
error_category: errorCategory,
|
|
798
996
|
exit_code: error.exitCode,
|
|
799
997
|
error_message: classification.detail,
|
|
998
|
+
command_resolution: commandResolution,
|
|
999
|
+
resolution_stage: "execute",
|
|
1000
|
+
source_context: activeTelemetryCommandContext?.source_context,
|
|
1001
|
+
});
|
|
1002
|
+
sentryFinishCommandSpan(false, error.message, {
|
|
1003
|
+
error_code: classification.code,
|
|
1004
|
+
error_category: errorCategory,
|
|
1005
|
+
exit_code: error.exitCode,
|
|
1006
|
+
command_resolution: commandResolution,
|
|
1007
|
+
resolution_stage: "execute",
|
|
800
1008
|
});
|
|
801
|
-
sentryFinishCommandSpan(false, error.message);
|
|
802
1009
|
await runAndClearAfterCommandHooks({
|
|
803
1010
|
ok: false,
|
|
804
1011
|
error: error.message,
|
|
805
1012
|
exit_code: error.exitCode,
|
|
806
1013
|
error_code: classification.code,
|
|
807
1014
|
error_category: errorCategory,
|
|
1015
|
+
command_resolution: commandResolution,
|
|
1016
|
+
resolution_stage: "execute",
|
|
808
1017
|
});
|
|
809
1018
|
sentryCaptureCliError(error);
|
|
810
1019
|
if (jsonErrors) {
|
|
@@ -831,7 +1040,7 @@ async function main() {
|
|
|
831
1040
|
unknownCommandExamples: usageContext.unknownCommandExamples,
|
|
832
1041
|
unknownCommandNextSteps: usageContext.unknownCommandNextSteps,
|
|
833
1042
|
});
|
|
834
|
-
const errorCategory = await emitTelemetryCommandError({
|
|
1043
|
+
const { errorCategory, commandResolution } = await emitTelemetryCommandError({
|
|
835
1044
|
command: unknownToken,
|
|
836
1045
|
errorCode: classification.code,
|
|
837
1046
|
errorMessage: classification.detail,
|
|
@@ -840,6 +1049,7 @@ async function main() {
|
|
|
840
1049
|
bootstrap_global_options: bootstrapGlobal,
|
|
841
1050
|
commander_code: code ?? "commander.helpDisplayed",
|
|
842
1051
|
},
|
|
1052
|
+
resolutionStage: "parse",
|
|
843
1053
|
});
|
|
844
1054
|
sentryLogCliUsageError({
|
|
845
1055
|
command: unknownToken,
|
|
@@ -847,17 +1057,28 @@ async function main() {
|
|
|
847
1057
|
error_category: errorCategory,
|
|
848
1058
|
exit_code: EXIT_CODE.USAGE,
|
|
849
1059
|
error_message: classification.detail,
|
|
1060
|
+
command_resolution: commandResolution,
|
|
1061
|
+
resolution_stage: "parse",
|
|
1062
|
+
source_context: activeTelemetryCommandContext?.source_context,
|
|
850
1063
|
});
|
|
851
1064
|
const renderedUsage = jsonErrors
|
|
852
1065
|
? await formatCommanderUsageJson({ message: unknownMessage }, program, activeRuntimeExtensionCommandDescriptors)
|
|
853
1066
|
: await formatCommanderUsageMessage({ message: unknownMessage }, program, activeRuntimeExtensionCommandDescriptors);
|
|
854
|
-
sentryFinishCommandSpan(false, unknownMessage
|
|
1067
|
+
sentryFinishCommandSpan(false, unknownMessage, {
|
|
1068
|
+
error_code: classification.code,
|
|
1069
|
+
error_category: errorCategory,
|
|
1070
|
+
exit_code: EXIT_CODE.USAGE,
|
|
1071
|
+
command_resolution: commandResolution,
|
|
1072
|
+
resolution_stage: "parse",
|
|
1073
|
+
});
|
|
855
1074
|
await runAndClearAfterCommandHooks({
|
|
856
1075
|
ok: false,
|
|
857
1076
|
error: unknownMessage,
|
|
858
1077
|
exit_code: EXIT_CODE.USAGE,
|
|
859
1078
|
error_code: classification.code,
|
|
860
1079
|
error_category: errorCategory,
|
|
1080
|
+
command_resolution: commandResolution,
|
|
1081
|
+
resolution_stage: "parse",
|
|
861
1082
|
});
|
|
862
1083
|
if (jsonErrors) {
|
|
863
1084
|
printError(renderedUsage);
|
|
@@ -869,19 +1090,31 @@ async function main() {
|
|
|
869
1090
|
process.exitCode = EXIT_CODE.USAGE;
|
|
870
1091
|
return;
|
|
871
1092
|
}
|
|
872
|
-
sentryFinishCommandSpan(true
|
|
1093
|
+
sentryFinishCommandSpan(true, undefined, {
|
|
1094
|
+
exit_code: EXIT_CODE.SUCCESS,
|
|
1095
|
+
command_resolution: "success",
|
|
1096
|
+
resolution_stage: "parse",
|
|
1097
|
+
});
|
|
873
1098
|
await runAndClearAfterCommandHooks({
|
|
874
1099
|
ok: true,
|
|
875
1100
|
exit_code: EXIT_CODE.SUCCESS,
|
|
1101
|
+
command_resolution: "success",
|
|
1102
|
+
resolution_stage: "parse",
|
|
876
1103
|
});
|
|
877
1104
|
process.exitCode = EXIT_CODE.SUCCESS;
|
|
878
1105
|
return;
|
|
879
1106
|
}
|
|
880
1107
|
if (code === "commander.version") {
|
|
881
|
-
sentryFinishCommandSpan(true
|
|
1108
|
+
sentryFinishCommandSpan(true, undefined, {
|
|
1109
|
+
exit_code: EXIT_CODE.SUCCESS,
|
|
1110
|
+
command_resolution: "success",
|
|
1111
|
+
resolution_stage: "parse",
|
|
1112
|
+
});
|
|
882
1113
|
await runAndClearAfterCommandHooks({
|
|
883
1114
|
ok: true,
|
|
884
1115
|
exit_code: EXIT_CODE.SUCCESS,
|
|
1116
|
+
command_resolution: "success",
|
|
1117
|
+
resolution_stage: "parse",
|
|
885
1118
|
});
|
|
886
1119
|
process.exitCode = EXIT_CODE.SUCCESS;
|
|
887
1120
|
return;
|
|
@@ -892,7 +1125,7 @@ async function main() {
|
|
|
892
1125
|
unknownCommandExamples: usageContext.unknownCommandExamples,
|
|
893
1126
|
unknownCommandNextSteps: usageContext.unknownCommandNextSteps,
|
|
894
1127
|
});
|
|
895
|
-
const errorCategory = await emitTelemetryCommandError({
|
|
1128
|
+
const { errorCategory, commandResolution } = await emitTelemetryCommandError({
|
|
896
1129
|
command: attemptedCommand,
|
|
897
1130
|
errorCode: classification.code,
|
|
898
1131
|
errorMessage: classification.detail,
|
|
@@ -901,6 +1134,7 @@ async function main() {
|
|
|
901
1134
|
bootstrap_global_options: bootstrapGlobal,
|
|
902
1135
|
commander_code: code,
|
|
903
1136
|
},
|
|
1137
|
+
resolutionStage: "parse",
|
|
904
1138
|
});
|
|
905
1139
|
sentryLogCliUsageError({
|
|
906
1140
|
command: attemptedCommand,
|
|
@@ -908,17 +1142,28 @@ async function main() {
|
|
|
908
1142
|
error_category: errorCategory,
|
|
909
1143
|
exit_code: EXIT_CODE.USAGE,
|
|
910
1144
|
error_message: classification.detail,
|
|
1145
|
+
command_resolution: commandResolution,
|
|
1146
|
+
resolution_stage: "parse",
|
|
1147
|
+
source_context: activeTelemetryCommandContext?.source_context,
|
|
911
1148
|
});
|
|
912
1149
|
const renderedUsage = jsonErrors
|
|
913
1150
|
? await formatCommanderUsageJson(error, program, activeRuntimeExtensionCommandDescriptors)
|
|
914
1151
|
: await formatCommanderUsageMessage(error, program, activeRuntimeExtensionCommandDescriptors);
|
|
915
|
-
sentryFinishCommandSpan(false, usageContext.message
|
|
1152
|
+
sentryFinishCommandSpan(false, usageContext.message, {
|
|
1153
|
+
error_code: classification.code,
|
|
1154
|
+
error_category: errorCategory,
|
|
1155
|
+
exit_code: EXIT_CODE.USAGE,
|
|
1156
|
+
command_resolution: commandResolution,
|
|
1157
|
+
resolution_stage: "parse",
|
|
1158
|
+
});
|
|
916
1159
|
await runAndClearAfterCommandHooks({
|
|
917
1160
|
ok: false,
|
|
918
1161
|
error: usageContext.message,
|
|
919
1162
|
exit_code: EXIT_CODE.USAGE,
|
|
920
1163
|
error_code: classification.code,
|
|
921
1164
|
error_category: errorCategory,
|
|
1165
|
+
command_resolution: commandResolution,
|
|
1166
|
+
resolution_stage: "parse",
|
|
922
1167
|
});
|
|
923
1168
|
if (jsonErrors) {
|
|
924
1169
|
printError(renderedUsage);
|
|
@@ -934,7 +1179,7 @@ async function main() {
|
|
|
934
1179
|
sentryCaptureCliError(error);
|
|
935
1180
|
const message = describeUnknownError(error);
|
|
936
1181
|
const classification = classifyUnknownError(message);
|
|
937
|
-
const errorCategory = await emitTelemetryCommandError({
|
|
1182
|
+
const { errorCategory, commandResolution } = await emitTelemetryCommandError({
|
|
938
1183
|
command: attemptedCommand,
|
|
939
1184
|
errorCode: classification.code,
|
|
940
1185
|
errorMessage: classification.detail,
|
|
@@ -942,14 +1187,23 @@ async function main() {
|
|
|
942
1187
|
options: {
|
|
943
1188
|
bootstrap_global_options: bootstrapGlobal,
|
|
944
1189
|
},
|
|
1190
|
+
resolutionStage: "execute",
|
|
1191
|
+
});
|
|
1192
|
+
sentryFinishCommandSpan(false, message, {
|
|
1193
|
+
error_code: classification.code,
|
|
1194
|
+
error_category: errorCategory,
|
|
1195
|
+
exit_code: EXIT_CODE.GENERIC_FAILURE,
|
|
1196
|
+
command_resolution: commandResolution,
|
|
1197
|
+
resolution_stage: "execute",
|
|
945
1198
|
});
|
|
946
|
-
sentryFinishCommandSpan(false, message);
|
|
947
1199
|
await runAndClearAfterCommandHooks({
|
|
948
1200
|
ok: false,
|
|
949
1201
|
error: message,
|
|
950
1202
|
exit_code: EXIT_CODE.GENERIC_FAILURE,
|
|
951
1203
|
error_code: classification.code,
|
|
952
1204
|
error_category: errorCategory,
|
|
1205
|
+
command_resolution: commandResolution,
|
|
1206
|
+
resolution_stage: "execute",
|
|
953
1207
|
});
|
|
954
1208
|
if (jsonErrors) {
|
|
955
1209
|
printError(JSON.stringify(formatUnknownErrorForJson(message, EXIT_CODE.GENERIC_FAILURE), null, 2));
|