@sfdxy/anypoint-connect 0.14.0 → 0.16.2
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 +39 -16
- package/dist/analysis/LogAnalyzer.d.ts +10 -4
- package/dist/analysis/LogAnalyzer.d.ts.map +1 -1
- package/dist/analysis/LogAnalyzer.js +29 -18
- package/dist/analysis/LogAnalyzer.js.map +1 -1
- package/dist/analysis/error-context.d.ts +2 -0
- package/dist/analysis/error-context.d.ts.map +1 -1
- package/dist/analysis/error-context.js +2 -1
- package/dist/analysis/error-context.js.map +1 -1
- package/dist/analysis/error-grouper.js +1 -1
- package/dist/analysis/error-grouper.js.map +1 -1
- package/dist/analysis/filter.d.ts +54 -0
- package/dist/analysis/filter.d.ts.map +1 -0
- package/dist/analysis/filter.js +100 -0
- package/dist/analysis/filter.js.map +1 -0
- package/dist/analysis/{utils.d.ts → normalize.d.ts} +1 -1
- package/dist/analysis/normalize.d.ts.map +1 -0
- package/dist/analysis/{utils.js → normalize.js} +2 -2
- package/dist/analysis/normalize.js.map +1 -0
- package/dist/analysis/parser.d.ts.map +1 -1
- package/dist/analysis/parser.js +45 -17
- package/dist/analysis/parser.js.map +1 -1
- package/dist/analysis/pattern-detector.js +1 -1
- package/dist/analysis/pattern-detector.js.map +1 -1
- package/dist/analysis/stats.d.ts +25 -0
- package/dist/analysis/stats.d.ts.map +1 -1
- package/dist/analysis/stats.js +35 -1
- package/dist/analysis/stats.js.map +1 -1
- package/dist/analysis/summary.d.ts +51 -0
- package/dist/analysis/summary.d.ts.map +1 -0
- package/dist/analysis/summary.js +47 -0
- package/dist/analysis/summary.js.map +1 -0
- package/dist/analysis/types.d.ts +14 -0
- package/dist/analysis/types.d.ts.map +1 -1
- package/dist/api/ApiManagerApi.d.ts +53 -0
- package/dist/api/ApiManagerApi.d.ts.map +1 -1
- package/dist/api/ApiManagerApi.js +53 -2
- package/dist/api/ApiManagerApi.js.map +1 -1
- package/dist/api/CloudHub2Api.d.ts +24 -4
- package/dist/api/CloudHub2Api.d.ts.map +1 -1
- package/dist/api/CloudHub2Api.js +10 -22
- package/dist/api/CloudHub2Api.js.map +1 -1
- package/dist/api/DesignCenterApi.d.ts +0 -20
- package/dist/api/DesignCenterApi.d.ts.map +1 -1
- package/dist/api/DesignCenterApi.js +0 -22
- package/dist/api/DesignCenterApi.js.map +1 -1
- package/dist/api/ExchangeApi.d.ts +15 -0
- package/dist/api/ExchangeApi.d.ts.map +1 -1
- package/dist/api/ExchangeApi.js +51 -0
- package/dist/api/ExchangeApi.js.map +1 -1
- package/dist/api/LogsApi.d.ts +50 -18
- package/dist/api/LogsApi.d.ts.map +1 -1
- package/dist/api/LogsApi.js +69 -98
- package/dist/api/LogsApi.js.map +1 -1
- package/dist/api/MonitoringApi.d.ts +137 -93
- package/dist/api/MonitoringApi.d.ts.map +1 -1
- package/dist/api/MonitoringApi.js +471 -204
- package/dist/api/MonitoringApi.js.map +1 -1
- package/dist/api/RuntimesApi.d.ts +56 -0
- package/dist/api/RuntimesApi.d.ts.map +1 -0
- package/dist/api/RuntimesApi.js +58 -0
- package/dist/api/RuntimesApi.js.map +1 -0
- package/dist/auth/FileStore.js +1 -1
- package/dist/auth/FileStore.js.map +1 -1
- package/dist/cli.js +4 -2
- package/dist/cli.js.map +1 -1
- package/dist/client/AnypointClient.d.ts +3 -1
- package/dist/client/AnypointClient.d.ts.map +1 -1
- package/dist/client/AnypointClient.js +5 -2
- package/dist/client/AnypointClient.js.map +1 -1
- package/dist/client/smoke-test.d.ts +111 -0
- package/dist/client/smoke-test.d.ts.map +1 -0
- package/dist/client/smoke-test.js +275 -0
- package/dist/client/smoke-test.js.map +1 -0
- package/dist/commands/api.d.ts +1 -1
- package/dist/commands/api.d.ts.map +1 -1
- package/dist/commands/api.js +175 -30
- package/dist/commands/api.js.map +1 -1
- package/dist/commands/app-change-cli.d.ts +52 -0
- package/dist/commands/app-change-cli.d.ts.map +1 -0
- package/dist/commands/app-change-cli.js +149 -0
- package/dist/commands/app-change-cli.js.map +1 -0
- package/dist/commands/apps.d.ts +1 -1
- package/dist/commands/apps.d.ts.map +1 -1
- package/dist/commands/apps.js +199 -18
- package/dist/commands/apps.js.map +1 -1
- package/dist/commands/auth.js +1 -1
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/compare.d.ts +8 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +104 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/config.js +1 -1
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/deploy.d.ts +6 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +89 -91
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/design-center.d.ts +1 -1
- package/dist/commands/design-center.d.ts.map +1 -1
- package/dist/commands/design-center.js +36 -25
- package/dist/commands/design-center.js.map +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/logs.d.ts +3 -2
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +142 -17
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/monitor.d.ts +5 -6
- package/dist/commands/monitor.d.ts.map +1 -1
- package/dist/commands/monitor.js +210 -230
- package/dist/commands/monitor.js.map +1 -1
- package/dist/commands/runtimes.d.ts +7 -0
- package/dist/commands/runtimes.d.ts.map +1 -0
- package/dist/commands/runtimes.js +66 -0
- package/dist/commands/runtimes.js.map +1 -0
- package/dist/commands/shared.d.ts +2 -0
- package/dist/commands/shared.d.ts.map +1 -1
- package/dist/commands/shared.js +16 -1
- package/dist/commands/shared.js.map +1 -1
- package/dist/{utils/config.d.ts → config/profiles.d.ts} +9 -1
- package/dist/config/profiles.d.ts.map +1 -0
- package/dist/{utils/config.js → config/profiles.js} +1 -1
- package/dist/config/profiles.js.map +1 -0
- package/dist/index.d.ts +12 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/prompts.js +7 -7
- package/dist/mcp/prompts.js.map +1 -1
- package/dist/mcp/server.d.ts +14 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +61 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/analysis.d.ts.map +1 -1
- package/dist/mcp/tools/analysis.js +74 -46
- package/dist/mcp/tools/analysis.js.map +1 -1
- package/dist/mcp/tools/anypoint-mq.d.ts.map +1 -1
- package/dist/mcp/tools/anypoint-mq.js +25 -54
- package/dist/mcp/tools/anypoint-mq.js.map +1 -1
- package/dist/mcp/tools/api-manager.d.ts +2 -1
- package/dist/mcp/tools/api-manager.d.ts.map +1 -1
- package/dist/mcp/tools/api-manager.js +154 -89
- package/dist/mcp/tools/api-manager.js.map +1 -1
- package/dist/mcp/tools/app-inputs.d.ts +92 -0
- package/dist/mcp/tools/app-inputs.d.ts.map +1 -0
- package/dist/mcp/tools/app-inputs.js +142 -0
- package/dist/mcp/tools/app-inputs.js.map +1 -0
- package/dist/mcp/tools/apps-deploy.d.ts +13 -0
- package/dist/mcp/tools/apps-deploy.d.ts.map +1 -0
- package/dist/mcp/tools/apps-deploy.js +358 -0
- package/dist/mcp/tools/apps-deploy.js.map +1 -0
- package/dist/mcp/tools/apps-lifecycle.d.ts +11 -0
- package/dist/mcp/tools/apps-lifecycle.d.ts.map +1 -0
- package/dist/mcp/tools/apps-lifecycle.js +244 -0
- package/dist/mcp/tools/apps-lifecycle.js.map +1 -0
- package/dist/mcp/tools/apps-read.d.ts +9 -0
- package/dist/mcp/tools/apps-read.d.ts.map +1 -0
- package/dist/mcp/tools/apps-read.js +414 -0
- package/dist/mcp/tools/apps-read.js.map +1 -0
- package/dist/mcp/tools/artifacts.d.ts +8 -0
- package/dist/mcp/tools/artifacts.d.ts.map +1 -0
- package/dist/mcp/tools/artifacts.js +81 -0
- package/dist/mcp/tools/artifacts.js.map +1 -0
- package/dist/mcp/tools/audit.d.ts.map +1 -1
- package/dist/mcp/tools/audit.js +9 -17
- package/dist/mcp/tools/audit.js.map +1 -1
- package/dist/mcp/tools/design-center.d.ts +2 -3
- package/dist/mcp/tools/design-center.d.ts.map +1 -1
- package/dist/mcp/tools/design-center.js +41 -185
- package/dist/mcp/tools/design-center.js.map +1 -1
- package/dist/mcp/tools/exchange.d.ts +1 -2
- package/dist/mcp/tools/exchange.d.ts.map +1 -1
- package/dist/mcp/tools/exchange.js +51 -312
- package/dist/mcp/tools/exchange.js.map +1 -1
- package/dist/mcp/tools/governance.d.ts +8 -0
- package/dist/mcp/tools/governance.d.ts.map +1 -0
- package/dist/mcp/tools/governance.js +59 -0
- package/dist/mcp/tools/governance.js.map +1 -0
- package/dist/mcp/tools/identity.d.ts.map +1 -1
- package/dist/mcp/tools/identity.js +15 -36
- package/dist/mcp/tools/identity.js.map +1 -1
- package/dist/mcp/tools/index.d.ts +5 -1
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +5 -1
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/logs.d.ts +48 -2
- package/dist/mcp/tools/logs.d.ts.map +1 -1
- package/dist/mcp/tools/logs.js +204 -54
- package/dist/mcp/tools/logs.js.map +1 -1
- package/dist/mcp/tools/monitoring.d.ts +1 -2
- package/dist/mcp/tools/monitoring.d.ts.map +1 -1
- package/dist/mcp/tools/monitoring.js +78 -285
- package/dist/mcp/tools/monitoring.js.map +1 -1
- package/dist/mcp/tools/object-store.d.ts +1 -1
- package/dist/mcp/tools/object-store.d.ts.map +1 -1
- package/dist/mcp/tools/object-store.js +19 -59
- package/dist/mcp/tools/object-store.js.map +1 -1
- package/dist/mcp/tools/profile.d.ts.map +1 -1
- package/dist/mcp/tools/profile.js +15 -35
- package/dist/mcp/tools/profile.js.map +1 -1
- package/dist/mcp/tools/shared.d.ts +43 -0
- package/dist/mcp/tools/shared.d.ts.map +1 -1
- package/dist/mcp/tools/shared.js +54 -0
- package/dist/mcp/tools/shared.js.map +1 -1
- package/dist/mcp.d.ts +3 -11
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +4 -56
- package/dist/mcp.js.map +1 -1
- package/dist/safety/deployment.d.ts +47 -2
- package/dist/safety/deployment.d.ts.map +1 -1
- package/dist/safety/deployment.js +139 -6
- package/dist/safety/deployment.js.map +1 -1
- package/dist/safety/guards.d.ts +2 -2
- package/dist/safety/guards.d.ts.map +1 -1
- package/dist/safety/guards.js +4 -4
- package/dist/safety/guards.js.map +1 -1
- package/dist/safety/paths.d.ts +29 -0
- package/dist/safety/paths.d.ts.map +1 -0
- package/dist/safety/paths.js +76 -0
- package/dist/safety/paths.js.map +1 -0
- package/dist/safety/runtime.d.ts +24 -0
- package/dist/safety/runtime.d.ts.map +1 -0
- package/dist/safety/runtime.js +59 -0
- package/dist/safety/runtime.js.map +1 -0
- package/dist/safety/secret-sources.d.ts +51 -0
- package/dist/safety/secret-sources.d.ts.map +1 -0
- package/dist/safety/secret-sources.js +124 -0
- package/dist/safety/secret-sources.js.map +1 -0
- package/dist/safety/secrets.d.ts +32 -0
- package/dist/safety/secrets.d.ts.map +1 -0
- package/dist/safety/secrets.js +91 -0
- package/dist/safety/secrets.js.map +1 -0
- package/dist/utils/errors.d.ts +14 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +31 -3
- package/dist/utils/errors.js.map +1 -1
- package/dist/workflows/app-change.d.ts +124 -0
- package/dist/workflows/app-change.d.ts.map +1 -0
- package/dist/workflows/app-change.js +305 -0
- package/dist/workflows/app-change.js.map +1 -0
- package/dist/workflows/app-state.d.ts +60 -0
- package/dist/workflows/app-state.d.ts.map +1 -0
- package/dist/workflows/app-state.js +95 -0
- package/dist/workflows/app-state.js.map +1 -0
- package/dist/workflows/artifact-compare.d.ts +134 -0
- package/dist/workflows/artifact-compare.d.ts.map +1 -0
- package/dist/workflows/artifact-compare.js +419 -0
- package/dist/workflows/artifact-compare.js.map +1 -0
- package/dist/workflows/asset-naming.d.ts +72 -0
- package/dist/workflows/asset-naming.d.ts.map +1 -0
- package/dist/workflows/asset-naming.js +116 -0
- package/dist/workflows/asset-naming.js.map +1 -0
- package/dist/{api/DesignCenterWorkflow.d.ts → workflows/design-center.d.ts} +4 -4
- package/dist/workflows/design-center.d.ts.map +1 -0
- package/dist/{api/DesignCenterWorkflow.js → workflows/design-center.js} +1 -1
- package/dist/workflows/design-center.js.map +1 -0
- package/dist/workflows/jar-deployment.d.ts +156 -0
- package/dist/workflows/jar-deployment.d.ts.map +1 -0
- package/dist/workflows/jar-deployment.js +178 -0
- package/dist/workflows/jar-deployment.js.map +1 -0
- package/package.json +12 -4
- package/dist/analysis/utils.d.ts.map +0 -1
- package/dist/analysis/utils.js.map +0 -1
- package/dist/api/DesignCenterWorkflow.d.ts.map +0 -1
- package/dist/api/DesignCenterWorkflow.js.map +0 -1
- package/dist/api/index.d.ts +0 -13
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -13
- package/dist/api/index.js.map +0 -1
- package/dist/mcp/tools/applications.d.ts +0 -4
- package/dist/mcp/tools/applications.d.ts.map +0 -1
- package/dist/mcp/tools/applications.js +0 -815
- package/dist/mcp/tools/applications.js.map +0 -1
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js.map +0 -1
package/README.md
CHANGED
|
@@ -63,16 +63,29 @@ release does not support the `client_credentials` grant, and its encrypted token
|
|
|
63
63
|
|
|
64
64
|
| Area | Examples |
|
|
65
65
|
| --- | --- |
|
|
66
|
-
| Applications | Status, deployment spec, resources,
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
66
|
+
| Applications | Status with a start-up-aware phase, deployment spec, resources, cross-environment comparison, publish and deploy a JAR, one-call `update_app` (version, runtime, settings and update strategy, in place or stop-then-start), runtime catalogs with retired-runtime refusal, asset naming conventions, rollback, restart, scale, stop, start, delete, and a check of what runs against a repo or JAR |
|
|
67
|
+
| Settings | Add, change, remove and move properties; secret values read from project files or environment variables; secret-looking plain values masked and flagged |
|
|
68
|
+
| Logs | Tail, search over message, logger and stack trace, download with filters, summaries and file output, error clustering with context, recurring patterns, log health statistics |
|
|
69
|
+
| Monitoring | Traffic, failures, and p50–p99 latency per app, worker, or route; heap, old-generation pressure, GC, CPU, and RAM per worker; time series from 1-minute to 1-day buckets; freeform AMQL |
|
|
70
|
+
| Exchange | Search, asset details, spec download, application JAR publication |
|
|
71
|
+
| API Manager and Governance | Instances, policies, SLA tiers, alerts, contracts, client applications with masked credentials, smoke tests with the client's credentials, governance rulesets and conformance |
|
|
72
|
+
| Design Center | Projects, branches, file reads, preview-then-apply file sync, verified Exchange publication |
|
|
72
73
|
| Platform services | Environments, entitlements, audit log, Anypoint MQ, Object Store v2 |
|
|
73
74
|
|
|
75
|
+
New in 0.16, each with a recipe:
|
|
76
|
+
|
|
77
|
+
- `update_app` with `mode: "stopStart"`: [deploy a listener-driven app without overlap](https://avinava.github.io/anypoint-connect/recipes/#deploy-a-listener-driven-app-without-overlap)
|
|
78
|
+
- `list_runtime_versions`: [move an app off a retired runtime](https://avinava.github.io/anypoint-connect/recipes/#move-an-app-off-a-retired-runtime)
|
|
79
|
+
- `securePropertiesFrom`: [add or rotate one secret](https://avinava.github.io/anypoint-connect/recipes/#add-or-rotate-one-secret)
|
|
80
|
+
- `moveToSecure`: [move a plain-text secret to secure](https://avinava.github.io/anypoint-connect/recipes/#move-a-plain-text-secret-to-secure)
|
|
81
|
+
- `compare_deployed_artifact`: [check that a repository matches what runs](https://avinava.github.io/anypoint-connect/recipes/#check-that-a-repository-matches-what-runs)
|
|
82
|
+
- `smoke_test_api`: [smoke test an API with its client credentials](https://avinava.github.io/anypoint-connect/recipes/#smoke-test-an-api-with-its-client-credentials)
|
|
83
|
+
- `download_logs` summary and `outputFile`: [keep log downloads small](https://avinava.github.io/anypoint-connect/recipes/#keep-log-downloads-small)
|
|
84
|
+
|
|
74
85
|
Copyable task flows are in [Common recipes](https://avinava.github.io/anypoint-connect/recipes/); every CLI
|
|
75
|
-
command is in the [CLI reference](https://avinava.github.io/anypoint-connect/cli-reference/)
|
|
86
|
+
command is in the [CLI reference](https://avinava.github.io/anypoint-connect/cli-reference/), every MCP tool
|
|
87
|
+
in the [tool catalog](https://avinava.github.io/anypoint-connect/tools/), and how to read runtime metrics in
|
|
88
|
+
[Monitoring](https://avinava.github.io/anypoint-connect/monitoring/).
|
|
76
89
|
|
|
77
90
|
## MCP server
|
|
78
91
|
|
|
@@ -84,7 +97,7 @@ OAuth tokens; it sends tool calls to the local server that owns the session.
|
|
|
84
97
|
"mcpServers": {
|
|
85
98
|
"anypoint-connect": {
|
|
86
99
|
"command": "npx",
|
|
87
|
-
"args": ["-y", "@sfdxy/anypoint-connect@0.
|
|
100
|
+
"args": ["-y", "@sfdxy/anypoint-connect@0.16.2", "mcp"]
|
|
88
101
|
}
|
|
89
102
|
}
|
|
90
103
|
}
|
|
@@ -99,33 +112,43 @@ Example requests use synthetic names:
|
|
|
99
112
|
```text
|
|
100
113
|
What applications are visible in Sandbox? Read only.
|
|
101
114
|
Analyze errors for sample-orders-api in Sandbox over the last two hours.
|
|
115
|
+
Is the old generation of sample-orders-api in Production close to its limit?
|
|
102
116
|
Preview a deployment of target/sample-orders-api-1.3.0-mule-application.jar to Sandbox; do not apply it.
|
|
103
117
|
```
|
|
104
118
|
|
|
105
119
|
## Safety
|
|
106
120
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
121
|
+
Every MCP write tool returns a preview first and changes nothing until it is called again with
|
|
122
|
+
`confirm: true`; in production it also needs `confirmProduction: true`. `anc deploy --dry-run` and
|
|
123
|
+
`anc apps update --dry-run` print the same plan.
|
|
124
|
+
Publishing binds the JAR's SHA-256. A change to an existing app is one update that carries only what you
|
|
125
|
+
asked to change, with the runtime checked against the target first. Secret values come from project files
|
|
126
|
+
or environment variables, never the conversation. Deletion requires the deployment ID returned by the
|
|
127
|
+
preview, and Design Center writes require a single-use preview token.
|
|
110
128
|
|
|
111
129
|
```jsonc
|
|
112
130
|
// Preview only
|
|
113
|
-
|
|
114
|
-
"appName": "
|
|
131
|
+
update_app({
|
|
132
|
+
"appName": "orders-sapi",
|
|
115
133
|
"environment": "Sandbox",
|
|
116
|
-
"version": "1.3.0"
|
|
134
|
+
"version": "1.3.0",
|
|
135
|
+
"mode": "stopStart"
|
|
117
136
|
})
|
|
118
137
|
|
|
119
138
|
// Apply the reviewed change
|
|
120
|
-
|
|
121
|
-
"appName": "
|
|
139
|
+
update_app({
|
|
140
|
+
"appName": "orders-sapi",
|
|
122
141
|
"environment": "Sandbox",
|
|
123
142
|
"version": "1.3.0",
|
|
143
|
+
"mode": "stopStart",
|
|
124
144
|
"confirm": true
|
|
125
145
|
})
|
|
126
146
|
```
|
|
127
147
|
|
|
128
148
|
The complete contract is in the [safety model](https://avinava.github.io/anypoint-connect/safety/).
|
|
149
|
+
Upgrading from 0.15? The
|
|
150
|
+
[migration tables](https://github.com/Avinava/anypoint-connect/blob/main/CHANGELOG.md#migration-from-015x)
|
|
151
|
+
list every changed tool, command and library call.
|
|
129
152
|
|
|
130
153
|
## Library
|
|
131
154
|
|
|
@@ -9,18 +9,24 @@
|
|
|
9
9
|
* - error-context.ts — Error context window builder
|
|
10
10
|
* - error-grouper.ts — Clusters similar errors
|
|
11
11
|
* - pattern-detector.ts — Identifies recurring message templates
|
|
12
|
-
* - stats.ts — Level distribution, error rate, spike detection
|
|
12
|
+
* - stats.ts — Level distribution, error rate, spike detection, histogram
|
|
13
|
+
* - filter.ts - Time, level, logger and text filters shared by every log surface
|
|
13
14
|
*/
|
|
14
15
|
export type { EnrichedLogEntry, ErrorWithContext, ErrorGroup, LogPattern, ErrorSpike, LogStats, AnalysisOptions, AnalysisResult, } from './types.js';
|
|
15
16
|
export { parseRawLogs } from './parser.js';
|
|
16
17
|
export { buildErrorContexts } from './error-context.js';
|
|
17
18
|
export { groupErrors } from './error-grouper.js';
|
|
18
19
|
export { detectPatterns } from './pattern-detector.js';
|
|
19
|
-
export { calculateStats } from './stats.js';
|
|
20
|
-
export { templatize, isNoise, LEVEL_PRIORITY } from './
|
|
20
|
+
export { calculateStats, histogram, topCounts, BUCKETS, type Bucket, type HistogramBucket } from './stats.js';
|
|
21
|
+
export { templatize, isNoise, LEVEL_PRIORITY } from './normalize.js';
|
|
22
|
+
export { buildFilter, filterEntries, searchEntries, entryText, clampLimit, MAX_LOG_LINES, type LogFilter, type LogSearchOptions, type LogSearchResult, } from './filter.js';
|
|
23
|
+
export { summarizeEntries, formatEntry, formatEntries, MAX_HISTOGRAM_ROWS, type LogSummary, type SummaryOptions, } from './summary.js';
|
|
21
24
|
import type { AnalysisOptions, AnalysisResult } from './types.js';
|
|
22
25
|
/**
|
|
23
|
-
* Full analysis pipeline: parse →
|
|
26
|
+
* Full analysis pipeline: parse → filter → context → group → pattern → stats.
|
|
27
|
+
* The time window applies to everything. Level, logger and search select the entries
|
|
28
|
+
* that are counted and analyzed as errors; error context still comes from every entry
|
|
29
|
+
* in the window, so a filtered error keeps the lines that led up to it.
|
|
24
30
|
*/
|
|
25
31
|
export declare function analyzeLogs(rawText: string, options?: AnalysisOptions): AnalysisResult;
|
|
26
32
|
//# sourceMappingURL=LogAnalyzer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LogAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analysis/LogAnalyzer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"LogAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analysis/LogAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;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,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EACH,WAAW,EACX,aAAa,EACb,aAAa,EACb,SAAS,EACT,UAAU,EACV,aAAa,EACb,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACH,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,cAAc,GACtB,MAAM,cAAc,CAAC;AAGtB,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AASlE;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,cAAc,CA2C1F"}
|
|
@@ -9,42 +9,53 @@
|
|
|
9
9
|
* - error-context.ts — Error context window builder
|
|
10
10
|
* - error-grouper.ts — Clusters similar errors
|
|
11
11
|
* - pattern-detector.ts — Identifies recurring message templates
|
|
12
|
-
* - stats.ts — Level distribution, error rate, spike detection
|
|
12
|
+
* - stats.ts — Level distribution, error rate, spike detection, histogram
|
|
13
|
+
* - filter.ts - Time, level, logger and text filters shared by every log surface
|
|
13
14
|
*/
|
|
14
15
|
// Re-export individual modules for direct use
|
|
15
16
|
export { parseRawLogs } from './parser.js';
|
|
16
17
|
export { buildErrorContexts } from './error-context.js';
|
|
17
18
|
export { groupErrors } from './error-grouper.js';
|
|
18
19
|
export { detectPatterns } from './pattern-detector.js';
|
|
19
|
-
export { calculateStats } from './stats.js';
|
|
20
|
-
export { templatize, isNoise, LEVEL_PRIORITY } from './
|
|
21
|
-
|
|
20
|
+
export { calculateStats, histogram, topCounts, BUCKETS } from './stats.js';
|
|
21
|
+
export { templatize, isNoise, LEVEL_PRIORITY } from './normalize.js';
|
|
22
|
+
export { buildFilter, filterEntries, searchEntries, entryText, clampLimit, MAX_LOG_LINES, } from './filter.js';
|
|
23
|
+
export { summarizeEntries, formatEntry, formatEntries, MAX_HISTOGRAM_ROWS, } from './summary.js';
|
|
22
24
|
import { parseRawLogs } from './parser.js';
|
|
23
25
|
import { buildErrorContexts } from './error-context.js';
|
|
24
26
|
import { groupErrors } from './error-grouper.js';
|
|
25
27
|
import { detectPatterns } from './pattern-detector.js';
|
|
26
28
|
import { calculateStats } from './stats.js';
|
|
29
|
+
import { buildFilter, levelPriority } from './filter.js';
|
|
30
|
+
import { LEVEL_PRIORITY } from './normalize.js';
|
|
27
31
|
/**
|
|
28
|
-
* Full analysis pipeline: parse →
|
|
32
|
+
* Full analysis pipeline: parse → filter → context → group → pattern → stats.
|
|
33
|
+
* The time window applies to everything. Level, logger and search select the entries
|
|
34
|
+
* that are counted and analyzed as errors; error context still comes from every entry
|
|
35
|
+
* in the window, so a filtered error keeps the lines that led up to it.
|
|
29
36
|
*/
|
|
30
37
|
export function analyzeLogs(rawText, options = {}) {
|
|
31
38
|
const totalLines = rawText.split('\n').length;
|
|
32
39
|
// 1. Parse and join multi-line entries
|
|
33
|
-
|
|
34
|
-
// 2.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
40
|
+
const parsed = parseRawLogs(rawText);
|
|
41
|
+
// 2. Time window
|
|
42
|
+
const startTime = options.startTime ?? (options.hoursBack ? Date.now() - options.hoursBack * 60 * 60 * 1000 : undefined);
|
|
43
|
+
const inWindow = buildFilter({ startTime, endTime: options.endTime });
|
|
44
|
+
const windowed = parsed.filter(inWindow);
|
|
45
|
+
// 3. Level, logger and search
|
|
46
|
+
const selected = buildFilter({
|
|
47
|
+
level: options.level,
|
|
48
|
+
logger: options.logger,
|
|
49
|
+
search: options.search,
|
|
50
|
+
regex: options.regex,
|
|
51
|
+
});
|
|
52
|
+
const entries = windowed.filter(selected);
|
|
53
|
+
// 4. Build error contexts over the whole window
|
|
54
|
+
const minErrorLevel = levelPriority(options.errorLevel ?? 'ERROR');
|
|
55
|
+
const errorContexts = buildErrorContexts(windowed, {
|
|
46
56
|
beforeCount: options.contextBefore,
|
|
47
57
|
afterCount: options.contextAfter,
|
|
58
|
+
isError: (e) => (LEVEL_PRIORITY[e.priority] ?? 0) >= minErrorLevel && selected(e),
|
|
48
59
|
});
|
|
49
60
|
// 5. Group errors
|
|
50
61
|
const errorGroups = groupErrors(errorContexts, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LogAnalyzer.js","sourceRoot":"","sources":["../../src/analysis/LogAnalyzer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"LogAnalyzer.js","sourceRoot":"","sources":["../../src/analysis/LogAnalyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,8 @@ export interface ErrorContextOptions {
|
|
|
11
11
|
afterCount?: number;
|
|
12
12
|
/** Time window in ms for fallback mode (default: 30000) */
|
|
13
13
|
timeWindowMs?: number;
|
|
14
|
+
/** Which entries count as errors (default: ERROR and FATAL) */
|
|
15
|
+
isError?: (entry: EnrichedLogEntry) => boolean;
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* Build error context for all ERROR entries.
|
|
@@ -1 +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;
|
|
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;IACtB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,OAAO,CAAC;CAClD;AAID;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,OAAO,GAAE,mBAAwB,GAAG,gBAAgB,EAAE,CAiDrH"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Builds before/after context windows for ERROR entries.
|
|
4
4
|
* Uses correlation-based context when available, time-window fallback otherwise.
|
|
5
5
|
*/
|
|
6
|
+
const isErrorLevel = (entry) => entry.priority === 'ERROR' || entry.priority === 'FATAL';
|
|
6
7
|
/**
|
|
7
8
|
* Build error context for all ERROR entries.
|
|
8
9
|
*/
|
|
@@ -10,7 +11,7 @@ export function buildErrorContexts(entries, options = {}) {
|
|
|
10
11
|
const beforeCount = options.beforeCount ?? 15;
|
|
11
12
|
const afterCount = options.afterCount ?? 10;
|
|
12
13
|
const timeWindowMs = options.timeWindowMs ?? 30000;
|
|
13
|
-
const errorEntries = entries.filter(
|
|
14
|
+
const errorEntries = entries.filter(options.isError ?? isErrorLevel);
|
|
14
15
|
const contexts = [];
|
|
15
16
|
// Build correlation index for fast lookup
|
|
16
17
|
const correlationIndex = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-context.js","sourceRoot":"","sources":["../../src/analysis/error-context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"error-context.js","sourceRoot":"","sources":["../../src/analysis/error-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"error-grouper.js","sourceRoot":"","sources":["../../src/analysis/error-grouper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAS5C;;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,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis - Filter
|
|
3
|
+
* One filter for every log surface: time window, minimum level, logger and text search.
|
|
4
|
+
* Search covers the whole entry (logger, thread, message, stack trace and JSON payload),
|
|
5
|
+
* so text on continuation lines is found on the entry it belongs to.
|
|
6
|
+
*/
|
|
7
|
+
import type { EnrichedLogEntry } from './types.js';
|
|
8
|
+
/** Hard cap on the lines a single search returns. */
|
|
9
|
+
export declare const MAX_LOG_LINES = 1000;
|
|
10
|
+
export interface LogFilter {
|
|
11
|
+
/** Inclusive start, epoch milliseconds */
|
|
12
|
+
startTime?: number;
|
|
13
|
+
/** Inclusive end, epoch milliseconds */
|
|
14
|
+
endTime?: number;
|
|
15
|
+
/** Minimum level: TRACE, DEBUG, INFO, WARN, ERROR or FATAL */
|
|
16
|
+
level?: string;
|
|
17
|
+
/** Case-insensitive substring of the logger name */
|
|
18
|
+
logger?: string;
|
|
19
|
+
/** Text to find anywhere in the entry */
|
|
20
|
+
search?: string;
|
|
21
|
+
/** Treat `search` as a case-insensitive regular expression */
|
|
22
|
+
regex?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface LogSearchOptions extends LogFilter {
|
|
25
|
+
/** Most entries to return, newest first (default 100, capped at MAX_LOG_LINES) */
|
|
26
|
+
limit?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface LogSearchResult {
|
|
29
|
+
/** Matches before `limit` was applied */
|
|
30
|
+
total: number;
|
|
31
|
+
/** Entries in this response */
|
|
32
|
+
returned: number;
|
|
33
|
+
truncated: boolean;
|
|
34
|
+
/** Newest first */
|
|
35
|
+
entries: EnrichedLogEntry[];
|
|
36
|
+
}
|
|
37
|
+
/** Validate a level name, returning its numeric priority. */
|
|
38
|
+
export declare function levelPriority(level: string): number;
|
|
39
|
+
/** Build the text matcher for a search term, or null when there is none. */
|
|
40
|
+
export declare function buildMatcher(search?: string, regex?: boolean): ((text: string) => boolean) | null;
|
|
41
|
+
/** The searchable text of an entry, in log line order. */
|
|
42
|
+
export declare function entryText(entry: EnrichedLogEntry): string;
|
|
43
|
+
/** Build a predicate for a filter. Validates the level and regex up front. */
|
|
44
|
+
export declare function buildFilter(filter: LogFilter): (entry: EnrichedLogEntry) => boolean;
|
|
45
|
+
/** Keep the entries that pass a filter, in their original order. */
|
|
46
|
+
export declare function filterEntries(entries: EnrichedLogEntry[], filter: LogFilter): EnrichedLogEntry[];
|
|
47
|
+
/** Clamp a requested line count to 1..MAX_LOG_LINES. */
|
|
48
|
+
export declare function clampLimit(limit: number | undefined, fallback?: number): number;
|
|
49
|
+
/**
|
|
50
|
+
* Filter entries and return the newest `limit` matches.
|
|
51
|
+
* `total` counts every match, so callers can tell when the result was cut.
|
|
52
|
+
*/
|
|
53
|
+
export declare function searchEntries(entries: EnrichedLogEntry[], options?: LogSearchOptions): LogSearchResult;
|
|
54
|
+
//# sourceMappingURL=filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/analysis/filter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGnD,qDAAqD;AACrD,eAAO,MAAM,aAAa,OAAO,CAAC;AAKlC,MAAM,WAAW,SAAS;IACtB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IAC/C,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC5B,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,mBAAmB;IACnB,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,IAAI,CAgBjG;AAED,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAazD;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,OAAO,CAcnF;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,MAAM,EAAE,SAAS,GAAG,gBAAgB,EAAE,CAGhG;AAED,wDAAwD;AACxD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,SAAM,GAAG,MAAM,CAG5E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,OAAO,GAAE,gBAAqB,GAAG,eAAe,CAO1G"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Analysis - Filter
|
|
3
|
+
* One filter for every log surface: time window, minimum level, logger and text search.
|
|
4
|
+
* Search covers the whole entry (logger, thread, message, stack trace and JSON payload),
|
|
5
|
+
* so text on continuation lines is found on the entry it belongs to.
|
|
6
|
+
*/
|
|
7
|
+
import { LEVEL_PRIORITY } from './normalize.js';
|
|
8
|
+
/** Hard cap on the lines a single search returns. */
|
|
9
|
+
export const MAX_LOG_LINES = 1000;
|
|
10
|
+
/** Longest regex pattern accepted for search. */
|
|
11
|
+
const MAX_PATTERN_LENGTH = 500;
|
|
12
|
+
/** Validate a level name, returning its numeric priority. */
|
|
13
|
+
export function levelPriority(level) {
|
|
14
|
+
const name = level.toUpperCase();
|
|
15
|
+
const priority = LEVEL_PRIORITY[name === 'WARNING' ? 'WARN' : name];
|
|
16
|
+
if (priority === undefined) {
|
|
17
|
+
throw new Error(`Unknown log level "${level}". Use one of ${Object.keys(LEVEL_PRIORITY).join(', ')}`);
|
|
18
|
+
}
|
|
19
|
+
return priority;
|
|
20
|
+
}
|
|
21
|
+
/** Build the text matcher for a search term, or null when there is none. */
|
|
22
|
+
export function buildMatcher(search, regex) {
|
|
23
|
+
if (!search)
|
|
24
|
+
return null;
|
|
25
|
+
if (regex) {
|
|
26
|
+
if (search.length > MAX_PATTERN_LENGTH) {
|
|
27
|
+
throw new Error(`Search regex is longer than ${MAX_PATTERN_LENGTH} characters`);
|
|
28
|
+
}
|
|
29
|
+
let pattern;
|
|
30
|
+
try {
|
|
31
|
+
pattern = new RegExp(search, 'i');
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
throw new Error(`Invalid search regex: ${error.message}`);
|
|
35
|
+
}
|
|
36
|
+
return (text) => pattern.test(text);
|
|
37
|
+
}
|
|
38
|
+
const needle = search.toLowerCase();
|
|
39
|
+
return (text) => text.toLowerCase().includes(needle);
|
|
40
|
+
}
|
|
41
|
+
/** The searchable text of an entry, in log line order. */
|
|
42
|
+
export function entryText(entry) {
|
|
43
|
+
const header = [
|
|
44
|
+
entry.loggerName,
|
|
45
|
+
entry.eventId ? `event:${entry.eventId}` : undefined,
|
|
46
|
+
entry.threadName !== undefined ? `${entry.threadName} -` : undefined,
|
|
47
|
+
entry.message,
|
|
48
|
+
]
|
|
49
|
+
.filter((part) => part !== undefined && part !== '')
|
|
50
|
+
.join(' ');
|
|
51
|
+
const parts = [header];
|
|
52
|
+
if (entry.stackTrace)
|
|
53
|
+
parts.push(entry.stackTrace);
|
|
54
|
+
if (entry.jsonPayload)
|
|
55
|
+
parts.push(JSON.stringify(entry.jsonPayload));
|
|
56
|
+
return parts.join('\n');
|
|
57
|
+
}
|
|
58
|
+
/** Build a predicate for a filter. Validates the level and regex up front. */
|
|
59
|
+
export function buildFilter(filter) {
|
|
60
|
+
const minLevel = filter.level ? levelPriority(filter.level) : undefined;
|
|
61
|
+
const logger = filter.logger?.toLowerCase();
|
|
62
|
+
const matches = buildMatcher(filter.search, filter.regex);
|
|
63
|
+
return (entry) => {
|
|
64
|
+
if (filter.startTime !== undefined && entry.timestamp < filter.startTime)
|
|
65
|
+
return false;
|
|
66
|
+
if (filter.endTime !== undefined && entry.timestamp > filter.endTime)
|
|
67
|
+
return false;
|
|
68
|
+
if (minLevel !== undefined && (LEVEL_PRIORITY[entry.priority] ?? 0) < minLevel)
|
|
69
|
+
return false;
|
|
70
|
+
if (logger && !(entry.loggerName ?? '').toLowerCase().includes(logger))
|
|
71
|
+
return false;
|
|
72
|
+
// The message alone first, so a regex anchored with ^ or $ means the message.
|
|
73
|
+
if (matches && !matches(entry.message ?? '') && !matches(entryText(entry)))
|
|
74
|
+
return false;
|
|
75
|
+
return true;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** Keep the entries that pass a filter, in their original order. */
|
|
79
|
+
export function filterEntries(entries, filter) {
|
|
80
|
+
const keep = buildFilter(filter);
|
|
81
|
+
return entries.filter(keep);
|
|
82
|
+
}
|
|
83
|
+
/** Clamp a requested line count to 1..MAX_LOG_LINES. */
|
|
84
|
+
export function clampLimit(limit, fallback = 100) {
|
|
85
|
+
const value = limit === undefined || !Number.isFinite(limit) ? fallback : Math.floor(limit);
|
|
86
|
+
return Math.min(Math.max(value, 1), MAX_LOG_LINES);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Filter entries and return the newest `limit` matches.
|
|
90
|
+
* `total` counts every match, so callers can tell when the result was cut.
|
|
91
|
+
*/
|
|
92
|
+
export function searchEntries(entries, options = {}) {
|
|
93
|
+
const limit = clampLimit(options.limit);
|
|
94
|
+
const matched = filterEntries(entries, options);
|
|
95
|
+
// Reverse, then a stable sort: entries that share a timestamp stay newest first.
|
|
96
|
+
const newestFirst = [...matched].reverse().sort((a, b) => b.timestamp - a.timestamp);
|
|
97
|
+
const page = newestFirst.slice(0, limit);
|
|
98
|
+
return { total: matched.length, returned: page.length, truncated: matched.length > page.length, entries: page };
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/analysis/filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/analysis/normalize.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAgBnD,+CAA+C;AAC/C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAOjD,CAAC;AAEF;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUlD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CASxD"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/** Variable-like tokens to replace with <*> in pattern detection */
|
|
6
6
|
const VARIABLE_PATTERNS = [
|
|
7
7
|
/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi, // UUIDs
|
|
8
|
-
/\b[a-zA-Z0-9]{15,18}\b/g, //
|
|
8
|
+
/\b[a-zA-Z0-9]{15,18}\b/g, // Opaque 15-18 character record IDs
|
|
9
9
|
/\b\d{4}-\d{2}-\d{2}T[\d:.]+Z?\b/g, // ISO timestamps
|
|
10
10
|
/\b\d+\.\d+\.\d+\.\d+\b/g, // IP addresses
|
|
11
11
|
/\b\d{5,}\b/g, // Long numbers (5+ digits)
|
|
@@ -52,4 +52,4 @@ export function isNoise(entry) {
|
|
|
52
52
|
}
|
|
53
53
|
return false;
|
|
54
54
|
}
|
|
55
|
-
//# sourceMappingURL=
|
|
55
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/analysis/normalize.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,oEAAoE;AACpE,MAAM,iBAAiB,GAAG;IACtB,oEAAoE,EAAE,QAAQ;IAC9E,yBAAyB,EAAE,oCAAoC;IAC/D,kCAAkC,EAAE,iBAAiB;IACrD,yBAAyB,EAAE,eAAe;IAC1C,aAAa,EAAE,2BAA2B;IAC1C,qBAAqB,EAAE,gBAAgB;IACvC,qBAAqB,EAAE,wCAAwC;CAClE,CAAC;AAEF,kCAAkC;AAClC,MAAM,qBAAqB,GAAG,iCAAiC,CAAC;AAEhE,+CAA+C;AAC/C,MAAM,CAAC,MAAM,cAAc,GAA2B;IAClD,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;CACX,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe;IACtC,IAAI,MAAM,GAAG,OAAO,CAAC;IACrB,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACtC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAClD,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACtB,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;IAC9C,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,KAAuB;IAC3C,IAAI,KAAK,CAAC,QAAQ,KAAK,OAAO,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;YAAE,OAAO,IAAI,CAAC;IACtF,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,KAAK,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAC9C,IAAI,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;IAC/D,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
|
|
@@ -1 +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;
|
|
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;AAuCnD;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAkFhE"}
|
package/dist/analysis/parser.js
CHANGED
|
@@ -3,16 +3,34 @@
|
|
|
3
3
|
* Parses raw CloudHub log text into enriched entries, joining multi-line blocks.
|
|
4
4
|
* Handles: JSON Logger blocks, stack traces, HTTP dumps, continuation lines.
|
|
5
5
|
*/
|
|
6
|
+
/** ISO timestamp, level and replica: the prefix every new entry starts with. */
|
|
7
|
+
const HEADER_PREFIX = String.raw `^(\d{4}-\d{2}-\d{2}T[\d:.]+(?:Z|[+-]\d{2}:?\d{2}))\s+(TRACE|DEBUG|INFO|WARN|ERROR|FATAL)\s+\[([^\]]*)\]`;
|
|
6
8
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
+
* Full Mule line: timestamp, level, instanceId, loggerName, optional eventId, thread, message.
|
|
10
|
+
* The first " - " separates the thread from the message.
|
|
9
11
|
*/
|
|
10
|
-
const LOG_LINE_REGEX =
|
|
12
|
+
const LOG_LINE_REGEX = new RegExp(HEADER_PREFIX + String.raw `\s+(\S+)\s+(?:event:(\S+)\s+)?(.+?)\s+-(?:\s(.*))?$`);
|
|
13
|
+
/** Any other line with the header prefix: the rest of the line is the message. */
|
|
14
|
+
const LOOSE_LINE_REGEX = new RegExp(HEADER_PREFIX + String.raw `\s*(.*)$`);
|
|
15
|
+
/** Parse the first line of an entry, or return null for a continuation line. */
|
|
16
|
+
function parseHeader(line) {
|
|
17
|
+
const full = line.match(LOG_LINE_REGEX);
|
|
18
|
+
if (full) {
|
|
19
|
+
const [, timestamp, level, instanceId, loggerName, eventId, threadName, message] = full;
|
|
20
|
+
return { timestamp, level, instanceId, loggerName, eventId, threadName, message: message ?? '' };
|
|
21
|
+
}
|
|
22
|
+
const loose = line.match(LOOSE_LINE_REGEX);
|
|
23
|
+
if (loose) {
|
|
24
|
+
const [, timestamp, level, instanceId, message] = loose;
|
|
25
|
+
return { timestamp, level, instanceId, message };
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
11
29
|
/**
|
|
12
30
|
* Parse raw log text into enriched entries, joining multi-line blocks.
|
|
13
31
|
*/
|
|
14
32
|
export function parseRawLogs(rawText) {
|
|
15
|
-
const lines = rawText.split(
|
|
33
|
+
const lines = rawText.split(/\r?\n/);
|
|
16
34
|
const entries = [];
|
|
17
35
|
let current = null;
|
|
18
36
|
let jsonBuffer = null;
|
|
@@ -20,8 +38,8 @@ export function parseRawLogs(rawText) {
|
|
|
20
38
|
for (const line of lines) {
|
|
21
39
|
if (!line.trim())
|
|
22
40
|
continue;
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
41
|
+
const header = parseHeader(line);
|
|
42
|
+
if (header) {
|
|
25
43
|
// Flush any pending entry
|
|
26
44
|
if (current) {
|
|
27
45
|
if (jsonBuffer) {
|
|
@@ -31,15 +49,14 @@ export function parseRawLogs(rawText) {
|
|
|
31
49
|
}
|
|
32
50
|
entries.push(current);
|
|
33
51
|
}
|
|
34
|
-
const [, timestamp, level, instanceId, loggerName, eventId, threadOrMessage, messageAfterDash] = match;
|
|
35
52
|
current = {
|
|
36
|
-
timestamp: new Date(timestamp).getTime(),
|
|
37
|
-
priority: level,
|
|
38
|
-
instanceId,
|
|
39
|
-
loggerName,
|
|
40
|
-
eventId,
|
|
41
|
-
threadName:
|
|
42
|
-
message:
|
|
53
|
+
timestamp: new Date(header.timestamp.replace(/([+-]\d{2})(\d{2})$/, '$1:$2')).getTime(),
|
|
54
|
+
priority: header.level,
|
|
55
|
+
instanceId: header.instanceId,
|
|
56
|
+
loggerName: header.loggerName,
|
|
57
|
+
eventId: header.eventId,
|
|
58
|
+
threadName: header.threadName,
|
|
59
|
+
message: header.message,
|
|
43
60
|
};
|
|
44
61
|
// Check if this is a JSON Logger entry starting with "{"
|
|
45
62
|
if (current.message !== undefined) {
|
|
@@ -96,6 +113,17 @@ export function parseRawLogs(rawText) {
|
|
|
96
113
|
}
|
|
97
114
|
return entries;
|
|
98
115
|
}
|
|
116
|
+
/** Logger payloads name the stack trace field differently (stackTrace, stacktrace, stack_trace, …). */
|
|
117
|
+
const STACK_TRACE_KEY = /^stack_?trace/i;
|
|
118
|
+
function findStackTrace(payload) {
|
|
119
|
+
if (!payload || typeof payload !== 'object')
|
|
120
|
+
return undefined;
|
|
121
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
122
|
+
if (STACK_TRACE_KEY.test(key) && typeof value === 'string' && value.trim())
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
99
127
|
/**
|
|
100
128
|
* Parse accumulated JSON lines and enrich the log entry with structured fields.
|
|
101
129
|
*/
|
|
@@ -112,9 +140,9 @@ function finalizeJsonEntry(entry, jsonLines) {
|
|
|
112
140
|
if (parsed.message && (!entry.message || entry.message.trim() === '')) {
|
|
113
141
|
entry.message = parsed.message;
|
|
114
142
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
143
|
+
const stackTrace = findStackTrace(parsed) ?? findStackTrace(parsed.content);
|
|
144
|
+
if (stackTrace)
|
|
145
|
+
entry.stackTrace = stackTrace;
|
|
118
146
|
}
|
|
119
147
|
catch {
|
|
120
148
|
entry.message = (entry.message || '') + '\n' + jsonText;
|