|
1 | 1 | <script lang="ts">
|
2 | 2 | import { onMount } from 'svelte';
|
3 | 3 | import { ProgressBar, CodeBlock } from '@skeletonlabs/skeleton';
|
4 |
| - import { ZoomInIcon } from 'svelte-feather-icons'; |
| 4 | + import { AlertTriangleIcon, ZoomInIcon } from 'svelte-feather-icons'; |
5 | 5 | import { filesize } from 'filesize';
|
6 | 6 | import getDryRunMetricsQuery from '$queries/get_dry_run_metrics.js';
|
7 | 7 | import getProjectQuery from '$queries/get_project';
|
|
36 | 36 | let selectedProject: { name: string; id: string };
|
37 | 37 | let logs: { [x: string]: string } = {};
|
38 | 38 |
|
39 |
| - let cpuData: { [key: string]: MetricsWithTimeStamps } = {}; |
| 39 | + let cumulativeCpuData: { [key: string]: MetricsWithTimeStamps } = {}; |
| 40 | + let currentCpuData: { [key: string]: MetricsWithTimeStamps } = {}; |
40 | 41 | let memoryData: { [key: string]: MetricsWithTimeStamps } = {};
|
41 |
| - let networkDataCombined: { |
| 42 | + let cumulativeNetworkData: { |
| 43 | + [key: string]: MetricsWithTimeStamps[]; |
| 44 | + } = {}; |
| 45 | + let currentNetworkData: { |
42 | 46 | [key: string]: MetricsWithTimeStamps[];
|
43 | 47 | } = {};
|
44 | 48 |
|
|
119 | 123 | const result = await getMetricsUsageUtils(metricsResponse as unknown as DryRunMetrics[]);
|
120 | 124 | const { allStepNames } = result;
|
121 | 125 | // console.log('allStepNames:', allStepNames);
|
122 |
| - cpuData = result.cpuData; |
| 126 | + cumulativeCpuData = result.cumulativeCpuData; |
| 127 | + currentCpuData = result.currentCpuData; |
123 | 128 | memoryData = result.memoryData;
|
124 |
| - networkDataCombined = result.networkDataCombined; |
| 129 | + cumulativeNetworkData = result.cumulativeNetworkData; |
| 130 | + currentNetworkData = result.currentNetworkData; |
125 | 131 | logs = result.logs;
|
126 | 132 | pipelineMetricsAnalytics = await getMetricsAnalyticsUtils(
|
127 | 133 | allStepNames,
|
128 | 134 | metricsResponse as unknown as DryRunMetrics[],
|
129 |
| - cpuData, |
| 135 | + cumulativeCpuData, |
130 | 136 | memoryData,
|
131 |
| - networkDataCombined |
| 137 | + cumulativeNetworkData |
132 | 138 | );
|
133 | 139 | const responses = {
|
134 | 140 | workflow: workflowResponse.project,
|
|
260 | 266 |
|
261 | 267 | // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
262 | 268 | $: getResource = (resource: string) => {
|
263 |
| - let resourceData; |
264 |
| - let wholeData: { x: string[]; y: number[]; type: string; name: string }[] = []; |
265 |
| - if (resource === 'cpu') { |
266 |
| - resourceData = cpuData; |
267 |
| - if (Object.keys(cpuData).length > 0) |
268 |
| - allStepNames.forEach((step) => { |
269 |
| - if (cpuData[step]) wholeData.push(cpuData[step]); |
270 |
| - }); |
271 |
| - } else if (resource === 'memory') { |
272 |
| - resourceData = memoryData; |
273 |
| - if (Object.keys(memoryData).length > 0) |
274 |
| - allStepNames.forEach((step) => { |
275 |
| - if (memoryData[step]) wholeData.push(memoryData[step]); |
276 |
| - }); |
277 |
| - } else { |
278 |
| - resourceData = networkDataCombined; |
279 |
| - wholeData = []; |
280 |
| - allStepNames.forEach((step) => { |
281 |
| - networkDataCombined[step]?.forEach((elem) => { |
282 |
| - wholeData.push(elem); |
283 |
| - }); |
284 |
| - }); |
285 |
| - } |
286 |
| - if (selectedStep !== 'Total') { |
287 |
| - if (resource === 'network') |
288 |
| - return { |
289 |
| - title: `${selectedStep}`, |
290 |
| - data: resourceData[selectedStep] ? resourceData[selectedStep] : [] |
291 |
| - }; |
292 |
| - return { |
293 |
| - title: `${selectedStep}`, |
294 |
| - data: resourceData[selectedStep] ? [resourceData[selectedStep]] : [] |
295 |
| - }; |
| 269 | + const data: { x: string[]; y: number[]; type: string; name: string }[] = []; |
| 270 | + switch (resource) { |
| 271 | + case 'cpu-cumulative': { |
| 272 | + if (Object.keys(cumulativeCpuData).length > 0) { |
| 273 | + if (selectedStep === 'Total') { |
| 274 | + allStepNames.forEach((step) => { |
| 275 | + if (cumulativeCpuData[step]) data.push(cumulativeCpuData[step]); |
| 276 | + }); |
| 277 | + } else { |
| 278 | + data.push(cumulativeCpuData[selectedStep]); |
| 279 | + } |
| 280 | + } |
| 281 | + break; |
| 282 | + } |
| 283 | + case 'cpu-current': { |
| 284 | + if (Object.keys(currentCpuData).length > 0) |
| 285 | + if (selectedStep === 'Total') { |
| 286 | + allStepNames.forEach((step) => { |
| 287 | + if (currentCpuData[step]) data.push(currentCpuData[step]); |
| 288 | + }); |
| 289 | + } else { |
| 290 | + data.push(currentCpuData[selectedStep]); |
| 291 | + } |
| 292 | + break; |
| 293 | + } |
| 294 | + case 'memory': { |
| 295 | + if (Object.keys(memoryData).length > 0) |
| 296 | + if (selectedStep === 'Total') { |
| 297 | + allStepNames.forEach((step) => { |
| 298 | + if (memoryData[step]) data.push(memoryData[step]); |
| 299 | + }); |
| 300 | + } else { |
| 301 | + data.push(memoryData[selectedStep]); |
| 302 | + } |
| 303 | + break; |
| 304 | + } |
| 305 | + case 'network-cumulative': { |
| 306 | + if (Object.keys(cumulativeNetworkData).length > 0) |
| 307 | + if (selectedStep === 'Total') { |
| 308 | + allStepNames.forEach((step) => { |
| 309 | + cumulativeNetworkData[step].forEach((networkData) => { |
| 310 | + data.push(networkData); |
| 311 | + }); |
| 312 | + }); |
| 313 | + } else { |
| 314 | + cumulativeNetworkData[selectedStep].forEach((networkData) => { |
| 315 | + data.push(networkData); |
| 316 | + }); |
| 317 | + } |
| 318 | + break; |
| 319 | + } |
| 320 | + case 'network-current': { |
| 321 | + if (Object.keys(currentNetworkData).length > 0) |
| 322 | + if (selectedStep === 'Total') { |
| 323 | + allStepNames.forEach((step) => { |
| 324 | + currentNetworkData[step].forEach((networkData) => { |
| 325 | + data.push(networkData); |
| 326 | + }); |
| 327 | + }); |
| 328 | + } else { |
| 329 | + currentNetworkData[selectedStep].forEach((networkData) => { |
| 330 | + data.push(networkData); |
| 331 | + }); |
| 332 | + } |
| 333 | + break; |
| 334 | + } |
| 335 | + default: { |
| 336 | + throw new Error('Invalid resource'); |
| 337 | + } |
296 | 338 | }
|
297 |
| - return { title: `- entire dry run`, data: wholeData }; |
| 339 | + return selectedStep === 'Total' |
| 340 | + ? { title: `- entire dry run`, data } |
| 341 | + : { title: `${selectedStep}`, data }; |
298 | 342 | };
|
299 | 343 |
|
300 | 344 | onMount(async () => {
|
|
368 | 412 | <tr on:click={() => stepOnClick(step.displayName)}>
|
369 | 413 | <td style="width:15%">{step.displayName}</td>
|
370 | 414 | <td style="width:20%">
|
371 |
| - {step.startedAt ? step.startedAt : '-'} |
| 415 | + {step.startedAt ?? '-'} |
372 | 416 | </td>
|
373 | 417 | <td style="width:20%">
|
374 |
| - {step.finishedAt ? step.finishedAt : '-'} |
| 418 | + {step.finishedAt ?? '-'} |
375 | 419 | </td>
|
376 | 420 | <td style="width:15%">{displayStepDuration(step)}</td>
|
377 | 421 | <td style="width:15%">{step.phase}</td>
|
|
396 | 440 | <!-- if the logs are empty, remove logs sections -->
|
397 | 441 | {#if Object.values(logs).join('') !== ''}
|
398 | 442 | <div class="card logcard row-span-4 p-5">
|
| 443 | + <!-- display if the dryrun has a non-empty phase message from argo (usually null if no error) --> |
| 444 | + {#if dryRunPhaseMessage} |
| 445 | + <div class="card logcard row-span-1 p-5"> |
| 446 | + <div style="display: flex; align-items: center; color: red; gap: 5px"> |
| 447 | + <AlertTriangleIcon /> |
| 448 | + <h1>Error Message</h1> |
| 449 | + </div> |
| 450 | + <section class="p-1"> |
| 451 | + <div class="w-full"> |
| 452 | + <CodeBlock language="json" code={dryRunPhaseMessage} /> |
| 453 | + </div> |
| 454 | + </section> |
| 455 | + </div> |
| 456 | + {/if} |
399 | 457 | <header class="card-header"><h1>Logs</h1></header>
|
400 | 458 | <section class="p-1">
|
401 | 459 | <br />
|
|
406 | 464 | </li>
|
407 | 465 | <li>
|
408 | 466 | {#if logs[key] && getPartLogs(key, 20_000)}
|
409 |
| - <div class="w-full"> |
| 467 | + <div class="logbox w-full"> |
410 | 468 | <CodeBlock language="bash" code={getPartLogs(key, 20_000)} />
|
411 | 469 | </div>
|
412 | 470 | {:else}
|
|
419 | 477 | </section>
|
420 | 478 | </div>
|
421 | 479 | {/if}
|
422 |
| - <!-- display if the dryrun has a non-empty phase message from argo (usually null if no error) --> |
423 |
| - {#if dryRunPhaseMessage} |
424 |
| - <div class="card logcard row-span-4 p-5"> |
425 |
| - <h1>Message</h1> |
426 |
| - <section class="p-1"> |
427 |
| - <div class="w-full"> |
428 |
| - <CodeBlock language="json" code={dryRunPhaseMessage} /> |
429 |
| - </div> |
430 |
| - </section> |
431 |
| - </div> |
432 |
| - {/if} |
433 | 480 |
|
434 | 481 | <div class="card resourcecard">
|
435 | 482 | <table class="table table-interactive">
|
|
470 | 517 |
|
471 | 518 | <div class="card plotcard">
|
472 | 519 | <Plot
|
473 |
| - data={getResource('cpu').data} |
474 |
| - plotTitle={`CPU Usage ${getResource('cpu').title}`} |
| 520 | + data={getResource('cpu-current').data} |
| 521 | + plotTitle={`CPU Utilization ${getResource('cpu-current').title}`} |
475 | 522 | xaxisTitle="time"
|
476 |
| - yaxisTitle="cpu usage" |
| 523 | + yaxisTitle="cpu utilization %" |
477 | 524 | />
|
478 | 525 | </div>
|
479 | 526 | <div class="card plotcard">
|
|
486 | 533 | </div>
|
487 | 534 | <div class="card plotcard">
|
488 | 535 | <Plot
|
489 |
| - data={getResource('network').data} |
490 |
| - plotTitle={`Network ${getResource('network').title}`} |
| 536 | + data={getResource('network-current').data} |
| 537 | + plotTitle={`Network ${getResource('network-current').title}`} |
491 | 538 | xaxisTitle="time"
|
492 | 539 | yaxisTitle="bytes"
|
493 | 540 | />
|
|
512 | 559 | overflow-y: scroll;
|
513 | 560 | max-height: fit-content;
|
514 | 561 | }
|
| 562 | + .logbox { |
| 563 | + overflow-y: scroll; |
| 564 | + max-height: 100vh; |
| 565 | + } |
515 | 566 | ul {
|
516 | 567 | max-height: 75vh;
|
517 | 568 | max-height: fit-content;
|
|
0 commit comments