1use thiserror::Error;
2use veloq_core::{ErrorCode, VeloqDiagnostic, sort::SortParseError};
3
4pub type NsysQueryResult<T> = Result<T, NsysQueryError>;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum SqlPhase {
8 Prepare,
9 Query,
10 Read,
11}
12
13impl SqlPhase {
14 fn code(self) -> ErrorCode {
15 match self {
16 Self::Prepare => ErrorCode::new("nsys.query.sql-prepare"),
17 Self::Query => ErrorCode::new("nsys.query.sql-query"),
18 Self::Read => ErrorCode::new("nsys.query.sql-read"),
19 }
20 }
21}
22
23impl std::fmt::Display for SqlPhase {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 f.write_str(match self {
26 Self::Prepare => "prepare",
27 Self::Query => "execute",
28 Self::Read => "read",
29 })
30 }
31}
32
33#[derive(Debug, Error)]
34pub enum NsysQueryError {
35 #[error("internal: {verb} cannot process `{kind}` rows after kind validation")]
36 InternalUnsupportedKind {
37 verb: &'static str,
38 kind: &'static str,
39 },
40
41 #[error("internal: {verb} SQL returned unrecognised kind tag `{kind}`")]
42 InternalSqlKindTagInvalid { verb: &'static str, kind: String },
43
44 #[error("internal: {verb} NVTX attribution cannot process `{kind}` rows after kind validation")]
45 InternalNvtxAttributionUnsupportedKind {
46 verb: &'static str,
47 kind: &'static str,
48 },
49
50 #[error("internal: {query} stats SQL returned no row")]
51 InternalStatsRowMissing { query: &'static str },
52
53 #[error("internal: ncu-command expected one launch recipe after count check ({selector})")]
54 InternalNcuCommandLaunchRecipeSelectionMissing { selector: &'static str },
55
56 #[error("internal: ncu-command {query} SQL returned no row")]
57 InternalNcuCommandSqlRowMissing { query: &'static str },
58
59 #[error("internal: slice builder for nvtx_rowid {row_id} disappeared between fold and emit")]
60 InternalSliceBuilderMissing { row_id: i64 },
61
62 #[error("reverse NVTX attribution failed to {mode} sidecar")]
63 NvtxReverseSidecarLoad {
64 mode: &'static str,
65 #[source]
66 source: Box<veloq_nsys_data::NsysDataError>,
67 },
68
69 #[error("{source}")]
70 TraceOpen {
71 #[source]
72 source: Box<veloq_nsys_data::NsysDataError>,
73 },
74
75 #[error("{source}")]
76 CorrelationIndexLoad {
77 #[source]
78 source: Box<veloq_nsys_data::NsysDataError>,
79 },
80
81 #[error("hardware extraction failed")]
82 HardwareExtract {
83 #[source]
84 source: Box<veloq_nsys_data::NsysDataError>,
85 },
86
87 #[error("time-window resolution failed")]
88 TimeWindowResolve {
89 #[source]
90 source: Box<veloq_nsys_data::NsysDataError>,
91 },
92
93 #[error("{source}")]
94 Data {
95 #[source]
96 source: Box<veloq_nsys_data::NsysDataError>,
97 },
98
99 #[error("summary metadata load failed")]
100 SummaryMetaLoad {
101 #[source]
102 source: Box<veloq_nsys_data::NsysDataError>,
103 },
104
105 #[error("NVTX-parent sidecar ensure failed")]
106 NvtxParentSidecarEnsure {
107 #[source]
108 source: Box<veloq_nsys_data::NsysDataError>,
109 },
110
111 #[error("NVTX nesting load failed")]
112 NvtxNestingLoad {
113 #[source]
114 source: Box<veloq_nsys_data::NsysDataError>,
115 },
116
117 #[error("NVTX tree load failed")]
118 NvtxTreeLoad {
119 #[source]
120 source: Box<veloq_nsys_data::NsysDataError>,
121 },
122
123 #[error("{area} failed to {phase} {label} SQL")]
124 Sql {
125 area: &'static str,
126 phase: SqlPhase,
127 label: String,
128 #[source]
129 source: duckdb::Error,
130 },
131
132 #[error("--limit must be at least 1 (got {limit})")]
133 LimitTooSmall { limit: usize },
134
135 #[error("invalid {flag} `{value}`")]
136 PositiveDurationInvalid {
137 flag: String,
138 value: String,
139 #[source]
140 source: veloq_core::time::TimeParseError,
141 },
142
143 #[error("{flag} must be positive (got {ns} ns)")]
144 PositiveDurationTooSmall { flag: String, ns: i64 },
145
146 #[error("`--name` and `--name-regex` are mutually exclusive; pick one")]
147 NameFilterConflict,
148
149 #[error(
150 "search doesn't surface cpu_sample rows; use `veloq metrics --type cpu-sampling` or `veloq inspect cpu_sample:<id>` instead"
151 )]
152 SearchCpuSampleUnsupported,
153
154 #[error("invalid search --sort")]
155 SearchSortInvalid {
156 #[source]
157 source: SortParseError,
158 },
159
160 #[error("invalid --interval `{value}`")]
161 TimelineIntervalInvalid {
162 value: String,
163 #[source]
164 source: veloq_core::time::TimeParseError,
165 },
166
167 #[error("--interval must be positive (got {interval_ns} ns)")]
168 TimelineIntervalTooSmall { interval_ns: i64 },
169
170 #[error("timeline only buckets GPU kinds (kernel/memcpy/memset/graph); got `{kind}`")]
171 TimelineKindNotAllowed { kind: &'static str },
172
173 #[error("viz timeline requires --from and --to")]
174 VizTimelineWindowRequired,
175
176 #[error("unknown viz timeline track kind `{kind}`")]
177 VizTimelineUnknownTrackKind { kind: String },
178
179 #[error("invalid viz timeline track selector `{selector}`; expected name=value")]
180 VizTimelineInvalidSelector { selector: String },
181
182 #[error("unknown selector `{selector}` for viz timeline track `{kind}`")]
183 VizTimelineUnknownSelector { kind: String, selector: String },
184
185 #[error("viz timeline selector `{selector}` must be a non-negative integer")]
186 VizTimelineSelectorNonNegativeInt { selector: String },
187
188 #[error("viz timeline selector `{selector}` must be a positive integer")]
189 VizTimelineSelectorPositiveInt { selector: String },
190
191 #[error("viz timeline --highlight-kernels requires `top=<n>`")]
192 VizTimelineHighlightTopRequired,
193
194 #[error("unknown viz timeline highlight scope `{scope}` (expected: name, instance)")]
195 VizTimelineUnknownHighlightScope { scope: String },
196
197 #[error(
198 "unknown viz timeline highlight metric `{metric}` (expected: duration, count, max-duration)"
199 )]
200 VizTimelineUnknownHighlightMetric { metric: String },
201
202 #[error("viz timeline track `cuda-stream` requires `device=<id>`")]
203 VizTimelineCudaStreamDeviceRequired,
204
205 #[error("viz timeline track `cuda-stream` requires `stream=<id>`")]
206 VizTimelineCudaStreamStreamRequired,
207
208 #[error("viz timeline track `cuda-stream` does not accept `device=all`")]
209 VizTimelineCudaStreamDeviceAll,
210
211 #[error("visualization artifact failed")]
212 VizTimelineArtifact {
213 #[source]
214 source: veloq_vis::VisualizationError,
215 },
216
217 #[error("unknown --group-by `{group_by}` for slices --aggregate (expected: name, path)")]
218 SlicesUnknownGroupBy { group_by: String },
219
220 #[error("invalid slices --sort")]
221 SlicesSortInvalid {
222 #[source]
223 source: SortParseError,
224 },
225
226 #[error(
227 "slices requires `{table}`, which is not present in this trace (NVTX attribution is unavailable)"
228 )]
229 SlicesPrereqTableMissing { table: &'static str },
230
231 #[error(
232 "slices requires at least one GPU event table (kernel/memcpy/memset), but none is present in this trace"
233 )]
234 SlicesGpuEventTableMissing,
235
236 #[error("--nvtx attribution requires `{table}`, which is not present in this trace")]
237 NvtxAttributionPrereqTableMissing { table: &'static str },
238
239 #[error(
240 "--nvtx attribution needs at least one attributable kind (kernel/memcpy/memset/sync/runtime); requested kinds don't match any present table"
241 )]
242 NvtxAttributionNoAttributableTableMatch,
243
244 #[error(
245 "--nvtx attribution on kernel/memcpy/memset/sync requires `TARGET_INFO_CUDA_CONTEXT_INFO`, which is not present in this trace (GPU activity rows cannot be bridged to runtime rows without the context-info table; the lookup would silently miss every kernel)"
246 )]
247 NvtxAttributionContextInfoMissing,
248
249 #[error("graph-replays --nvtx requires `{table}`, which is not present in this trace")]
250 GraphReplaysNvtxPrereqTableMissing { table: &'static str },
251
252 #[error("invalid graph-replays --sort")]
253 GraphReplaysSortInvalid {
254 #[source]
255 source: SortParseError,
256 },
257
258 #[error("--group-by name axis specified twice (`{previous}` and `{current}`); pick one")]
259 StatsGroupByNameAxisConflict {
260 previous: &'static str,
261 current: &'static str,
262 },
263
264 #[error(
265 "unknown --group-by token `{token}` (expected: short, demangled, mangled, no-name, device, stream, context, graph, graph_node, nvtx-parent, nvtx-path, grid_block)"
266 )]
267 StatsGroupByUnknownToken { token: String },
268
269 #[error(
270 "stats only aggregates duration-bearing kinds (kernel/memcpy/memset/sync/graph/nvtx); got `{kind}`"
271 )]
272 StatsKindNotAllowed { kind: &'static str },
273
274 #[error(
275 "stats: --group-by device/context/stream/graph/graph_node has no meaning for `--type {kinds}`; every kind in the set is CPU-side and carries no device/stream/graph columns. Group by name (the default) or mix in a GPU-side kind (kernel/memcpy/memset/sync/graph/cuda_event) to split GPU rows by device while keeping the CPU-side rows in their own null bucket."
276 )]
277 StatsGroupByLocationAxisConflict { kinds: String },
278
279 #[error(
280 "{verb}: --group-by {axis} requires a device parent axis because {axis} ids are device-local; use `--device <id>` for one device or include `device,{axis}` in --group-by for comparison"
281 )]
282 StatsGroupByDeviceParentRequired {
283 verb: &'static str,
284 axis: &'static str,
285 },
286
287 #[error(
288 "stats: --group-by grid_block is kernel-only; gridX/Y/Z and blockX/Y/Z columns live on CUPTI_ACTIVITY_KIND_KERNEL and nowhere else. Got `--type {kind}` in the explicit kind set; either drop the non-kernel kinds or unset --group-by grid_block"
289 )]
290 StatsGridBlockKindConflict { kind: &'static str },
291
292 #[error("invalid stats --sort")]
293 StatsSortInvalid {
294 #[source]
295 source: SortParseError,
296 },
297
298 #[error(
299 "--by size only aggregates byte-carrying kinds (memcpy/memset); got `--type {kind}`; drop the kind or unset --by size"
300 )]
301 StatsBySizeKindNotAllowed { kind: &'static str },
302
303 #[error(
304 "stats-by-size does not yet support --group-by {axes}; supported axes today are the name axis (short/demangled/mangled/no-name) and device/context/stream"
305 )]
306 StatsBySizeGroupByUnsupported { axes: String },
307
308 #[error("invalid stats-by-size --sort")]
309 StatsBySizeSortInvalid {
310 #[source]
311 source: SortParseError,
312 },
313
314 #[error(
315 "stats: --group-by nvtx-parent and nvtx-path are mutually exclusive; pick rowid-level parent buckets or path-level hierarchy buckets"
316 )]
317 StatsNvtxHierarchyAxesConflict,
318
319 #[error(
320 "stats: --group-by {axis_name} is mutually exclusive with graph/graph_node; NVTX attribution walks host-thread containment, captured-graph axes walk device-side state. Pick one model per query"
321 )]
322 StatsNvtxHierarchyGraphAxisConflict { axis_name: &'static str },
323
324 #[error(
325 "stats: --group-by {axis_name} + --type nvtx is a self-attribute tautology; NVTX rows are the ranges NVTX hierarchy axes attribute other kinds to. Drop one of the two flags"
326 )]
327 StatsNvtxHierarchySelfAttribute { axis_name: &'static str },
328
329 #[error("--group-by {axis_name} requires `{table}`, which is not present in this trace")]
330 StatsNvtxHierarchyPrereqTableMissing {
331 axis_name: &'static str,
332 table: &'static str,
333 },
334
335 #[error(
336 "--group-by {axis_name} on kernel/memcpy/memset/sync requires `TARGET_INFO_CUDA_CONTEXT_INFO`, which is not present in this trace (GPU activity rows cannot be bridged to runtime rows without the context-info table; the lookup would silently miss every kernel)"
337 )]
338 StatsNvtxHierarchyContextInfoMissing { axis_name: &'static str },
339
340 #[error("unknown --env `{env}` (expected: none, safe, all)")]
341 NcuCommandUnknownEnv { env: String },
342
343 #[error(
344 "ncu-command requires a CUDA kernel row id (got `{row_id}`); use `search --type kernel` first"
345 )]
346 NcuCommandRowIdKind { row_id: String },
347
348 #[error("ncu-command requires `CUPTI_ACTIVITY_KIND_KERNEL`, which is absent from this trace")]
349 NcuCommandKernelTableMissing,
350
351 #[error(
352 "ncu-command requires `META_DATA_CAPTURE` to recover the original command, argv, cwd, and env"
353 )]
354 NcuCommandMetadataTableMissing,
355
356 #[error("kernel row `{row_id}` was not found")]
357 NcuCommandKernelNotFound { row_id: String },
358
359 #[error("kernel row `{row_id}` has neither a resolved shortName nor demangledName")]
360 NcuCommandKernelNameMissing { row_id: String },
361
362 #[error("META_DATA_CAPTURE contains no PROCESS_N:COMMAND launch recipe")]
363 NcuCommandLaunchRecipeMissing,
364
365 #[error(
366 "multiple META_DATA_CAPTURE launch recipes match process `{process}`; cannot choose an NCU target command"
367 )]
368 NcuCommandAmbiguousProcessRecipe { process: String },
369
370 #[error(
371 "multiple META_DATA_CAPTURE launch recipes are present and none matched the selected kernel process"
372 )]
373 NcuCommandAmbiguousLaunchRecipe,
374
375 #[error(
376 "{verb}: {axes} cannot be combined with `--type {kinds}`; these kinds have no device/stream columns"
377 )]
378 KindLocationFilterConflict {
379 verb: String,
380 axes: &'static str,
381 kinds: String,
382 },
383
384 #[error(
385 "{verb}: --nvtx cannot scope `--type {kinds}`; NVTX attribution for these kinds is experimental and not yet implemented"
386 )]
387 KindNvtxAttributionUnsupported { verb: String, kinds: String },
388
389 #[error("invalid --scope `{scope}`; expected device, stream, or trace")]
390 GapsInvalidScope { scope: String },
391
392 #[error("invalid --min-duration `{value}`")]
393 GapsMinDurationInvalid {
394 value: String,
395 #[source]
396 source: veloq_core::time::TimeParseError,
397 },
398
399 #[error("--min must be positive (got {min_ns} ns)")]
400 GapsMinTooSmall { min_ns: i64 },
401
402 #[error(
403 "--stream <id> requires --scope stream; under --scope {scope} rows have no stream axis"
404 )]
405 GapsStreamRequiresStreamScope { scope: &'static str },
406
407 #[error(
408 "--device {device} is incompatible with --scope trace; use --scope device --device {device}"
409 )]
410 GapsDeviceInTraceScope { device: i32 },
411
412 #[error(
413 "--sort stream requires --scope stream; under --scope {scope} rows have no stream axis"
414 )]
415 GapsSortStreamRequiresStreamScope { scope: &'static str },
416
417 #[error(
418 "--sort device is incompatible with --scope trace; trace-scope gaps are not partitioned by device"
419 )]
420 GapsSortDeviceInTraceScope,
421
422 #[error("invalid gaps --sort")]
423 GapsSortInvalid {
424 #[source]
425 source: SortParseError,
426 },
427
428 #[error("--sort doesn't apply in bucketed mode; buckets are time-ordered")]
429 MetricsSortWithBucket,
430
431 #[error("--bucket must be positive (got {bucket_ns} ns)")]
432 MetricsBucketTooSmall { bucket_ns: i64 },
433
434 #[error("invalid metrics --sort")]
435 MetricsSortInvalid {
436 #[source]
437 source: SortParseError,
438 },
439
440 #[error(
441 "unknown `--type {metric_source}` for metrics (supported: gpu, nic, cpu-sampling, cpu-sched)"
442 )]
443 MetricsUnknownSource { metric_source: String },
444
445 #[error(
446 "metrics --type gpu requires `GPU_METRICS`, which is absent from this trace; re-capture with `nsys profile --gpu-metrics-devices=…`"
447 )]
448 MetricsGpuTableMissing,
449
450 #[error(
451 "metrics --type gpu requires `TARGET_INFO_GPU_METRICS` (counter dictionary); likely a partial or corrupted nsys export"
452 )]
453 MetricsGpuDictionaryMissing,
454
455 #[error(
456 "no GPU counters match `--counter {glob}`; run `veloq metrics <trace> --type gpu` (no --counter) to list available names"
457 )]
458 MetricsGpuCounterNoMatch { glob: String },
459
460 #[error(
461 "metrics --type nic requires `NET_NIC_METRIC`, which is absent from this trace; re-capture with `nsys profile --nic-metrics=lf` (or `hf`) and verify `nsys status --network` passes"
462 )]
463 MetricsNicTableMissing,
464
465 #[error(
466 "metrics --type nic requires `TARGET_INFO_NETWORK_METRICS` (counter dictionary); likely a partial or corrupted nsys export"
467 )]
468 MetricsNicDictionaryMissing,
469
470 #[error(
471 "metrics --type nic requires `NIC_ID_MAP` (globalId to nicId mapping); likely a partial or corrupted nsys export"
472 )]
473 MetricsNicIdMapMissing,
474
475 #[error(
476 "metrics --type nic requires `TARGET_INFO_NIC_INFO` (NIC identity); likely a partial or corrupted nsys export"
477 )]
478 MetricsNicInfoMissing,
479
480 #[error(
481 "no NIC counters match `--counter {glob}`; run `veloq metrics <trace> --type nic` (no --counter) to list available names"
482 )]
483 MetricsNicCounterNoMatch { glob: String },
484
485 #[error(
486 "metrics --type cpu-sampling requires `COMPOSITE_EVENTS`, which is absent from this trace; re-capture with `nsys profile --sample=process-tree`"
487 )]
488 MetricsCpuSamplingCompositeEventsMissing,
489
490 #[error(
491 "unknown --group-by `{axis}` for cpu-sampling (expected: symbol, tid, cpu, module, stack)"
492 )]
493 MetricsCpuSamplingUnknownGroupBy { axis: String },
494
495 #[error(
496 "--group-by {group_by} needs `SAMPLING_CALLCHAINS` (per-sample stacks), which is absent from this trace; either re-capture with stack sampling enabled or switch to `--group-by tid` / `cpu`"
497 )]
498 MetricsCpuSamplingCallchainsMissing { group_by: &'static str },
499
500 #[error(
501 "--group-by {group_by} bucketed mode needs `SAMPLING_CALLCHAINS`, which is absent from this trace"
502 )]
503 MetricsCpuSamplingBucketCallchainsMissing { group_by: &'static str },
504
505 #[error(
506 "--group-by stack does not support --bucket yet; use summary mode for stack aggregation or switch to symbol/module/tid/cpu for bucketed samples"
507 )]
508 MetricsCpuSamplingStackBucketUnsupported,
509
510 #[error(
511 "--name doesn't apply on --group-by {group_by} (keys are numeric); drop it or switch to `--group-by symbol` / `module` / `stack`"
512 )]
513 MetricsCpuSamplingNameOnNumericAxis { group_by: &'static str },
514
515 #[error(
516 "metrics --type cpu-sched requires `SCHED_EVENTS`, which is absent from this trace; re-capture with `nsys profile --cpuctxsw=process-tree` (or `system-wide`)"
517 )]
518 MetricsCpuSchedEventsMissing,
519
520 #[error("unknown --group-by `{axis}` for cpu-sched (expected: tid, cpu, state)")]
521 MetricsCpuSchedUnknownGroupBy { axis: String },
522
523 #[error("--top-nodes must be at least 1 (got 0)")]
524 GraphReplaysTopNodesTooSmall,
525}
526
527impl NsysQueryError {
528 pub fn internal_unsupported_kind(verb: &'static str, kind: &'static str) -> Self {
529 Self::InternalUnsupportedKind { verb, kind }
530 }
531
532 pub fn internal_sql_kind_tag_invalid(verb: &'static str, kind: &str) -> Self {
533 Self::InternalSqlKindTagInvalid {
534 verb,
535 kind: kind.to_string(),
536 }
537 }
538
539 pub fn internal_nvtx_attribution_unsupported_kind(
540 verb: &'static str,
541 kind: &'static str,
542 ) -> Self {
543 Self::InternalNvtxAttributionUnsupportedKind { verb, kind }
544 }
545
546 pub fn internal_stats_row_missing(query: &'static str) -> Self {
547 Self::InternalStatsRowMissing { query }
548 }
549
550 pub fn internal_slice_builder_missing(row_id: i64) -> Self {
551 Self::InternalSliceBuilderMissing { row_id }
552 }
553
554 pub fn nvtx_reverse_sidecar_load(
555 mode: &'static str,
556 source: veloq_nsys_data::NsysDataError,
557 ) -> Self {
558 Self::NvtxReverseSidecarLoad {
559 mode,
560 source: Box::new(source),
561 }
562 }
563
564 pub fn trace_open(source: veloq_nsys_data::NsysDataError) -> Self {
565 Self::TraceOpen {
566 source: Box::new(source),
567 }
568 }
569
570 pub fn correlation_index_load(source: veloq_nsys_data::NsysDataError) -> Self {
571 Self::CorrelationIndexLoad {
572 source: Box::new(source),
573 }
574 }
575
576 pub fn hardware_extract(source: veloq_nsys_data::NsysDataError) -> Self {
577 Self::HardwareExtract {
578 source: Box::new(source),
579 }
580 }
581
582 pub fn time_window_resolve(source: veloq_nsys_data::NsysDataError) -> Self {
583 Self::TimeWindowResolve {
584 source: Box::new(source),
585 }
586 }
587
588 pub fn data(source: veloq_nsys_data::NsysDataError) -> Self {
589 Self::Data {
590 source: Box::new(source),
591 }
592 }
593
594 pub fn summary_meta_load(source: veloq_nsys_data::NsysDataError) -> Self {
595 Self::SummaryMetaLoad {
596 source: Box::new(source),
597 }
598 }
599
600 pub fn nvtx_parent_sidecar_ensure(source: veloq_nsys_data::NsysDataError) -> Self {
601 Self::NvtxParentSidecarEnsure {
602 source: Box::new(source),
603 }
604 }
605
606 pub fn nvtx_nesting_load(source: veloq_nsys_data::NsysDataError) -> Self {
607 Self::NvtxNestingLoad {
608 source: Box::new(source),
609 }
610 }
611
612 pub fn nvtx_tree_load(source: veloq_nsys_data::NsysDataError) -> Self {
613 Self::NvtxTreeLoad {
614 source: Box::new(source),
615 }
616 }
617
618 pub fn sql(
619 area: &'static str,
620 phase: SqlPhase,
621 label: impl Into<String>,
622 source: duckdb::Error,
623 ) -> Self {
624 Self::Sql {
625 area,
626 phase,
627 label: label.into(),
628 source,
629 }
630 }
631
632 pub fn sql_prepare(
633 area: &'static str,
634 label: impl Into<String>,
635 source: duckdb::Error,
636 ) -> Self {
637 Self::sql(area, SqlPhase::Prepare, label, source)
638 }
639
640 pub fn sql_query(area: &'static str, label: impl Into<String>, source: duckdb::Error) -> Self {
641 Self::sql(area, SqlPhase::Query, label, source)
642 }
643
644 pub fn sql_read(area: &'static str, label: impl Into<String>, source: duckdb::Error) -> Self {
645 Self::sql(area, SqlPhase::Read, label, source)
646 }
647
648 pub fn sql_parts(&self) -> Option<(&'static str, SqlPhase, &str)> {
649 match self {
650 Self::Sql {
651 area, phase, label, ..
652 } => Some((*area, *phase, label.as_str())),
653 _ => None,
654 }
655 }
656
657 pub fn search_sort_invalid(source: SortParseError) -> Self {
658 Self::SearchSortInvalid { source }
659 }
660
661 pub fn kind_location_filter_conflict(verb: &str, axes: &'static str, kinds: String) -> Self {
662 Self::KindLocationFilterConflict {
663 verb: verb.to_string(),
664 axes,
665 kinds,
666 }
667 }
668
669 pub fn kind_nvtx_attribution_unsupported(verb: &str, kinds: String) -> Self {
670 Self::KindNvtxAttributionUnsupported {
671 verb: verb.to_string(),
672 kinds,
673 }
674 }
675
676 pub fn gaps_invalid_scope(scope: &str) -> Self {
677 Self::GapsInvalidScope {
678 scope: scope.to_string(),
679 }
680 }
681
682 pub fn gaps_sort_invalid(source: SortParseError) -> Self {
683 Self::GapsSortInvalid { source }
684 }
685
686 pub fn graph_replays_sort_invalid(source: SortParseError) -> Self {
687 Self::GraphReplaysSortInvalid { source }
688 }
689
690 pub fn metrics_unknown_source(metric_source: &str) -> Self {
691 Self::MetricsUnknownSource {
692 metric_source: metric_source.to_string(),
693 }
694 }
695
696 pub fn metrics_sort_invalid(source: SortParseError) -> Self {
697 Self::MetricsSortInvalid { source }
698 }
699
700 pub fn metrics_gpu_counter_no_match(glob: &str) -> Self {
701 Self::MetricsGpuCounterNoMatch {
702 glob: glob.to_string(),
703 }
704 }
705
706 pub fn metrics_nic_counter_no_match(glob: &str) -> Self {
707 Self::MetricsNicCounterNoMatch {
708 glob: glob.to_string(),
709 }
710 }
711
712 pub fn metrics_cpu_sampling_unknown_group_by(axis: &str) -> Self {
713 Self::MetricsCpuSamplingUnknownGroupBy {
714 axis: axis.to_string(),
715 }
716 }
717
718 pub fn metrics_cpu_sched_unknown_group_by(axis: &str) -> Self {
719 Self::MetricsCpuSchedUnknownGroupBy {
720 axis: axis.to_string(),
721 }
722 }
723
724 pub fn slices_unknown_group_by(group_by: &str) -> Self {
725 Self::SlicesUnknownGroupBy {
726 group_by: group_by.to_string(),
727 }
728 }
729
730 pub fn slices_sort_invalid(source: SortParseError) -> Self {
731 Self::SlicesSortInvalid { source }
732 }
733
734 pub fn stats_group_by_unknown_token(token: &str) -> Self {
735 Self::StatsGroupByUnknownToken {
736 token: token.to_string(),
737 }
738 }
739
740 pub fn stats_group_by_location_axis_conflict(kinds: String) -> Self {
741 Self::StatsGroupByLocationAxisConflict { kinds }
742 }
743
744 pub fn stats_by_size_group_by_unsupported(axes: String) -> Self {
745 Self::StatsBySizeGroupByUnsupported { axes }
746 }
747
748 pub fn stats_sort_invalid(source: SortParseError) -> Self {
749 Self::StatsSortInvalid { source }
750 }
751
752 pub fn stats_by_size_sort_invalid(source: SortParseError) -> Self {
753 Self::StatsBySizeSortInvalid { source }
754 }
755
756 pub fn ncu_command_unknown_env(env: &str) -> Self {
757 Self::NcuCommandUnknownEnv {
758 env: env.to_string(),
759 }
760 }
761
762 pub fn ncu_command_row_id_kind(row_id: impl ToString) -> Self {
763 Self::NcuCommandRowIdKind {
764 row_id: row_id.to_string(),
765 }
766 }
767
768 pub fn ncu_command_kernel_not_found(row_id: impl ToString) -> Self {
769 Self::NcuCommandKernelNotFound {
770 row_id: row_id.to_string(),
771 }
772 }
773
774 pub fn ncu_command_kernel_name_missing(row_id: impl ToString) -> Self {
775 Self::NcuCommandKernelNameMissing {
776 row_id: row_id.to_string(),
777 }
778 }
779
780 pub fn ncu_command_ambiguous_process_recipe(process: &str) -> Self {
781 Self::NcuCommandAmbiguousProcessRecipe {
782 process: process.to_string(),
783 }
784 }
785}
786
787impl VeloqDiagnostic for NsysQueryError {
788 fn code(&self) -> ErrorCode {
789 match self {
790 Self::InternalUnsupportedKind { .. } => {
791 ErrorCode::new("nsys.internal.unsupported-kind")
792 }
793 Self::InternalSqlKindTagInvalid { .. } => {
794 ErrorCode::new("nsys.internal.sql-kind-tag-invalid")
795 }
796 Self::InternalNvtxAttributionUnsupportedKind { .. } => {
797 ErrorCode::new("nsys.internal.nvtx-attribution-unsupported-kind")
798 }
799 Self::InternalStatsRowMissing { .. } => {
800 ErrorCode::new("nsys.internal.stats-row-missing")
801 }
802 Self::InternalNcuCommandLaunchRecipeSelectionMissing { .. } => {
803 ErrorCode::new("nsys.internal.ncu-command-launch-recipe-selection-missing")
804 }
805 Self::InternalNcuCommandSqlRowMissing { .. } => {
806 ErrorCode::new("nsys.internal.ncu-command-sql-row-missing")
807 }
808 Self::InternalSliceBuilderMissing { .. } => {
809 ErrorCode::new("nsys.internal.slice-builder-missing")
810 }
811 Self::NvtxReverseSidecarLoad { .. } => {
812 ErrorCode::new("nsys.query.nvtx-reverse-sidecar-load")
813 }
814 Self::TraceOpen { source }
815 | Self::CorrelationIndexLoad { source }
816 | Self::Data { source } => source.code(),
817 Self::HardwareExtract { .. } => ErrorCode::new("nsys.query.hardware-extract"),
818 Self::TimeWindowResolve { .. } => ErrorCode::new("nsys.query.time-window-resolve"),
819 Self::SummaryMetaLoad { .. } => ErrorCode::new("nsys.query.summary-meta-load"),
820 Self::NvtxParentSidecarEnsure { .. } => {
821 ErrorCode::new("nsys.query.nvtx-parent-sidecar-ensure")
822 }
823 Self::NvtxNestingLoad { .. } => ErrorCode::new("nsys.query.nvtx-nesting-load"),
824 Self::NvtxTreeLoad { .. } => ErrorCode::new("nsys.query.nvtx-tree-load"),
825 Self::Sql { phase, .. } => phase.code(),
826 Self::LimitTooSmall { .. } => ErrorCode::new("nsys.query.limit-too-small"),
827 Self::PositiveDurationInvalid { .. } => {
828 ErrorCode::new("nsys.query.invalid-positive-duration")
829 }
830 Self::PositiveDurationTooSmall { .. } => {
831 ErrorCode::new("nsys.query.positive-duration-too-small")
832 }
833 Self::NameFilterConflict => ErrorCode::new("nsys.query.name-filter-conflict"),
834 Self::SearchCpuSampleUnsupported => {
835 ErrorCode::new("nsys.query.search-cpu-sample-unsupported")
836 }
837 Self::SearchSortInvalid { .. } => ErrorCode::new("nsys.query.search-sort-invalid"),
838 Self::TimelineIntervalInvalid { .. } => {
839 ErrorCode::new("nsys.query.timeline-interval-invalid")
840 }
841 Self::TimelineIntervalTooSmall { .. } => {
842 ErrorCode::new("nsys.query.timeline-interval-too-small")
843 }
844 Self::TimelineKindNotAllowed { .. } => {
845 ErrorCode::new("nsys.query.timeline-kind-not-allowed")
846 }
847 Self::VizTimelineWindowRequired => {
848 ErrorCode::new("nsys.query.viz-timeline-window-required")
849 }
850 Self::VizTimelineUnknownTrackKind { .. } => {
851 ErrorCode::new("nsys.query.viz-timeline-unknown-track-kind")
852 }
853 Self::VizTimelineInvalidSelector { .. } => {
854 ErrorCode::new("nsys.query.viz-timeline-invalid-selector")
855 }
856 Self::VizTimelineUnknownSelector { .. } => {
857 ErrorCode::new("nsys.query.viz-timeline-unknown-selector")
858 }
859 Self::VizTimelineSelectorNonNegativeInt { .. } => {
860 ErrorCode::new("nsys.query.viz-timeline-selector-non-negative-int")
861 }
862 Self::VizTimelineSelectorPositiveInt { .. } => {
863 ErrorCode::new("nsys.query.viz-timeline-selector-positive-int")
864 }
865 Self::VizTimelineHighlightTopRequired => {
866 ErrorCode::new("nsys.query.viz-timeline-highlight-top-required")
867 }
868 Self::VizTimelineUnknownHighlightScope { .. } => {
869 ErrorCode::new("nsys.query.viz-timeline-unknown-highlight-scope")
870 }
871 Self::VizTimelineUnknownHighlightMetric { .. } => {
872 ErrorCode::new("nsys.query.viz-timeline-unknown-highlight-metric")
873 }
874 Self::VizTimelineCudaStreamDeviceRequired => {
875 ErrorCode::new("nsys.query.viz-timeline-cuda-stream-device-required")
876 }
877 Self::VizTimelineCudaStreamStreamRequired => {
878 ErrorCode::new("nsys.query.viz-timeline-cuda-stream-stream-required")
879 }
880 Self::VizTimelineCudaStreamDeviceAll => {
881 ErrorCode::new("nsys.query.viz-timeline-cuda-stream-device-all")
882 }
883 Self::VizTimelineArtifact { source } => source.code(),
884 Self::SlicesUnknownGroupBy { .. } => {
885 ErrorCode::new("nsys.query.slices-unknown-group-by")
886 }
887 Self::SlicesSortInvalid { .. } => ErrorCode::new("nsys.query.slices-sort-invalid"),
888 Self::SlicesPrereqTableMissing { .. } => {
889 ErrorCode::new("nsys.query.slices-prereq-missing")
890 }
891 Self::SlicesGpuEventTableMissing => {
892 ErrorCode::new("nsys.query.slices-gpu-event-table-missing")
893 }
894 Self::NvtxAttributionPrereqTableMissing { .. } => {
895 ErrorCode::new("nsys.query.nvtx-attribution-prereq-missing")
896 }
897 Self::NvtxAttributionNoAttributableTableMatch => {
898 ErrorCode::new("nsys.query.nvtx-attribution-no-attributable-kind")
899 }
900 Self::NvtxAttributionContextInfoMissing => {
901 ErrorCode::new("nsys.query.nvtx-attribution-context-info-missing")
902 }
903 Self::GraphReplaysNvtxPrereqTableMissing { .. } => {
904 ErrorCode::new("nsys.query.graph-replays-nvtx-prereq-missing")
905 }
906 Self::GraphReplaysSortInvalid { .. } => {
907 ErrorCode::new("nsys.query.graph-replays-sort-invalid")
908 }
909 Self::StatsGroupByNameAxisConflict { .. } => {
910 ErrorCode::new("nsys.query.stats-group-by-name-axis-conflict")
911 }
912 Self::StatsGroupByUnknownToken { .. } => {
913 ErrorCode::new("nsys.query.stats-group-by-unknown-token")
914 }
915 Self::StatsKindNotAllowed { .. } => ErrorCode::new("nsys.query.stats-kind-not-allowed"),
916 Self::StatsGroupByLocationAxisConflict { .. } => {
917 ErrorCode::new("nsys.query.stats-group-by-location-axis-conflict")
918 }
919 Self::StatsGroupByDeviceParentRequired { .. } => {
920 ErrorCode::new("nsys.query.stats-group-by-device-parent-required")
921 }
922 Self::StatsGridBlockKindConflict { .. } => {
923 ErrorCode::new("nsys.query.stats-grid-block-kind-conflict")
924 }
925 Self::StatsSortInvalid { .. } => ErrorCode::new("nsys.query.stats-sort-invalid"),
926 Self::StatsBySizeKindNotAllowed { .. } => {
927 ErrorCode::new("nsys.query.stats-by-size-kind-not-allowed")
928 }
929 Self::StatsBySizeGroupByUnsupported { .. } => {
930 ErrorCode::new("nsys.query.stats-by-size-group-by-unsupported")
931 }
932 Self::StatsBySizeSortInvalid { .. } => {
933 ErrorCode::new("nsys.query.stats-by-size-sort-invalid")
934 }
935 Self::StatsNvtxHierarchyAxesConflict => {
936 ErrorCode::new("nsys.query.stats-nvtx-hierarchy-axis-conflict")
937 }
938 Self::StatsNvtxHierarchyGraphAxisConflict { .. } => {
939 ErrorCode::new("nsys.query.stats-nvtx-hierarchy-graph-axis-conflict")
940 }
941 Self::StatsNvtxHierarchySelfAttribute { .. } => {
942 ErrorCode::new("nsys.query.stats-nvtx-hierarchy-self-attribute")
943 }
944 Self::StatsNvtxHierarchyPrereqTableMissing { .. } => {
945 ErrorCode::new("nsys.query.stats-nvtx-hierarchy-prereq-missing")
946 }
947 Self::StatsNvtxHierarchyContextInfoMissing { .. } => {
948 ErrorCode::new("nsys.query.stats-nvtx-hierarchy-context-info-missing")
949 }
950 Self::NcuCommandUnknownEnv { .. } => {
951 ErrorCode::new("nsys.query.ncu-command-unknown-env")
952 }
953 Self::NcuCommandRowIdKind { .. } => {
954 ErrorCode::new("nsys.query.ncu-command-row-id-kind")
955 }
956 Self::NcuCommandKernelTableMissing => {
957 ErrorCode::new("nsys.query.ncu-command-kernel-table-missing")
958 }
959 Self::NcuCommandMetadataTableMissing => {
960 ErrorCode::new("nsys.query.ncu-command-metadata-table-missing")
961 }
962 Self::NcuCommandKernelNotFound { .. } => {
963 ErrorCode::new("nsys.query.ncu-command-kernel-not-found")
964 }
965 Self::NcuCommandKernelNameMissing { .. } => {
966 ErrorCode::new("nsys.query.ncu-command-kernel-name-missing")
967 }
968 Self::NcuCommandLaunchRecipeMissing => {
969 ErrorCode::new("nsys.query.ncu-command-launch-recipe-missing")
970 }
971 Self::NcuCommandAmbiguousProcessRecipe { .. } => {
972 ErrorCode::new("nsys.query.ncu-command-launch-recipe-ambiguous-process")
973 }
974 Self::NcuCommandAmbiguousLaunchRecipe => {
975 ErrorCode::new("nsys.query.ncu-command-launch-recipe-ambiguous")
976 }
977 Self::KindLocationFilterConflict { .. } => {
978 ErrorCode::new("nsys.query.kind-location-filter-conflict")
979 }
980 Self::KindNvtxAttributionUnsupported { .. } => {
981 ErrorCode::new("nsys.query.kind-nvtx-attribution-unsupported")
982 }
983 Self::GapsInvalidScope { .. } => ErrorCode::new("nsys.query.gaps-invalid-scope"),
984 Self::GapsMinDurationInvalid { .. } => {
985 ErrorCode::new("nsys.query.gaps-min-duration-invalid")
986 }
987 Self::GapsMinTooSmall { .. } => ErrorCode::new("nsys.query.gaps-min-too-small"),
988 Self::GapsStreamRequiresStreamScope { .. } => {
989 ErrorCode::new("nsys.query.gaps-stream-scope-required")
990 }
991 Self::GapsDeviceInTraceScope { .. } => {
992 ErrorCode::new("nsys.query.gaps-device-scope-conflict")
993 }
994 Self::GapsSortStreamRequiresStreamScope { .. } => {
995 ErrorCode::new("nsys.query.gaps-sort-stream-scope-required")
996 }
997 Self::GapsSortDeviceInTraceScope => {
998 ErrorCode::new("nsys.query.gaps-sort-device-scope-conflict")
999 }
1000 Self::GapsSortInvalid { .. } => ErrorCode::new("nsys.query.gaps-sort-invalid"),
1001 Self::MetricsSortWithBucket => {
1002 ErrorCode::new("nsys.query.metrics-sort-bucket-conflict")
1003 }
1004 Self::MetricsBucketTooSmall { .. } => {
1005 ErrorCode::new("nsys.query.metrics-bucket-too-small")
1006 }
1007 Self::MetricsSortInvalid { .. } => ErrorCode::new("nsys.query.metrics-sort-invalid"),
1008 Self::MetricsUnknownSource { .. } => {
1009 ErrorCode::new("nsys.query.metrics-unknown-source")
1010 }
1011 Self::MetricsGpuTableMissing => ErrorCode::new("nsys.query.metrics-gpu-table-missing"),
1012 Self::MetricsGpuDictionaryMissing => {
1013 ErrorCode::new("nsys.query.metrics-gpu-dictionary-missing")
1014 }
1015 Self::MetricsGpuCounterNoMatch { .. } => {
1016 ErrorCode::new("nsys.query.metrics-gpu-counter-no-match")
1017 }
1018 Self::MetricsNicTableMissing => ErrorCode::new("nsys.query.metrics-nic-table-missing"),
1019 Self::MetricsNicDictionaryMissing => {
1020 ErrorCode::new("nsys.query.metrics-nic-dictionary-missing")
1021 }
1022 Self::MetricsNicIdMapMissing => ErrorCode::new("nsys.query.metrics-nic-id-map-missing"),
1023 Self::MetricsNicInfoMissing => ErrorCode::new("nsys.query.metrics-nic-info-missing"),
1024 Self::MetricsNicCounterNoMatch { .. } => {
1025 ErrorCode::new("nsys.query.metrics-nic-counter-no-match")
1026 }
1027 Self::MetricsCpuSamplingCompositeEventsMissing => {
1028 ErrorCode::new("nsys.query.metrics-cpu-sampling-table-missing")
1029 }
1030 Self::MetricsCpuSamplingUnknownGroupBy { .. } => {
1031 ErrorCode::new("nsys.query.metrics-cpu-sampling-unknown-group-by")
1032 }
1033 Self::MetricsCpuSamplingCallchainsMissing { .. } => {
1034 ErrorCode::new("nsys.query.metrics-cpu-sampling-callchains-missing")
1035 }
1036 Self::MetricsCpuSamplingBucketCallchainsMissing { .. } => {
1037 ErrorCode::new("nsys.query.metrics-cpu-sampling-callchains-missing")
1038 }
1039 Self::MetricsCpuSamplingStackBucketUnsupported => {
1040 ErrorCode::new("nsys.query.metrics-cpu-sampling-stack-bucket-unsupported")
1041 }
1042 Self::MetricsCpuSamplingNameOnNumericAxis { .. } => {
1043 ErrorCode::new("nsys.query.metrics-cpu-sampling-name-axis-conflict")
1044 }
1045 Self::MetricsCpuSchedEventsMissing => {
1046 ErrorCode::new("nsys.query.metrics-cpu-sched-table-missing")
1047 }
1048 Self::MetricsCpuSchedUnknownGroupBy { .. } => {
1049 ErrorCode::new("nsys.query.metrics-cpu-sched-unknown-group-by")
1050 }
1051 Self::GraphReplaysTopNodesTooSmall => {
1052 ErrorCode::new("nsys.query.graph-replays-top-nodes-too-small")
1053 }
1054 }
1055 }
1056}