@stati/core 1.16.3 → 1.17.0
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/dist/core/build.d.ts +41 -12
- package/dist/core/build.d.ts.map +1 -1
- package/dist/core/build.js +92 -11
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/templates.d.ts +10 -1
- package/dist/core/templates.d.ts.map +1 -1
- package/dist/core/templates.js +8 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/metrics/index.d.ts +38 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +42 -0
- package/dist/metrics/noop.d.ts +12 -0
- package/dist/metrics/noop.d.ts.map +1 -0
- package/dist/metrics/noop.js +88 -0
- package/dist/metrics/recorder.d.ts +31 -0
- package/dist/metrics/recorder.d.ts.map +1 -0
- package/dist/metrics/recorder.js +176 -0
- package/dist/metrics/types.d.ts +236 -0
- package/dist/metrics/types.d.ts.map +1 -0
- package/dist/metrics/types.js +7 -0
- package/dist/metrics/utils/index.d.ts +9 -0
- package/dist/metrics/utils/index.d.ts.map +1 -0
- package/dist/metrics/utils/index.js +9 -0
- package/dist/metrics/utils/system.utils.d.ts +44 -0
- package/dist/metrics/utils/system.utils.d.ts.map +1 -0
- package/dist/metrics/utils/system.utils.js +95 -0
- package/dist/metrics/utils/writer.utils.d.ts +64 -0
- package/dist/metrics/utils/writer.utils.d.ts.map +1 -0
- package/dist/metrics/utils/writer.utils.js +145 -0
- package/package.json +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics file writing utilities.
|
|
3
|
+
* Handles graceful degradation - never blocks builds on write failures.
|
|
4
|
+
*/
|
|
5
|
+
import type { BuildMetrics } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Default metrics output directory (relative to cache dir).
|
|
8
|
+
*/
|
|
9
|
+
export declare const DEFAULT_METRICS_DIR = "metrics";
|
|
10
|
+
/**
|
|
11
|
+
* Generate a timestamped filename for metrics output.
|
|
12
|
+
*
|
|
13
|
+
* @param command - The command that was run (build, dev)
|
|
14
|
+
* @param timestamp - ISO timestamp
|
|
15
|
+
* @returns Filename like "build-2024-01-15T10-30-00.json"
|
|
16
|
+
*/
|
|
17
|
+
export declare function generateMetricsFilename(command: string, timestamp: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Options for writing metrics.
|
|
20
|
+
*/
|
|
21
|
+
export interface WriteMetricsOptions {
|
|
22
|
+
/** Base cache directory (e.g., .stati) */
|
|
23
|
+
cacheDir: string;
|
|
24
|
+
/** Custom output path (overrides default) */
|
|
25
|
+
outputPath?: string | undefined;
|
|
26
|
+
/** Format: json (default) or ndjson */
|
|
27
|
+
format?: 'json' | 'ndjson' | undefined;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Result of metrics write operation.
|
|
31
|
+
*/
|
|
32
|
+
export interface WriteMetricsResult {
|
|
33
|
+
success: boolean;
|
|
34
|
+
path?: string;
|
|
35
|
+
error?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Write build metrics to a JSON file.
|
|
39
|
+
* Degrades gracefully on failure - logs warning but doesn't throw.
|
|
40
|
+
*
|
|
41
|
+
* @param metrics - The metrics to write
|
|
42
|
+
* @param options - Write options
|
|
43
|
+
* @returns Result indicating success/failure and path
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const result = await writeMetrics(metrics, {
|
|
48
|
+
* cacheDir: '.stati',
|
|
49
|
+
* });
|
|
50
|
+
*
|
|
51
|
+
* if (result.success) {
|
|
52
|
+
* console.log(`Metrics written to ${result.path}`);
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function writeMetrics(metrics: BuildMetrics, options: WriteMetricsOptions): Promise<WriteMetricsResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Format metrics for CLI summary output.
|
|
59
|
+
*
|
|
60
|
+
* @param metrics - Build metrics to format
|
|
61
|
+
* @returns Array of formatted lines for CLI output
|
|
62
|
+
*/
|
|
63
|
+
export declare function formatMetricsSummary(metrics: BuildMetrics): string[];
|
|
64
|
+
//# sourceMappingURL=writer.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.utils.d.ts","sourceRoot":"","sources":["../../../src/metrics/utils/writer.utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAuB7C;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAIlF;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CA2C7B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,EAAE,CA6CpE"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics file writing utilities.
|
|
3
|
+
* Handles graceful degradation - never blocks builds on write failures.
|
|
4
|
+
*/
|
|
5
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
6
|
+
import { join, dirname } from 'node:path';
|
|
7
|
+
/**
|
|
8
|
+
* Default metrics output directory (relative to cache dir).
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_METRICS_DIR = 'metrics';
|
|
11
|
+
/**
|
|
12
|
+
* Display names for build phases.
|
|
13
|
+
* Maps raw phase keys (e.g., 'configLoadMs') to human-readable labels.
|
|
14
|
+
*/
|
|
15
|
+
const PHASE_DISPLAY_NAMES = {
|
|
16
|
+
configLoadMs: 'Config Load',
|
|
17
|
+
contentDiscoveryMs: 'Content Discovery',
|
|
18
|
+
navigationBuildMs: 'Navigation Build',
|
|
19
|
+
cacheManifestLoadMs: 'Cache Manifest Load',
|
|
20
|
+
typescriptCompileMs: 'TypeScript Compile',
|
|
21
|
+
pageRenderingMs: 'Page Rendering',
|
|
22
|
+
assetCopyMs: 'Asset Copy',
|
|
23
|
+
cacheManifestSaveMs: 'Cache Manifest Save',
|
|
24
|
+
sitemapGenerationMs: 'Sitemap Generation',
|
|
25
|
+
rssGenerationMs: 'RSS Generation',
|
|
26
|
+
hookBeforeAllMs: 'Hook: Before All',
|
|
27
|
+
hookAfterAllMs: 'Hook: After All',
|
|
28
|
+
hookBeforeRenderTotalMs: 'Hook: Before Render (Total)',
|
|
29
|
+
hookAfterRenderTotalMs: 'Hook: After Render (Total)',
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Generate a timestamped filename for metrics output.
|
|
33
|
+
*
|
|
34
|
+
* @param command - The command that was run (build, dev)
|
|
35
|
+
* @param timestamp - ISO timestamp
|
|
36
|
+
* @returns Filename like "build-2024-01-15T10-30-00.json"
|
|
37
|
+
*/
|
|
38
|
+
export function generateMetricsFilename(command, timestamp) {
|
|
39
|
+
// Replace colons with dashes for Windows compatibility
|
|
40
|
+
const safeTimestamp = timestamp.replace(/:/g, '-').replace(/\.\d+Z$/, 'Z');
|
|
41
|
+
return `${command}-${safeTimestamp}.json`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Write build metrics to a JSON file.
|
|
45
|
+
* Degrades gracefully on failure - logs warning but doesn't throw.
|
|
46
|
+
*
|
|
47
|
+
* @param metrics - The metrics to write
|
|
48
|
+
* @param options - Write options
|
|
49
|
+
* @returns Result indicating success/failure and path
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const result = await writeMetrics(metrics, {
|
|
54
|
+
* cacheDir: '.stati',
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* if (result.success) {
|
|
58
|
+
* console.log(`Metrics written to ${result.path}`);
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export async function writeMetrics(metrics, options) {
|
|
63
|
+
try {
|
|
64
|
+
// Determine output path
|
|
65
|
+
let outputPath;
|
|
66
|
+
if (options.outputPath) {
|
|
67
|
+
outputPath = options.outputPath;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const metricsDir = join(options.cacheDir, DEFAULT_METRICS_DIR);
|
|
71
|
+
const filename = generateMetricsFilename(metrics.meta.command, metrics.meta.timestamp);
|
|
72
|
+
outputPath = join(metricsDir, filename);
|
|
73
|
+
}
|
|
74
|
+
// Ensure directory exists
|
|
75
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
76
|
+
// Format content
|
|
77
|
+
const format = options.format ?? 'json';
|
|
78
|
+
let content;
|
|
79
|
+
if (format === 'ndjson') {
|
|
80
|
+
// NDJSON: one JSON object per line, no pretty printing
|
|
81
|
+
content = JSON.stringify(metrics) + '\n';
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
// JSON: pretty printed for readability
|
|
85
|
+
content = JSON.stringify(metrics, null, 2) + '\n';
|
|
86
|
+
}
|
|
87
|
+
// Write file
|
|
88
|
+
await writeFile(outputPath, content, 'utf-8');
|
|
89
|
+
return {
|
|
90
|
+
success: true,
|
|
91
|
+
path: outputPath,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
// Graceful degradation - don't throw, just report failure
|
|
96
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
97
|
+
return {
|
|
98
|
+
success: false,
|
|
99
|
+
error: `Failed to write metrics: ${errorMessage}`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Format metrics for CLI summary output.
|
|
105
|
+
*
|
|
106
|
+
* @param metrics - Build metrics to format
|
|
107
|
+
* @returns Array of formatted lines for CLI output
|
|
108
|
+
*/
|
|
109
|
+
export function formatMetricsSummary(metrics) {
|
|
110
|
+
const lines = [];
|
|
111
|
+
// Header
|
|
112
|
+
lines.push('');
|
|
113
|
+
lines.push('Build Metrics Summary');
|
|
114
|
+
lines.push('─'.repeat(40));
|
|
115
|
+
// Total duration
|
|
116
|
+
const totalSeconds = (metrics.totals.durationMs / 1000).toFixed(2);
|
|
117
|
+
lines.push(`Total build time: ${totalSeconds}s`);
|
|
118
|
+
// Page stats
|
|
119
|
+
const { totalPages, renderedPages, cachedPages } = metrics.counts;
|
|
120
|
+
lines.push(`Pages: ${totalPages} total, ${renderedPages} rendered, ${cachedPages} cached`);
|
|
121
|
+
// Cache hit rate
|
|
122
|
+
const hitRate = (metrics.isg.cacheHitRate * 100).toFixed(1);
|
|
123
|
+
lines.push(`Cache hit rate: ${hitRate}%`);
|
|
124
|
+
// Memory
|
|
125
|
+
const peakMB = (metrics.totals.peakRssBytes / 1024 / 1024).toFixed(1);
|
|
126
|
+
lines.push(`Peak memory: ${peakMB} MB`);
|
|
127
|
+
// Top phases (sorted by duration, top 3)
|
|
128
|
+
const phases = Object.entries(metrics.phases)
|
|
129
|
+
.filter(([, duration]) => duration !== undefined && duration > 0)
|
|
130
|
+
.map(([name, duration]) => ({ name, duration: duration }))
|
|
131
|
+
.sort((a, b) => b.duration - a.duration)
|
|
132
|
+
.slice(0, 3);
|
|
133
|
+
if (phases.length > 0) {
|
|
134
|
+
lines.push('');
|
|
135
|
+
lines.push('Top phases:');
|
|
136
|
+
for (const phase of phases) {
|
|
137
|
+
// Use mapped display name if available, otherwise fall back to raw name
|
|
138
|
+
const phaseName = PHASE_DISPLAY_NAMES[phase.name] || phase.name;
|
|
139
|
+
const phaseMs = phase.duration.toFixed(0);
|
|
140
|
+
lines.push(` ${phaseName}: ${phaseMs}ms`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
lines.push('─'.repeat(40));
|
|
144
|
+
return lines;
|
|
145
|
+
}
|