@swmansion/argent 0.21.1-next.2 → 0.21.1-next.4

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.
@@ -136339,13 +136339,13 @@ function summarizeHangBlocking(states) {
136339
136339
  var MAX_INLINE_HOTSPOTS = 5;
136340
136340
  var MAX_INLINE_HANGS = 3;
136341
136341
  async function renderNativeProfilerReport(input) {
136342
- const { payload, traceFile, freshnessNote, mallocStackLogging } = input;
136342
+ const { payload, traceFile, freshnessNote, cpuDiagnostic, mallocStackLogging } = input;
136343
136343
  const exportErrors = input.exportErrors ?? {};
136344
136344
  const bottlenecksTotal = payload.bottlenecks.length;
136345
136345
  const status = Object.keys(exportErrors).length > 0 ? "analysis_failed" : "ok";
136346
136346
  const cpuHotspotsCount = payload.bottlenecks.filter((b) => b.type === "cpu_hotspot").length;
136347
136347
  const uiHangsCount = payload.bottlenecks.filter((b) => b.type === "ui_hang").length;
136348
- const fullReport = bottlenecksTotal === 0 ? renderAllClear2(payload, exportErrors, freshnessNote) : renderFullReport(
136348
+ const fullReport = bottlenecksTotal === 0 ? renderAllClear2(payload, exportErrors, freshnessNote, cpuDiagnostic) : renderFullReport(
136349
136349
  payload,
136350
136350
  exportErrors,
136351
136351
  {
@@ -136353,11 +136353,12 @@ async function renderNativeProfilerReport(input) {
136353
136353
  hangLimit: Infinity
136354
136354
  },
136355
136355
  freshnessNote,
136356
- mallocStackLogging
136356
+ mallocStackLogging,
136357
+ cpuDiagnostic
136357
136358
  );
136358
136359
  const reportFile = traceFile ? deriveReportPath(traceFile) : null;
136359
136360
  const wroteFile = reportFile ? await writeReport2(reportFile, fullReport) : false;
136360
- const inlineReport = bottlenecksTotal === 0 ? renderAllClear2(payload, exportErrors, freshnessNote) : renderFullReport(
136361
+ const inlineReport = bottlenecksTotal === 0 ? renderAllClear2(payload, exportErrors, freshnessNote, cpuDiagnostic) : renderFullReport(
136361
136362
  payload,
136362
136363
  exportErrors,
136363
136364
  {
@@ -136365,13 +136366,19 @@ async function renderNativeProfilerReport(input) {
136365
136366
  hangLimit: MAX_INLINE_HANGS
136366
136367
  },
136367
136368
  freshnessNote,
136368
- mallocStackLogging
136369
+ mallocStackLogging,
136370
+ cpuDiagnostic
136369
136371
  );
136370
136372
  const shownHotspots = Math.min(MAX_INLINE_HOTSPOTS, cpuHotspotsCount);
136371
136373
  const shownHangs = Math.min(MAX_INLINE_HANGS, uiHangsCount);
136374
+ const shownParts = [
136375
+ ...shownHotspots > 0 ? [`top ${shownHotspots} CPU hotspots`] : [],
136376
+ ...shownHangs > 0 ? [`top ${shownHangs} hangs`] : []
136377
+ ];
136378
+ const shownSummary = shownParts.length > 0 ? `showing ${shownParts.join(" and ")} inline` : `summary inline`;
136372
136379
  const report = wroteFile && reportFile ? inlineReport + `
136373
136380
 
136374
- > Full report saved \u2014 ${bottlenecksTotal} bottleneck(s) total, showing top ${shownHotspots} CPU hotspots and top ${shownHangs} hangs inline. Use the Read tool on the \`reportFile\` path in this result to view all details.` : inlineReport;
136381
+ > Full report saved \u2014 ${bottlenecksTotal} bottleneck(s) total, ${shownSummary}. Use the Read tool on the \`reportFile\` path in this result to view all details.` : inlineReport;
136375
136382
  return {
136376
136383
  report,
136377
136384
  reportFile: wroteFile ? reportFile : null,
@@ -136411,7 +136418,7 @@ function renderTraceProcessorUnavailable(err) {
136411
136418
  function reportTitle(payload) {
136412
136419
  return payload.metadata.platform.toLowerCase() === "android" ? "Android Perfetto Analysis" : "iOS Instruments Analysis";
136413
136420
  }
136414
- function renderAllClear2(payload, exportErrors, freshnessNote) {
136421
+ function renderAllClear2(payload, exportErrors, freshnessNote, cpuDiagnostic) {
136415
136422
  const traceName = payload.metadata.traceFile ? `\`${path24.basename(payload.metadata.traceFile)}\`` : "unknown";
136416
136423
  const lines = [
136417
136424
  `# ${reportTitle(payload)}`,
@@ -136420,6 +136427,7 @@ function renderAllClear2(payload, exportErrors, freshnessNote) {
136420
136427
  ``
136421
136428
  ];
136422
136429
  if (freshnessNote) lines.push(freshnessNote, ``);
136430
+ if (cpuDiagnostic) lines.push(`> \u26A0\uFE0F **CPU sampling:** ${cpuDiagnostic}`, ``);
136423
136431
  const errorLines = renderExportErrors(exportErrors);
136424
136432
  if (errorLines.length > 0) {
136425
136433
  lines.push(...errorLines, ``);
@@ -136439,7 +136447,7 @@ function renderAllClear2(payload, exportErrors, freshnessNote) {
136439
136447
  }
136440
136448
  return lines.join("\n");
136441
136449
  }
136442
- function renderFullReport(payload, exportErrors, cap = { hotspotLimit: Infinity, hangLimit: Infinity }, freshnessNote, mallocStackLogging) {
136450
+ function renderFullReport(payload, exportErrors, cap = { hotspotLimit: Infinity, hangLimit: Infinity }, freshnessNote, mallocStackLogging, cpuDiagnostic) {
136443
136451
  const traceName = payload.metadata.traceFile ? `\`${path24.basename(payload.metadata.traceFile)}\`` : "unknown";
136444
136452
  const cpuHotspots = payload.bottlenecks.filter((b) => b.type === "cpu_hotspot");
136445
136453
  const uiHangs = payload.bottlenecks.filter((b) => b.type === "ui_hang");
@@ -136454,6 +136462,7 @@ function renderFullReport(payload, exportErrors, cap = { hotspotLimit: Infinity,
136454
136462
  ``
136455
136463
  ];
136456
136464
  if (freshnessNote) lines.push(freshnessNote, ``);
136465
+ if (cpuDiagnostic) lines.push(`> \u26A0\uFE0F **CPU sampling:** ${cpuDiagnostic}`, ``);
136457
136466
  const errorLines = renderExportErrors(exportErrors);
136458
136467
  if (errorLines.length > 0) {
136459
136468
  lines.push(...errorLines, ``);
@@ -138044,8 +138053,13 @@ async function runAndroidProfilerPipeline(tracePath, appPackage) {
138044
138053
  exportErrors.rss = msg;
138045
138054
  });
138046
138055
  if (cpuRows.length === 0 && hangRows.length === 0 && !exportErrors.cpu) {
138047
- exportErrors.cpu = `No CPU samples were captured for cmdline \`${appPackage}\`. The most common cause is the target app being non-debuggable (release build) without a \`<profileable shell="true">\` entry in its AndroidManifest.xml. Without that, Perfetto silently drops the linux.perf data source. Add \`<profileable android:shell="true"/>\` to the \`<application>\` element and rebuild, or run a debug variant of the app.`;
138056
+ exportErrors.cpu = `No CPU samples were captured for cmdline \`${appPackage}\`. The trace contains no perf_sample rows for a process with that name, so no CPU analysis is possible. Either the name never matched a running process (it must equal the process cmdline exactly), or the app was never scheduled on-CPU during the recording. If it was running, it must be a debug build or declare \`<profileable android:shell="true"/>\` under \`<application>\` in its AndroidManifest.xml \u2014 then re-record.`;
138048
138057
  }
138058
+ const stacklessSamples = cpuRows.reduce(
138059
+ (sum, r) => r.leaf_function ? sum : sum + Number(r.sample_count),
138060
+ 0
138061
+ );
138062
+ const cpuDiagnostic = cpuRows.length > 0 && !cpuRows.some((r) => r.leaf_function) && stacklessSamples > 0 ? describeStacklessSamples(appPackage, cpuRows, stacklessSamples) : void 0;
138049
138063
  const cpuHotspots = aggregateCpuHotspots(cpuRowsToAggregatorRows(cpuRows, traceStartNs), {
138050
138064
  platform: "android"
138051
138065
  });
@@ -138073,7 +138087,14 @@ async function runAndroidProfilerPipeline(tracePath, appPackage) {
138073
138087
  });
138074
138088
  const rssGrowth = rssRowsToBottlenecks(rssRows);
138075
138089
  const bottlenecks = [...cpuHotspots, ...uiHangs, ...rssGrowth];
138076
- return { bottlenecks, cpuHotspots, uiHangs, rssGrowth, exportErrors };
138090
+ return {
138091
+ bottlenecks,
138092
+ cpuHotspots,
138093
+ uiHangs,
138094
+ rssGrowth,
138095
+ exportErrors,
138096
+ ...cpuDiagnostic ? { cpuDiagnostic } : {}
138097
+ };
138077
138098
  }
138078
138099
  async function loadAndroidCombinedData(tracePath, appPackage) {
138079
138100
  const target = sanitizeProcessName(appPackage);
@@ -138306,6 +138327,11 @@ async function renderThreadBreakdownAndroid(opts, target) {
138306
138327
  }
138307
138328
  return lines.join("\n");
138308
138329
  }
138330
+ function describeStacklessSamples(appPackage, cpuRows, stacklessSamples) {
138331
+ const unwound = cpuRows.some((r) => r.leaf_mapping);
138332
+ const head = `${stacklessSamples} CPU sample${stacklessSamples === 1 ? "" : "s"} were captured for \`${appPackage}\`, but none carry a usable call stack, so no CPU hotspots could be computed and \`profiler-stack-query\` mode=\`function_callers\` / mode=\`hang_stacks\` will find nothing. The app was running \u2014 this is a capture limitation, not an idle app. mode=\`thread_breakdown\` still works, since it counts samples and needs no stacks.`;
138333
+ return unwound ? `${head} The stacks were unwound but no frame resolved to a symbol, which points at stripped native libraries. Profile a build that keeps its symbols (a debug build, or a release build with unstripped \`.so\`s).` : `${head} No stack was unwound at all: Perfetto only unwinds a process it can read \`/proc/<pid>/mem\` for. Profile a debug build, or add \`<profileable android:shell="true"/>\` to \`<application>\` and rebuild \u2014 verify with \`adb shell dumpsys package ${appPackage}\`, which shows \`DEBUGGABLE\` for a profileable target. Platform packages such as \`com.android.settings\` are never profileable.`;
138334
+ }
138309
138335
  function cpuRowsToAggregatorRows(rows, traceStartNs) {
138310
138336
  const traceStartMs = Math.round(traceStartNs / 1e6);
138311
138337
  const out = [];
@@ -138647,7 +138673,9 @@ async function analyzeNativeProfilerAndroid(api) {
138647
138673
  // wallClockStartMs is the recording's start time (set at start, persisted in
138648
138674
  // the metadata sidecar, restored by profiler-load). A large gap to "now"
138649
138675
  // means we're analyzing a trace from an earlier session, not a fresh capture.
138650
- freshnessNote: formatTraceFreshness(api.wallClockStartMs, Date.now()) ?? void 0
138676
+ freshnessNote: formatTraceFreshness(api.wallClockStartMs, Date.now()) ?? void 0,
138677
+ // Explains an absent CPU section when samples exist but carry no stacks.
138678
+ cpuDiagnostic: pipelineResult.cpuDiagnostic
138651
138679
  });
138652
138680
  }
138653
138681
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/argent",
3
- "version": "0.21.1-next.2",
3
+ "version": "0.21.1-next.4",
4
4
  "mcpName": "io.github.software-mansion/argent",
5
5
  "description": "MCP server for iOS Simulator and Android Emulator control",
6
6
  "license": "Apache-2.0",