@sfdxy/anypoint-connect 0.2.3 → 0.4.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/README.md +15 -0
- package/dist/analysis/LogAnalyzer.d.ts +26 -0
- package/dist/analysis/LogAnalyzer.d.ts.map +1 -0
- package/dist/analysis/LogAnalyzer.js +61 -0
- package/dist/analysis/LogAnalyzer.js.map +1 -0
- package/dist/analysis/error-context.d.ts +19 -0
- package/dist/analysis/error-context.d.ts.map +1 -0
- package/dist/analysis/error-context.js +69 -0
- package/dist/analysis/error-context.js.map +1 -0
- package/dist/analysis/error-grouper.d.ts +16 -0
- package/dist/analysis/error-grouper.d.ts.map +1 -0
- package/dist/analysis/error-grouper.js +44 -0
- package/dist/analysis/error-grouper.js.map +1 -0
- package/dist/analysis/parser.d.ts +11 -0
- package/dist/analysis/parser.d.ts.map +1 -0
- package/dist/analysis/parser.js +123 -0
- package/dist/analysis/parser.js.map +1 -0
- package/dist/analysis/pattern-detector.d.ts +16 -0
- package/dist/analysis/pattern-detector.d.ts.map +1 -0
- package/dist/analysis/pattern-detector.js +38 -0
- package/dist/analysis/pattern-detector.js.map +1 -0
- package/dist/analysis/stats.d.ts +10 -0
- package/dist/analysis/stats.d.ts.map +1 -0
- package/dist/analysis/stats.js +82 -0
- package/dist/analysis/stats.js.map +1 -0
- package/dist/analysis/types.d.ts +84 -0
- package/dist/analysis/types.d.ts.map +1 -0
- package/dist/analysis/types.js +6 -0
- package/dist/analysis/types.js.map +1 -0
- package/dist/analysis/utils.d.ts +16 -0
- package/dist/analysis/utils.d.ts.map +1 -0
- package/dist/analysis/utils.js +55 -0
- package/dist/analysis/utils.js.map +1 -0
- package/dist/api/LogsApi.d.ts +5 -0
- package/dist/api/LogsApi.d.ts.map +1 -1
- package/dist/api/LogsApi.js +9 -0
- package/dist/api/LogsApi.js.map +1 -1
- package/dist/api/MonitoringApi.d.ts +50 -5
- package/dist/api/MonitoringApi.d.ts.map +1 -1
- package/dist/api/MonitoringApi.js +86 -10
- package/dist/api/MonitoringApi.js.map +1 -1
- package/dist/commands/monitor.d.ts +5 -1
- package/dist/commands/monitor.d.ts.map +1 -1
- package/dist/commands/monitor.js +171 -16
- package/dist/commands/monitor.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/prompts.d.ts.map +1 -1
- package/dist/mcp/prompts.js +10 -6
- package/dist/mcp/prompts.js.map +1 -1
- package/dist/mcp/tools/analysis.d.ts +8 -0
- package/dist/mcp/tools/analysis.d.ts.map +1 -0
- package/dist/mcp/tools/analysis.js +184 -0
- package/dist/mcp/tools/analysis.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +1 -0
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +1 -0
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/monitoring.d.ts +2 -1
- package/dist/mcp/tools/monitoring.d.ts.map +1 -1
- package/dist/mcp/tools/monitoring.js +171 -2
- package/dist/mcp/tools/monitoring.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +2 -1
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,6 +97,15 @@ src/
|
|
|
97
97
|
│ ├── ApiManagerApi.ts API instances, policies, SLA tiers
|
|
98
98
|
│ ├── DesignCenterApi.ts Projects, files, lock/save, publish
|
|
99
99
|
│ └── AccessManagementApi.ts
|
|
100
|
+
├── analysis/ Log analysis pipeline
|
|
101
|
+
│ ├── LogAnalyzer.ts Pipeline orchestrator
|
|
102
|
+
│ ├── parser.ts Multi-line joiner + JSON Logger parser
|
|
103
|
+
│ ├── error-context.ts Error context windows (before/after)
|
|
104
|
+
│ ├── error-grouper.ts Clusters similar errors
|
|
105
|
+
│ ├── pattern-detector.ts Recurring message templates
|
|
106
|
+
│ ├── stats.ts Level distribution, error spikes
|
|
107
|
+
│ ├── types.ts Shared type definitions
|
|
108
|
+
│ └── utils.ts Noise detection, templatization
|
|
100
109
|
├── commands/ CLI commands
|
|
101
110
|
│ ├── config.ts init | show | set | path
|
|
102
111
|
│ ├── auth.ts login | logout | status
|
|
@@ -373,6 +382,9 @@ No `env` block needed — the MCP server reads from `~/.anypoint-connect/` autom
|
|
|
373
382
|
| `scale_app` | ⚠️ Scale application replicas (1–8) |
|
|
374
383
|
| `get_logs` | Fetch recent log entries |
|
|
375
384
|
| `download_logs` | Download logs for a time range |
|
|
385
|
+
| `analyze_errors` | Clustered error groups with before/after context windows |
|
|
386
|
+
| `get_log_patterns` | Top recurring message templates with counts |
|
|
387
|
+
| `get_log_stats` | Statistical health summary: error rate, spikes, noise % |
|
|
376
388
|
| `get_metrics` | Fetch monitoring metrics (AMQL) |
|
|
377
389
|
| `search_exchange` | Search assets in Exchange |
|
|
378
390
|
| `download_api_spec` | Download RAML/OAS spec from Exchange |
|
|
@@ -407,6 +419,9 @@ No `env` block needed — the MCP server reads from `~/.anypoint-connect/` autom
|
|
|
407
419
|
- *"What apps are running in Sandbox?"*
|
|
408
420
|
- *"Show me the resource allocation across all Production apps"*
|
|
409
421
|
- *"Show me the last 50 error logs for my-api in Production"*
|
|
422
|
+
- *"Analyze the errors in my-api in Production — what's failing and why?"*
|
|
423
|
+
- *"What are the top log patterns for billing-api in Development?"*
|
|
424
|
+
- *"Give me a health summary of external-sapi in Production"*
|
|
410
425
|
- *"Compare Development and Production environments"*
|
|
411
426
|
- *"What policies are applied to the Order API?"*
|
|
412
427
|
- *"Show me the RAML spec for the order-api project"*
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analyzer — Orchestrator
|
|
3
|
+
* Thin pipeline that composes the individual analysis modules.
|
|
4
|
+
*
|
|
5
|
+
* Module structure:
|
|
6
|
+
* - types.ts — Shared type definitions
|
|
7
|
+
* - utils.ts — Noise detection, templatization, constants
|
|
8
|
+
* - parser.ts — Multi-line log parser (JSON Logger, stack traces)
|
|
9
|
+
* - error-context.ts — Error context window builder
|
|
10
|
+
* - error-grouper.ts — Clusters similar errors
|
|
11
|
+
* - pattern-detector.ts — Identifies recurring message templates
|
|
12
|
+
* - stats.ts — Level distribution, error rate, spike detection
|
|
13
|
+
*/
|
|
14
|
+
export type { EnrichedLogEntry, ErrorWithContext, ErrorGroup, LogPattern, ErrorSpike, LogStats, AnalysisOptions, AnalysisResult, } from './types.js';
|
|
15
|
+
export { parseRawLogs } from './parser.js';
|
|
16
|
+
export { buildErrorContexts } from './error-context.js';
|
|
17
|
+
export { groupErrors } from './error-grouper.js';
|
|
18
|
+
export { detectPatterns } from './pattern-detector.js';
|
|
19
|
+
export { calculateStats } from './stats.js';
|
|
20
|
+
export { templatize, isNoise, LEVEL_PRIORITY } from './utils.js';
|
|
21
|
+
import type { AnalysisOptions, AnalysisResult } from './types.js';
|
|
22
|
+
/**
|
|
23
|
+
* Full analysis pipeline: parse → enrich → context → group → pattern → stats.
|
|
24
|
+
*/
|
|
25
|
+
export declare function analyzeLogs(rawText: string, options?: AnalysisOptions): AnalysisResult;
|
|
26
|
+
//# sourceMappingURL=LogAnalyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analysis/LogAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,YAAY,EACR,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,eAAe,EACf,cAAc,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjE,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAQlE;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,cAAc,CAsC1F"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analyzer — Orchestrator
|
|
3
|
+
* Thin pipeline that composes the individual analysis modules.
|
|
4
|
+
*
|
|
5
|
+
* Module structure:
|
|
6
|
+
* - types.ts — Shared type definitions
|
|
7
|
+
* - utils.ts — Noise detection, templatization, constants
|
|
8
|
+
* - parser.ts — Multi-line log parser (JSON Logger, stack traces)
|
|
9
|
+
* - error-context.ts — Error context window builder
|
|
10
|
+
* - error-grouper.ts — Clusters similar errors
|
|
11
|
+
* - pattern-detector.ts — Identifies recurring message templates
|
|
12
|
+
* - stats.ts — Level distribution, error rate, spike detection
|
|
13
|
+
*/
|
|
14
|
+
// Re-export individual modules for direct use
|
|
15
|
+
export { parseRawLogs } from './parser.js';
|
|
16
|
+
export { buildErrorContexts } from './error-context.js';
|
|
17
|
+
export { groupErrors } from './error-grouper.js';
|
|
18
|
+
export { detectPatterns } from './pattern-detector.js';
|
|
19
|
+
export { calculateStats } from './stats.js';
|
|
20
|
+
export { templatize, isNoise, LEVEL_PRIORITY } from './utils.js';
|
|
21
|
+
import { LEVEL_PRIORITY } from './utils.js';
|
|
22
|
+
import { parseRawLogs } from './parser.js';
|
|
23
|
+
import { buildErrorContexts } from './error-context.js';
|
|
24
|
+
import { groupErrors } from './error-grouper.js';
|
|
25
|
+
import { detectPatterns } from './pattern-detector.js';
|
|
26
|
+
import { calculateStats } from './stats.js';
|
|
27
|
+
/**
|
|
28
|
+
* Full analysis pipeline: parse → enrich → context → group → pattern → stats.
|
|
29
|
+
*/
|
|
30
|
+
export function analyzeLogs(rawText, options = {}) {
|
|
31
|
+
const totalLines = rawText.split('\n').length;
|
|
32
|
+
// 1. Parse and join multi-line entries
|
|
33
|
+
let entries = parseRawLogs(rawText);
|
|
34
|
+
// 2. Filter by time if requested
|
|
35
|
+
if (options.hoursBack) {
|
|
36
|
+
const cutoff = Date.now() - options.hoursBack * 60 * 60 * 1000;
|
|
37
|
+
entries = entries.filter((e) => e.timestamp >= cutoff);
|
|
38
|
+
}
|
|
39
|
+
// 3. Filter by level if requested
|
|
40
|
+
if (options.level) {
|
|
41
|
+
const minLevel = LEVEL_PRIORITY[options.level.toUpperCase()] ?? 0;
|
|
42
|
+
entries = entries.filter((e) => (LEVEL_PRIORITY[e.priority] ?? 0) >= minLevel);
|
|
43
|
+
}
|
|
44
|
+
// 4. Build error contexts
|
|
45
|
+
const errorContexts = buildErrorContexts(entries, {
|
|
46
|
+
beforeCount: options.contextBefore,
|
|
47
|
+
afterCount: options.contextAfter,
|
|
48
|
+
});
|
|
49
|
+
// 5. Group errors
|
|
50
|
+
const errorGroups = groupErrors(errorContexts, {
|
|
51
|
+
maxGroups: options.maxErrorGroups,
|
|
52
|
+
});
|
|
53
|
+
// 6. Detect patterns
|
|
54
|
+
const patterns = detectPatterns(entries, {
|
|
55
|
+
topN: options.maxPatterns,
|
|
56
|
+
});
|
|
57
|
+
// 7. Calculate stats
|
|
58
|
+
const stats = calculateStats(entries, totalLines, errorGroups, patterns);
|
|
59
|
+
return { entries, errorContexts, errorGroups, patterns, stats };
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=LogAnalyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogAnalyzer.js","sourceRoot":"","sources":["../../src/analysis/LogAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAcH,8CAA8C;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,UAA2B,EAAE;IACtE,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAE9C,uCAAuC;IACvC,IAAI,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAEpC,iCAAiC;IACjC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAC/D,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC,CAAC;IAC3D,CAAC;IAED,kCAAkC;IAClC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;QAClE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC;IACnF,CAAC;IAED,0BAA0B;IAC1B,MAAM,aAAa,GAAG,kBAAkB,CAAC,OAAO,EAAE;QAC9C,WAAW,EAAE,OAAO,CAAC,aAAa;QAClC,UAAU,EAAE,OAAO,CAAC,YAAY;KACnC,CAAC,CAAC;IAEH,kBAAkB;IAClB,MAAM,WAAW,GAAG,WAAW,CAAC,aAAa,EAAE;QAC3C,SAAS,EAAE,OAAO,CAAC,cAAc;KACpC,CAAC,CAAC;IAEH,qBAAqB;IACrB,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,EAAE;QACrC,IAAI,EAAE,OAAO,CAAC,WAAW;KAC5B,CAAC,CAAC;IAEH,qBAAqB;IACrB,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IAEzE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis — Error Context
|
|
3
|
+
* Builds before/after context windows for ERROR entries.
|
|
4
|
+
* Uses correlation-based context when available, time-window fallback otherwise.
|
|
5
|
+
*/
|
|
6
|
+
import type { EnrichedLogEntry, ErrorWithContext } from './types.js';
|
|
7
|
+
export interface ErrorContextOptions {
|
|
8
|
+
/** Number of entries to capture before the error (default: 15) */
|
|
9
|
+
beforeCount?: number;
|
|
10
|
+
/** Number of entries to capture after the error (default: 10) */
|
|
11
|
+
afterCount?: number;
|
|
12
|
+
/** Time window in ms for fallback mode (default: 30000) */
|
|
13
|
+
timeWindowMs?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Build error context for all ERROR entries.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildErrorContexts(entries: EnrichedLogEntry[], options?: ErrorContextOptions): ErrorWithContext[];
|
|
19
|
+
//# sourceMappingURL=error-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-context.d.ts","sourceRoot":"","sources":["../../src/analysis/error-context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,mBAAmB;IAChC,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,OAAO,GAAE,mBAAwB,GAAG,gBAAgB,EAAE,CAiDrH"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis — Error Context
|
|
3
|
+
* Builds before/after context windows for ERROR entries.
|
|
4
|
+
* Uses correlation-based context when available, time-window fallback otherwise.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Build error context for all ERROR entries.
|
|
8
|
+
*/
|
|
9
|
+
export function buildErrorContexts(entries, options = {}) {
|
|
10
|
+
const beforeCount = options.beforeCount ?? 15;
|
|
11
|
+
const afterCount = options.afterCount ?? 10;
|
|
12
|
+
const timeWindowMs = options.timeWindowMs ?? 30000;
|
|
13
|
+
const errorEntries = entries.filter((e) => e.priority === 'ERROR');
|
|
14
|
+
const contexts = [];
|
|
15
|
+
// Build correlation index for fast lookup
|
|
16
|
+
const correlationIndex = new Map();
|
|
17
|
+
for (const entry of entries) {
|
|
18
|
+
if (entry.correlationId) {
|
|
19
|
+
let group = correlationIndex.get(entry.correlationId);
|
|
20
|
+
if (!group) {
|
|
21
|
+
group = [];
|
|
22
|
+
correlationIndex.set(entry.correlationId, group);
|
|
23
|
+
}
|
|
24
|
+
group.push(entry);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
for (const error of errorEntries) {
|
|
28
|
+
let before;
|
|
29
|
+
let after;
|
|
30
|
+
let correlationId;
|
|
31
|
+
if (error.correlationId && correlationIndex.has(error.correlationId)) {
|
|
32
|
+
// Correlation-based context — follow the full request lifecycle
|
|
33
|
+
correlationId = error.correlationId;
|
|
34
|
+
const correlated = correlationIndex.get(correlationId);
|
|
35
|
+
const errorIdx = correlated.indexOf(error);
|
|
36
|
+
before = correlated.slice(Math.max(0, errorIdx - beforeCount), errorIdx);
|
|
37
|
+
after = correlated.slice(errorIdx + 1, errorIdx + 1 + afterCount);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Time-window fallback
|
|
41
|
+
const errorIdx = entries.indexOf(error);
|
|
42
|
+
before = entries
|
|
43
|
+
.slice(Math.max(0, errorIdx - beforeCount), errorIdx)
|
|
44
|
+
.filter((e) => error.timestamp - e.timestamp <= timeWindowMs);
|
|
45
|
+
after = entries
|
|
46
|
+
.slice(errorIdx + 1, errorIdx + 1 + afterCount)
|
|
47
|
+
.filter((e) => e.timestamp - error.timestamp <= timeWindowMs);
|
|
48
|
+
}
|
|
49
|
+
const flowTrace = buildFlowTrace(before, error);
|
|
50
|
+
contexts.push({ error, before, after, correlationId, flowTrace });
|
|
51
|
+
}
|
|
52
|
+
return contexts;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extract the flow execution path from context entries.
|
|
56
|
+
*/
|
|
57
|
+
function buildFlowTrace(before, error) {
|
|
58
|
+
const flows = [];
|
|
59
|
+
const seen = new Set();
|
|
60
|
+
for (const entry of [...before, error]) {
|
|
61
|
+
const flow = entry.flowName;
|
|
62
|
+
if (flow && !seen.has(flow)) {
|
|
63
|
+
seen.add(flow);
|
|
64
|
+
flows.push(flow);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return flows;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=error-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-context.js","sourceRoot":"","sources":["../../src/analysis/error-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis — Error Grouper
|
|
3
|
+
* Clusters similar errors by (errorType + message template).
|
|
4
|
+
*/
|
|
5
|
+
import type { ErrorWithContext, ErrorGroup } from './types.js';
|
|
6
|
+
export interface ErrorGrouperOptions {
|
|
7
|
+
/** Maximum samples per group (default: 3) */
|
|
8
|
+
maxSamples?: number;
|
|
9
|
+
/** Maximum groups to return (default: 10) */
|
|
10
|
+
maxGroups?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Group similar errors by error type and message pattern.
|
|
14
|
+
*/
|
|
15
|
+
export declare function groupErrors(contexts: ErrorWithContext[], options?: ErrorGrouperOptions): ErrorGroup[];
|
|
16
|
+
//# sourceMappingURL=error-grouper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-grouper.d.ts","sourceRoot":"","sources":["../../src/analysis/error-grouper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG/D,MAAM,WAAW,mBAAmB;IAChC,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,gBAAgB,EAAE,EAAE,OAAO,GAAE,mBAAwB,GAAG,UAAU,EAAE,CAwCzG"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis — Error Grouper
|
|
3
|
+
* Clusters similar errors by (errorType + message template).
|
|
4
|
+
*/
|
|
5
|
+
import { templatize } from './utils.js';
|
|
6
|
+
/**
|
|
7
|
+
* Group similar errors by error type and message pattern.
|
|
8
|
+
*/
|
|
9
|
+
export function groupErrors(contexts, options = {}) {
|
|
10
|
+
const maxSamples = options.maxSamples ?? 3;
|
|
11
|
+
const maxGroups = options.maxGroups ?? 10;
|
|
12
|
+
const groups = new Map();
|
|
13
|
+
for (const ctx of contexts) {
|
|
14
|
+
const errorType = ctx.error.errorType || 'UNKNOWN';
|
|
15
|
+
const template = templatize(ctx.error.message || '');
|
|
16
|
+
const key = `${errorType}::${template}`;
|
|
17
|
+
let group = groups.get(key);
|
|
18
|
+
if (!group) {
|
|
19
|
+
group = { contexts: [], flows: new Set() };
|
|
20
|
+
groups.set(key, group);
|
|
21
|
+
}
|
|
22
|
+
group.contexts.push(ctx);
|
|
23
|
+
if (ctx.error.flowName) {
|
|
24
|
+
group.flows.add(ctx.error.flowName);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const sorted = [...groups.entries()]
|
|
28
|
+
.sort((a, b) => b[1].contexts.length - a[1].contexts.length)
|
|
29
|
+
.slice(0, maxGroups);
|
|
30
|
+
return sorted.map(([key, group]) => {
|
|
31
|
+
const [errorType, template] = key.split('::', 2);
|
|
32
|
+
const timestamps = group.contexts.map((c) => c.error.timestamp).sort();
|
|
33
|
+
return {
|
|
34
|
+
errorType,
|
|
35
|
+
template,
|
|
36
|
+
count: group.contexts.length,
|
|
37
|
+
firstSeen: new Date(timestamps[0]).toISOString(),
|
|
38
|
+
lastSeen: new Date(timestamps[timestamps.length - 1]).toISOString(),
|
|
39
|
+
samples: group.contexts.slice(0, maxSamples),
|
|
40
|
+
affectedFlows: [...group.flows],
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=error-grouper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-grouper.js","sourceRoot":"","sources":["../../src/analysis/error-grouper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AASxC;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAA4B,EAAE,UAA+B,EAAE;IACvF,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;IAE1C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAgE,CAAC;IAEvF,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,SAAS,CAAC;QACnD,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,GAAG,GAAG,GAAG,SAAS,KAAK,QAAQ,EAAE,CAAC;QAExC,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,KAAK,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;YAC3C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC3B,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrB,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACxC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SAC/B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;SAC3D,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAEzB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QAC/B,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC;QAEvE,OAAO;YACH,SAAS;YACT,QAAQ;YACR,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;YAC5B,SAAS,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;YAChD,QAAQ,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;YACnE,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;YAC5C,aAAa,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;SAClC,CAAC;IACN,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis — Parser
|
|
3
|
+
* Parses raw CloudHub log text into enriched entries, joining multi-line blocks.
|
|
4
|
+
* Handles: JSON Logger blocks, stack traces, HTTP dumps, continuation lines.
|
|
5
|
+
*/
|
|
6
|
+
import type { EnrichedLogEntry } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Parse raw log text into enriched entries, joining multi-line blocks.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseRawLogs(rawText: string): EnrichedLogEntry[];
|
|
11
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/analysis/parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AASnD;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAoFhE"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis — Parser
|
|
3
|
+
* Parses raw CloudHub log text into enriched entries, joining multi-line blocks.
|
|
4
|
+
* Handles: JSON Logger blocks, stack traces, HTTP dumps, continuation lines.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Enhanced log line regex that captures:
|
|
8
|
+
* - timestamp, level, instanceId, loggerName, eventId, thread, message
|
|
9
|
+
*/
|
|
10
|
+
const LOG_LINE_REGEX = /^(\d{4}-\d{2}-\d{2}T[\d:.]+Z)\s+(TRACE|DEBUG|INFO|WARN|ERROR|FATAL)\s+\[([^\]]*)\]\s+(\S+)\s+(?:event:(\S+)\s+)?(.+?)(?:\s+-\s+(.*))?$/;
|
|
11
|
+
/**
|
|
12
|
+
* Parse raw log text into enriched entries, joining multi-line blocks.
|
|
13
|
+
*/
|
|
14
|
+
export function parseRawLogs(rawText) {
|
|
15
|
+
const lines = rawText.split('\n');
|
|
16
|
+
const entries = [];
|
|
17
|
+
let current = null;
|
|
18
|
+
let jsonBuffer = null;
|
|
19
|
+
let jsonBraceDepth = 0;
|
|
20
|
+
for (const line of lines) {
|
|
21
|
+
if (!line.trim())
|
|
22
|
+
continue;
|
|
23
|
+
const match = line.match(LOG_LINE_REGEX);
|
|
24
|
+
if (match) {
|
|
25
|
+
// Flush any pending entry
|
|
26
|
+
if (current) {
|
|
27
|
+
if (jsonBuffer) {
|
|
28
|
+
finalizeJsonEntry(current, jsonBuffer);
|
|
29
|
+
jsonBuffer = null;
|
|
30
|
+
jsonBraceDepth = 0;
|
|
31
|
+
}
|
|
32
|
+
entries.push(current);
|
|
33
|
+
}
|
|
34
|
+
const [, timestamp, level, instanceId, loggerName, eventId, threadOrMessage, messageAfterDash] = match;
|
|
35
|
+
current = {
|
|
36
|
+
timestamp: new Date(timestamp).getTime(),
|
|
37
|
+
priority: level,
|
|
38
|
+
instanceId,
|
|
39
|
+
loggerName,
|
|
40
|
+
eventId,
|
|
41
|
+
threadName: messageAfterDash !== undefined ? threadOrMessage : undefined,
|
|
42
|
+
message: messageAfterDash !== undefined ? messageAfterDash : threadOrMessage,
|
|
43
|
+
};
|
|
44
|
+
// Check if this is a JSON Logger entry starting with "{"
|
|
45
|
+
if (current.message !== undefined) {
|
|
46
|
+
const trimmedMsg = current.message.trim();
|
|
47
|
+
if (trimmedMsg === '{' || trimmedMsg.endsWith('- {')) {
|
|
48
|
+
jsonBuffer = ['{'];
|
|
49
|
+
jsonBraceDepth = 1;
|
|
50
|
+
if (trimmedMsg.endsWith('- {')) {
|
|
51
|
+
current.message = trimmedMsg.slice(0, -3).trim();
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
current.message = '';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Continuation line — no timestamp prefix
|
|
61
|
+
if (jsonBuffer !== null) {
|
|
62
|
+
jsonBuffer.push(line);
|
|
63
|
+
for (const ch of line) {
|
|
64
|
+
if (ch === '{')
|
|
65
|
+
jsonBraceDepth++;
|
|
66
|
+
else if (ch === '}')
|
|
67
|
+
jsonBraceDepth--;
|
|
68
|
+
}
|
|
69
|
+
if (jsonBraceDepth <= 0) {
|
|
70
|
+
if (current) {
|
|
71
|
+
finalizeJsonEntry(current, jsonBuffer);
|
|
72
|
+
}
|
|
73
|
+
jsonBuffer = null;
|
|
74
|
+
jsonBraceDepth = 0;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else if (current) {
|
|
78
|
+
if (current.stackTrace) {
|
|
79
|
+
current.stackTrace += '\n' + line;
|
|
80
|
+
}
|
|
81
|
+
else if (line.match(/^\s+(at |Caused by:|\.{3}\s+\d+\s+more|Error type|Element DSL)/)) {
|
|
82
|
+
current.stackTrace = line;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
current.message = (current.message || '') + '\n' + line;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Flush last entry
|
|
91
|
+
if (current) {
|
|
92
|
+
if (jsonBuffer) {
|
|
93
|
+
finalizeJsonEntry(current, jsonBuffer);
|
|
94
|
+
}
|
|
95
|
+
entries.push(current);
|
|
96
|
+
}
|
|
97
|
+
return entries;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Parse accumulated JSON lines and enrich the log entry with structured fields.
|
|
101
|
+
*/
|
|
102
|
+
function finalizeJsonEntry(entry, jsonLines) {
|
|
103
|
+
const jsonText = jsonLines.join('\n');
|
|
104
|
+
try {
|
|
105
|
+
const parsed = JSON.parse(jsonText);
|
|
106
|
+
entry.jsonPayload = parsed;
|
|
107
|
+
entry.correlationId = parsed.correlationId || entry.correlationId;
|
|
108
|
+
entry.elapsed = parsed.elapsed;
|
|
109
|
+
entry.tracePoint = parsed.tracePoint;
|
|
110
|
+
entry.flowName = parsed.content?.flowName || parsed.locationInfo?.rootContainer;
|
|
111
|
+
entry.errorType = parsed.errorType || parsed.content?.errorType || parsed.content?.errorCode;
|
|
112
|
+
if (parsed.message && (!entry.message || entry.message.trim() === '')) {
|
|
113
|
+
entry.message = parsed.message;
|
|
114
|
+
}
|
|
115
|
+
if (parsed.Stacktrace__c || parsed.content?.Stacktrace__c) {
|
|
116
|
+
entry.stackTrace = parsed.Stacktrace__c || parsed.content?.Stacktrace__c;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
entry.message = (entry.message || '') + '\n' + jsonText;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/analysis/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis — Pattern Detector
|
|
3
|
+
* Identifies the top N recurring log message templates.
|
|
4
|
+
*/
|
|
5
|
+
import type { EnrichedLogEntry, LogPattern } from './types.js';
|
|
6
|
+
export interface PatternDetectorOptions {
|
|
7
|
+
/** Number of top patterns to return (default: 15) */
|
|
8
|
+
topN?: number;
|
|
9
|
+
/** Whether to exclude HTTP listener noise (default: true) */
|
|
10
|
+
excludeNoise?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Identify recurring log message templates.
|
|
14
|
+
*/
|
|
15
|
+
export declare function detectPatterns(entries: EnrichedLogEntry[], options?: PatternDetectorOptions): LogPattern[];
|
|
16
|
+
//# sourceMappingURL=pattern-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-detector.d.ts","sourceRoot":"","sources":["../../src/analysis/pattern-detector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG/D,MAAM,WAAW,sBAAsB;IACnC,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,OAAO,GAAE,sBAA2B,GAAG,UAAU,EAAE,CAgC9G"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis — Pattern Detector
|
|
3
|
+
* Identifies the top N recurring log message templates.
|
|
4
|
+
*/
|
|
5
|
+
import { templatize, isNoise } from './utils.js';
|
|
6
|
+
/**
|
|
7
|
+
* Identify recurring log message templates.
|
|
8
|
+
*/
|
|
9
|
+
export function detectPatterns(entries, options = {}) {
|
|
10
|
+
const topN = options.topN ?? 15;
|
|
11
|
+
const excludeNoise = options.excludeNoise ?? true;
|
|
12
|
+
const counts = new Map();
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
if (excludeNoise && isNoise(entry))
|
|
15
|
+
continue;
|
|
16
|
+
const template = templatize(entry.message || '');
|
|
17
|
+
const key = `${entry.priority}::${template}`;
|
|
18
|
+
const existing = counts.get(key);
|
|
19
|
+
if (existing) {
|
|
20
|
+
existing.count++;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
counts.set(key, { count: 1, level: entry.priority, loggerName: entry.loggerName });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const total = excludeNoise ? entries.filter((e) => !isNoise(e)).length : entries.length;
|
|
27
|
+
return [...counts.entries()]
|
|
28
|
+
.sort((a, b) => b[1].count - a[1].count)
|
|
29
|
+
.slice(0, topN)
|
|
30
|
+
.map(([key, val]) => ({
|
|
31
|
+
template: key.split('::', 2)[1],
|
|
32
|
+
count: val.count,
|
|
33
|
+
level: val.level,
|
|
34
|
+
percentage: total > 0 ? Math.round((val.count / total) * 10000) / 100 : 0,
|
|
35
|
+
loggerName: val.loggerName,
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=pattern-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-detector.js","sourceRoot":"","sources":["../../src/analysis/pattern-detector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AASjD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAA2B,EAAE,UAAkC,EAAE;IAC5F,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;IAChC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,IAAI,CAAC;IAElD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiE,CAAC;IAExF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC;YAAE,SAAS;QAE7C,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAE7C,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,QAAQ,EAAE,CAAC;YACX,QAAQ,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;aAAM,CAAC;YACJ,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QACvF,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAExF,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACvB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;SACvC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;SACd,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAClB,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/B,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,UAAU,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACzE,UAAU,EAAE,GAAG,CAAC,UAAU;KAC7B,CAAC,CAAC,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis — Stats Calculator
|
|
3
|
+
* Computes level distribution, error rate, spikes, and noise percentage.
|
|
4
|
+
*/
|
|
5
|
+
import type { EnrichedLogEntry, ErrorGroup, LogPattern, LogStats } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Compute comprehensive statistics for a set of enriched entries.
|
|
8
|
+
*/
|
|
9
|
+
export declare function calculateStats(entries: EnrichedLogEntry[], totalLines: number, errorGroups?: ErrorGroup[], patterns?: LogPattern[]): LogStats;
|
|
10
|
+
//# sourceMappingURL=stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/analysis/stats.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAc,MAAM,YAAY,CAAC;AAGjG;;GAEG;AACH,wBAAgB,cAAc,CAC1B,OAAO,EAAE,gBAAgB,EAAE,EAC3B,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,UAAU,EAAE,EAC1B,QAAQ,CAAC,EAAE,UAAU,EAAE,GACxB,QAAQ,CAmCV"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis — Stats Calculator
|
|
3
|
+
* Computes level distribution, error rate, spikes, and noise percentage.
|
|
4
|
+
*/
|
|
5
|
+
import { isNoise } from './utils.js';
|
|
6
|
+
/**
|
|
7
|
+
* Compute comprehensive statistics for a set of enriched entries.
|
|
8
|
+
*/
|
|
9
|
+
export function calculateStats(entries, totalLines, errorGroups, patterns) {
|
|
10
|
+
const byLevel = {};
|
|
11
|
+
let noiseCount = 0;
|
|
12
|
+
const correlationIds = new Set();
|
|
13
|
+
const timestamps = [];
|
|
14
|
+
for (const entry of entries) {
|
|
15
|
+
byLevel[entry.priority] = (byLevel[entry.priority] || 0) + 1;
|
|
16
|
+
if (isNoise(entry))
|
|
17
|
+
noiseCount++;
|
|
18
|
+
if (entry.correlationId)
|
|
19
|
+
correlationIds.add(entry.correlationId);
|
|
20
|
+
if (entry.timestamp)
|
|
21
|
+
timestamps.push(entry.timestamp);
|
|
22
|
+
}
|
|
23
|
+
timestamps.sort((a, b) => a - b);
|
|
24
|
+
const errorCount = byLevel['ERROR'] || 0;
|
|
25
|
+
const totalEntries = entries.length;
|
|
26
|
+
const errorRate = totalEntries > 0 ? Math.round((errorCount / totalEntries) * 10000) / 100 : 0;
|
|
27
|
+
const errorSpikes = calculateErrorSpikes(entries, 5 * 60 * 1000);
|
|
28
|
+
return {
|
|
29
|
+
totalLines,
|
|
30
|
+
totalEntries,
|
|
31
|
+
byLevel,
|
|
32
|
+
errorRate,
|
|
33
|
+
timeRange: {
|
|
34
|
+
start: timestamps.length > 0 ? new Date(timestamps[0]).toISOString() : '',
|
|
35
|
+
end: timestamps.length > 0 ? new Date(timestamps[timestamps.length - 1]).toISOString() : '',
|
|
36
|
+
},
|
|
37
|
+
errorSpikes,
|
|
38
|
+
topErrors: errorGroups || [],
|
|
39
|
+
topPatterns: patterns || [],
|
|
40
|
+
noisePercentage: totalEntries > 0 ? Math.round((noiseCount / totalEntries) * 10000) / 100 : 0,
|
|
41
|
+
uniqueCorrelationIds: correlationIds.size,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Find 5-minute windows with above-average error rates.
|
|
46
|
+
*/
|
|
47
|
+
function calculateErrorSpikes(entries, windowMs) {
|
|
48
|
+
if (entries.length === 0)
|
|
49
|
+
return [];
|
|
50
|
+
const timestamps = entries.map((e) => e.timestamp).sort((a, b) => a - b);
|
|
51
|
+
const start = timestamps[0];
|
|
52
|
+
const end = timestamps[timestamps.length - 1];
|
|
53
|
+
if (end - start < windowMs)
|
|
54
|
+
return [];
|
|
55
|
+
const windows = new Map();
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
const windowStart = Math.floor((entry.timestamp - start) / windowMs) * windowMs + start;
|
|
58
|
+
let w = windows.get(windowStart);
|
|
59
|
+
if (!w) {
|
|
60
|
+
w = { total: 0, errors: 0 };
|
|
61
|
+
windows.set(windowStart, w);
|
|
62
|
+
}
|
|
63
|
+
w.total++;
|
|
64
|
+
if (entry.priority === 'ERROR')
|
|
65
|
+
w.errors++;
|
|
66
|
+
}
|
|
67
|
+
const totalErrors = entries.filter((e) => e.priority === 'ERROR').length;
|
|
68
|
+
const avgErrorRate = entries.length > 0 ? totalErrors / entries.length : 0;
|
|
69
|
+
const spikes = [];
|
|
70
|
+
for (const [windowStart, w] of windows) {
|
|
71
|
+
const rate = w.total > 0 ? w.errors / w.total : 0;
|
|
72
|
+
if (rate > avgErrorRate * 1.5 && w.errors > 0) {
|
|
73
|
+
spikes.push({
|
|
74
|
+
window: new Date(windowStart).toISOString(),
|
|
75
|
+
count: w.errors,
|
|
76
|
+
rate: Math.round(rate * 10000) / 100,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return spikes.sort((a, b) => b.count - a.count).slice(0, 10);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/analysis/stats.ts"],"names":[],"mappings":"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"}
|