Skip to content

Commit c73f053

Browse files
authored
Merge pull request #178 from LennartvdM/codex/refactor-log-formatter-for-multi-line-support
Refine purity summary logging output
2 parents 15ac0d2 + a1c4370 commit c73f053

1 file changed

Lines changed: 34 additions & 65 deletions

File tree

web/app.js

Lines changed: 34 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3741,54 +3741,12 @@ function formatPurityPercent(value) {
37413741

37423742
function buildPurityObservations(summary) {
37433743
const lines = [];
3744-
if (!summary) {
3745-
return lines;
3746-
}
3747-
const totalRuns = Number.isFinite(summary.totalRuns) ? summary.totalRuns : 0;
3748-
const pureRuns = Number.isFinite(summary.pureRuns) ? summary.pureRuns : 0;
3749-
const impureRuns = Number.isFinite(summary.impureRuns) ? summary.impureRuns : 0;
3750-
const statusLabel = summary.didCheckerError
3751-
? 'ERROR'
3752-
: summary.hasAnyError
3753-
? 'FAILED'
3754-
: 'OK';
3755-
if (totalRuns > 0) {
3756-
const statusParts = [`Purity status: ${statusLabel}.`];
3757-
if (summary.didCheckerError) {
3758-
statusParts.push('Checker encountered errors.');
3759-
} else if (impureRuns > 0) {
3760-
statusParts.push(`${impureRuns}/${totalRuns} runs show drift between raw and share totals.`);
3761-
} else {
3762-
statusParts.push(`All ${pureRuns}/${totalRuns} runs are pure.`);
3763-
}
3764-
lines.push(`Overall: ${statusParts.join(' ')}`);
3765-
}
3766-
3767-
const analysis = summary.analysis;
3744+
const analysis = summary?.analysis;
3745+
const totalRuns = Number.isFinite(summary?.totalRuns) ? summary.totalRuns : 0;
37683746
if (!analysis || !totalRuns) {
37693747
return lines;
37703748
}
37713749

3772-
if (Number.isFinite(analysis.avgRawTotal)) {
3773-
const avgRaw = formatPurityMinutes(analysis.avgRawTotal);
3774-
const avgShare = formatPurityMinutes(analysis.avgShareTotal);
3775-
const avgSequence = formatPurityMinutes(analysis.avgSequenceTotal);
3776-
lines.push(
3777-
`Overall: Average total minutes per run: raw=${avgRaw}, share=${avgShare}, sequence=${avgSequence}.`
3778-
);
3779-
3780-
const shareDiff = analysis.avgShareTotal - analysis.avgRawTotal;
3781-
const percentDiff = analysis.avgRawTotal === 0 ? null : shareDiff / analysis.avgRawTotal;
3782-
if (Math.abs(shareDiff) >= 1) {
3783-
const direction = shareDiff < 0 ? 'missing' : 'over-reporting';
3784-
const percentText = formatPurityPercent(percentDiff);
3785-
const percentSuffix = percentText === 'n/a' ? '' : ` (≈ ${percentText}).`;
3786-
const driftMinutesText = formatPurityMinutes(Math.abs(shareDiff));
3787-
const baseText = `Overall: On average, share is ${direction} ${driftMinutesText} minutes per run compared to raw`;
3788-
lines.push(percentSuffix ? `${baseText}${percentSuffix}` : `${baseText}.`);
3789-
}
3790-
}
3791-
37923750
const activityThresholdMinutes = 60;
37933751
const activityThresholdPercent = 0.1;
37943752
const activityAnalyses = Array.isArray(analysis.activities) ? analysis.activities.slice() : [];
@@ -3810,14 +3768,14 @@ function buildPurityObservations(summary) {
38103768
.slice(0, 3);
38113769

38123770
significantActivities.forEach((activity) => {
3813-
const driftMinutes = activity.avgShareDriftMinutes || 0;
3814-
const direction = driftMinutes < 0 ? 'undercounted' : 'overcounted';
38153771
const label = activity.label || activity.key || 'activity';
3772+
const avgRawText = formatPurityMinutes(activity.avgRawPerRun);
3773+
const avgShareText = formatPurityMinutes(activity.avgSharePerRun);
3774+
const driftMinutesText = formatPurityMinutes(activity.avgShareDriftMinutes || 0);
38163775
const percentText = formatPurityPercent(activity.avgShareDriftPercent);
3817-
const percentSuffix = percentText === 'n/a' ? '' : ` (≈ ${percentText} vs raw)`;
3818-
const driftMinutesText = formatPurityMinutes(Math.abs(driftMinutes));
3776+
const percentSuffix = percentText === 'n/a' ? '' : ` (≈ ${percentText})`;
38193777
lines.push(
3820-
`Activity '${label}' is ${direction} in share by an average of ${driftMinutesText} minutes per run${percentSuffix}.`
3778+
`ACTIVITY | ${label} | avg raw/share per run: ${avgRawText} / ${avgShareText} | drift: ${driftMinutesText} min${percentSuffix}`
38213779
);
38223780
});
38233781

@@ -3842,38 +3800,49 @@ function buildPurityObservations(summary) {
38423800
}
38433801
const minMagnitudeText = formatPurityMinutes(minMagnitude);
38443802
lines.push(
3845-
`Runs: Largest total drift in runs ${runLabels.join(', ')} (share ${descriptor}${minMagnitudeText} minutes each).`
3803+
`RUNS | worst total drift: ${runLabels.join(', ')} (share ${descriptor}${minMagnitudeText} min each)`
38463804
);
38473805
}
38483806

38493807
return lines;
38503808
}
38513809

38523810
function buildPuritySummaryLines(summary, observations) {
3811+
const lines = [];
38533812
const totalRuns = Number.isFinite(summary?.totalRuns) ? summary.totalRuns : 0;
38543813
const pureRuns = Number.isFinite(summary?.pureRuns) ? summary.pureRuns : 0;
38553814
const impureRuns = Number.isFinite(summary?.impureRuns) ? summary.impureRuns : 0;
38563815
const runs = Array.isArray(summary?.runs) ? summary.runs : [];
38573816
const checkerErrorRuns = runs.filter((run) => run && run.didError).length;
38583817
const hasCheckerError = Boolean(summary?.didCheckerError);
38593818
const errorCount = hasCheckerError ? Math.max(1, checkerErrorRuns) : checkerErrorRuns;
3860-
const headerStats = [`Batch size: ${totalRuns}`, `Pure: ${pureRuns}`, `Impure: ${impureRuns}`];
3819+
const statusLabel = hasCheckerError ? 'ERROR' : summary?.hasAnyError ? 'FAILED' : 'OK';
3820+
const statusParts = [`runs: ${totalRuns} total, ${pureRuns} pure, ${impureRuns} impure`];
38613821
if (errorCount > 0) {
3862-
headerStats.push(`Checker errors: ${errorCount}`);
3822+
statusParts.push(`checker errors: ${errorCount}`);
38633823
}
3864-
const summaryLines = Array.isArray(observations) && observations.length > 0
3865-
? observations
3866-
: ['(No observations available.)'];
3867-
const headerLine = '============================================================';
3868-
const separatorLine = '------------------------------------------------------------';
3869-
const lines = [
3870-
headerLine,
3871-
`PURITY REPORT | ${headerStats.join(' | ')}`,
3872-
headerLine,
3873-
...summaryLines.map((line) => `Overall: ${line}`),
3874-
separatorLine,
3875-
'(Full raw purity data continues below…)',
3876-
];
3824+
lines.push(`STATUS | ${statusLabel} | ${statusParts.join(' | ')}`);
3825+
3826+
const analysis = summary?.analysis;
3827+
if (analysis && totalRuns > 0) {
3828+
const avgRaw = formatPurityMinutes(analysis.avgRawTotal);
3829+
const avgShare = formatPurityMinutes(analysis.avgShareTotal);
3830+
const avgSequence = formatPurityMinutes(analysis.avgSequenceTotal);
3831+
lines.push(`TOTALS | avg raw/share/sequence per run: ${avgRaw} / ${avgShare} / ${avgSequence}`);
3832+
3833+
const shareDiff = (Number(analysis.avgShareTotal) || 0) - (Number(analysis.avgRawTotal) || 0);
3834+
const percentDiff = analysis.avgRawTotal === 0 ? null : shareDiff / analysis.avgRawTotal;
3835+
const driftMinutesText = formatPurityMinutes(shareDiff);
3836+
const percentText = formatPurityPercent(percentDiff);
3837+
const percentSuffix = percentText === 'n/a' ? '' : ` (≈ ${percentText})`;
3838+
lines.push(`TOTALS | avg drift (share vs raw): ${driftMinutesText} min per run${percentSuffix}`);
3839+
}
3840+
3841+
if (Array.isArray(observations) && observations.length > 0) {
3842+
lines.push(...observations);
3843+
}
3844+
3845+
lines.push('NOTE | Full raw purity data continues below…');
38773846
return lines;
38783847
}
38793848

0 commit comments

Comments
 (0)