Skip to content

Commit 68ed4bb

Browse files
committed
refactor: rename DiagnosticAgent → ArgusAgent across entire codebase
- Rename src/diagnostic-agent.ts → src/argus-agent.ts - Rename tests/diagnostic-agent*.test.ts → tests/argus-agent*.test.ts - Replace all DiagnosticAgent class/type references with ArgusAgent - Update all import paths from diagnostic-agent to argus-agent - Update Symbol.for("diagnostic-agent.patched") → "argus-agent.patched" - Update README, CHANGELOG, CONTRIBUTING, DEMO.md Aligns the public API with the package name (argus). All 508 tests pass, 0 TS errors, 0 ESLint warnings, Prettier clean.
1 parent 23fe21a commit 68ed4bb

22 files changed

Lines changed: 148 additions & 151 deletions

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2626
- **Architecture — God object split**: Extracted three cohesive modules from the 1 109-line
2727
`diagnostic-agent.ts`:
2828
- `src/internal/profile-factory.ts``buildAgentProfile()` contains all preset-resolution
29-
and builder-wiring logic for `DiagnosticAgent.createProfile()`.
29+
and builder-wiring logic for `ArgusAgent.createProfile()`.
3030
- `src/internal/query-handler.ts``createQueryHandler()` factory produces the per-query
3131
processing closure (adaptive sampling → query analysis → slow-query check → aggregation).
3232
- `src/internal/console-logger.ts``installConsoleLogger()` registers formatted console
@@ -44,7 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4444
### Added
4545

4646
#### Core agent
47-
- `DiagnosticAgent` fluent builder with two entry points: `create()` (manual) and
47+
- `ArgusAgent` fluent builder with two entry points: `create()` (manual) and
4848
`createProfile()` (preset-based).
4949
- Zero-overhead global kill-switch via `DIAGNOSTIC_AGENT_ENABLED=false``.start()` becomes
5050
a no-op with no timer, subscription, or memory overhead.
@@ -54,7 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5454
- Three environment presets: `prod`, `dev`, `test`.
5555
- Three app-type presets: `web`, `db`, `worker` (composable as an array).
5656
- `'auto'` mode — scans `package.json` dependencies and infers the correct preset.
57-
- `DiagnosticAgent.detectAppTypes()` standalone detector.
57+
- `ArgusAgent.detectAppTypes()` standalone detector.
5858

5959
#### Instrumentation
6060
- `node:diagnostics_channel`-based query tracing for 14 DB drivers: `pg`, `mysql2`, `mssql`,

CONTRIBUTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pnpm lint:fix # auto-fix what's fixable
5656
The agent is structured in five layers:
5757

5858
```
59-
DiagnosticAgent (fluent builder + event bus)
59+
ArgusAgent (fluent builder + event bus)
6060
6161
├── Profiling — runtime observation, crash interception, source maps
6262
│ RuntimeMonitor event-loop lag, heap growth (accumulated model)
@@ -110,7 +110,7 @@ DB driver interception uses `node:diagnostics_channel` (the official Node.js obs
110110

111111
### CrashGuard flush before process.exit
112112

113-
When `DiagnosticAgent.wireGuards()` creates `CrashGuard`, it passes `() => this.stop()` as the `beforeExit` callback. On an `uncaughtException`:
113+
When `ArgusAgent.wireGuards()` creates `CrashGuard`, it passes `() => this.stop()` as the `beforeExit` callback. On an `uncaughtException`:
114114
1. The crash event is emitted synchronously (in-process listeners get it).
115115
2. `beforeExit()` is awaited (max 2 s) so the OTLP exporter can flush.
116116
3. `process.exit(1)` runs only after the flush or the deadline, whichever comes first.
@@ -175,7 +175,7 @@ This section tracks planned monitoring capabilities — what's already shipped,
175175
| Cache hit-rate monitoring | `CacheMonitor` | Sliding-window hit rate, fires `cache-degraded` |
176176
| Query plan analysis (EXPLAIN) | `ExplainAnalyzer` | User-supplied executor, per-pattern cooldown |
177177
| DNS resolution monitoring | `DnsMonitor` | `dns.lookup` intercept, `slow-dns` events |
178-
| Adaptive sampling | `AdaptiveSampler` | Token-bucket per category, wired in `DiagnosticAgent` |
178+
| Adaptive sampling | `AdaptiveSampler` | Token-bucket per category, wired in `ArgusAgent` |
179179
| OTLP-compatible export (no mTLS) | `OTLPCompatibleExporter` | Plain http/https, optional bearer token |
180180

181181
---

README.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ This package ships a **dual build**: ESM and CommonJS. Node.js picks the right f
8787

8888
```js
8989
// ✅ ESM project (type:module or .mjs)
90-
import { DiagnosticAgent } from 'argus';
90+
import { ArgusAgent } from 'argus';
9191

9292
// ✅ CommonJS project — require() works directly
93-
const { DiagnosticAgent } = require('argus');
93+
const { ArgusAgent } = require('argus');
9494

9595
// ✅ CommonJS project — dynamic import also works
96-
const { DiagnosticAgent } = await import('argus');
96+
const { ArgusAgent } = await import('argus');
9797
```
9898

9999
---
@@ -109,7 +109,7 @@ npm install argus
109109
Then import from the compiled entry point:
110110

111111
```typescript
112-
import { DiagnosticAgent } from 'argus';
112+
import { ArgusAgent } from 'argus';
113113
```
114114

115115
### Building from source (Node ≥ 22.6, contributors only)
@@ -152,12 +152,12 @@ dist/
152152

153153
```typescript
154154
// Compiled npm package
155-
import { DiagnosticAgent } from 'argus';
155+
import { ArgusAgent } from 'argus';
156156

157157
// Or if running source directly (Node 22.6+)
158-
// import { DiagnosticAgent } from './packages/agent/src/index.ts';
158+
// import { ArgusAgent } from './packages/agent/src/index.ts';
159159

160-
const agent = await DiagnosticAgent.createProfile({
160+
const agent = await ArgusAgent.createProfile({
161161
environment: 'prod', // or 'dev' | 'test'
162162
appType: ['web', 'db'],
163163
}).start();
@@ -195,7 +195,7 @@ See [`quotes-demo-app/README.md`](quotes-demo-app/README.md) for the full setup
195195
`createProfile` returns a pre-configured builder instance wired for your environment and app type. Call `.start()` to initialize all subsystems.
196196

197197
```typescript
198-
const agent = await DiagnosticAgent.createProfile({
198+
const agent = await ArgusAgent.createProfile({
199199
environment: 'prod', // 'dev' | 'test' | 'prod'
200200
appType: ['web', 'db'], // single string or array — modules are unioned
201201
enabled: true, // overridden by DIAGNOSTIC_AGENT_ENABLED env-var
@@ -227,21 +227,21 @@ Each `.with*()` call is **idempotent** — combining types never double-register
227227

228228
```typescript
229229
// Express API + background job runner
230-
DiagnosticAgent.createProfile({ appType: ['web', 'worker'] });
230+
ArgusAgent.createProfile({ appType: ['web', 'worker'] });
231231

232232
// Worker that queries databases directly
233-
DiagnosticAgent.createProfile({ appType: ['db', 'worker'] });
233+
ArgusAgent.createProfile({ appType: ['db', 'worker'] });
234234

235235
// Monolith — full coverage
236-
DiagnosticAgent.createProfile({ appType: ['web', 'db', 'worker'] });
236+
ArgusAgent.createProfile({ appType: ['web', 'db', 'worker'] });
237237
```
238238

239239
### Auto-Detection
240240

241241
Leave `appType` unset (or set it to `'auto'`) and the agent will scan your `package.json` dependencies to infer the correct profile:
242242

243243
```typescript
244-
const agent = await DiagnosticAgent.createProfile({
244+
const agent = await ArgusAgent.createProfile({
245245
environment: 'prod',
246246
// appType: 'auto' is the default
247247
}).start();
@@ -252,7 +252,7 @@ const agent = await DiagnosticAgent.createProfile({
252252
You can also call the detector standalone:
253253

254254
```typescript
255-
const result = DiagnosticAgent.detectAppTypes('./my-service');
255+
const result = ArgusAgent.detectAppTypes('./my-service');
256256
// { types: ['web', 'db'], matches: { web: ['express', 'cors'], db: ['pg', 'ioredis'], worker: [] } }
257257
```
258258

@@ -274,10 +274,10 @@ const result = DiagnosticAgent.detectAppTypes('./my-service');
274274
For maximum control, compose the agent manually using the fluent builder:
275275

276276
```typescript
277-
import { DiagnosticAgent } from 'argus';
277+
import { ArgusAgent } from 'argus';
278278
import fs from 'node:fs';
279279

280-
const agent = await DiagnosticAgent.create()
280+
const agent = await ArgusAgent.create()
281281
.withSourceMaps('./dist') // Source-map resolution for stack traces
282282
.withRuntimeMonitor({ eventLoopThresholdMs: 50 }) // Event loop lag + memory leak detection
283283
.withInstrumentation({ autoPatching: true }) // 16 DB drivers via diagnostics_channel
@@ -468,7 +468,7 @@ Requires `.withSourceMaps()`.
468468

469469
## Events Reference
470470

471-
The agent is an `EventEmitter`. All events are emitted on the `DiagnosticAgent` instance:
471+
The agent is an `EventEmitter`. All events are emitted on the `ArgusAgent` instance:
472472

473473
| Event | Payload | When |
474474
|---|---|---|
@@ -527,7 +527,7 @@ agent.on('pool-exhaustion', (event) => {
527527
```
528528

529529
> [!NOTE]
530-
> `DiagnosticAgent` calls `setMaxListeners(0)` internally — you can attach as many listeners as needed without triggering Node's memory leak warning.
530+
> `ArgusAgent` calls `setMaxListeners(0)` internally — you can attach as many listeners as needed without triggering Node's memory leak warning.
531531
532532
---
533533

@@ -557,8 +557,8 @@ All thresholds can be overridden without code changes, making the agent CI/CD an
557557

558558
| Method | Prod Safe? | Resource Impact | Description |
559559
|---|---|---|---|
560-
| `DiagnosticAgent.createProfile(config)` | ✅ Yes | N/A | Pre-configured instance from env/app presets |
561-
| `DiagnosticAgent.create()` | ✅ Yes | N/A | Unconfigured fluent builder |
560+
| `ArgusAgent.createProfile(config)` | ✅ Yes | N/A | Pre-configured instance from env/app presets |
561+
| `ArgusAgent.create()` | ✅ Yes | N/A | Unconfigured fluent builder |
562562
| `.withSourceMaps(dir?)` | ✅ Yes | Very Low | Source-map resolution for minified stack traces |
563563
| `.withRuntimeMonitor(opts?)` | ✅ Yes | Low | Event loop lag + memory leak detection |
564564
| `.withCrashGuard()` | ✅ Yes | Very Low | Intercepts `uncaughtException`; emits event for `unhandledRejection` |
@@ -617,7 +617,7 @@ Telemetry is exported over **mTLS** (Mutual TLS) — both client and server cert
617617

618618
```
619619
┌──────────────────────────────────────────────────────────────────┐
620-
DiagnosticAgent │ ← Fluent builder / event bus
620+
ArgusAgent │ ← Fluent builder / event bus
621621
├──────────────────┬─────────────────────────┬─────────────────────┤
622622
│ Profiling │ Instrumentation │ Analysis │
623623
│ ──────────────── │ ───────────────────── │ ───────────────── │
@@ -800,7 +800,7 @@ docker compose -f docker-compose.jaeger.yml up -d
800800
Then point the agent at it:
801801

802802
```typescript
803-
const agent = await DiagnosticAgent.createProfile({ environment: 'dev', appType: ['web', 'db'] })
803+
const agent = await ArgusAgent.createProfile({ environment: 'dev', appType: ['web', 'db'] })
804804
.withExporter({ endpointUrl: 'http://localhost:4318/v1/traces' }) // no TLS needed locally
805805
.start();
806806
```
Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ import { createQueryHandler } from "./internal/query-handler.ts";
6060
import { installConsoleLogger, type DebugListener } from "./internal/console-logger.ts";
6161

6262
// WeakMap-based private storage for license claims — avoids exposing internal field on agent
63-
const licenseClaims = new WeakMap<DiagnosticAgent, LicenseClaims>();
63+
const licenseClaims = new WeakMap<ArgusAgent, LicenseClaims>();
6464

6565
export function shouldExport(eventType: string, claims: LicenseClaims | null): boolean {
6666
if (!claims) return false; // free mode: local EventEmitter only, no OTLP export
@@ -92,7 +92,7 @@ export interface AgentProfileConfig {
9292
*
9393
* @example
9494
* ```ts
95-
* const agent = await DiagnosticAgent.create()
95+
* const agent = await ArgusAgent.create()
9696
* .withSourceMaps('./dist')
9797
* .withRuntimeMonitor({ eventLoopThresholdMs: 50 })
9898
* .withInstrumentation()
@@ -103,7 +103,7 @@ export interface AgentProfileConfig {
103103
* agent.stop();
104104
* ```
105105
*/
106-
export class DiagnosticAgent extends EventEmitter {
106+
export class ArgusAgent extends EventEmitter {
107107
// ── configuration captured by the builder ──
108108
private globallyDisabled = false;
109109
private sourceMapDir: string | null = null;
@@ -153,7 +153,7 @@ export class DiagnosticAgent extends EventEmitter {
153153
// Listeners added by useConsoleLogger — kept so they can be removed on stop().
154154
private debugListeners: DebugListener[] = [];
155155

156-
// Private constructor — use DiagnosticAgent.create()
156+
// Private constructor — use ArgusAgent.create()
157157
private constructor() {
158158
super();
159159
// High-frequency events (query, http, fs, log) may have many listeners
@@ -164,8 +164,8 @@ export class DiagnosticAgent extends EventEmitter {
164164
/**
165165
* Entry point — returns a fresh builder instance.
166166
*/
167-
public static create(): DiagnosticAgent {
168-
return new DiagnosticAgent();
167+
public static create(): ArgusAgent {
168+
return new ArgusAgent();
169169
}
170170

171171
/**
@@ -179,13 +179,13 @@ export class DiagnosticAgent extends EventEmitter {
179179
}
180180

181181
/**
182-
* Generates a preconfigured DiagnosticAgent using highly optimized presets based on environment and application types.
182+
* Generates a preconfigured ArgusAgent using highly optimized presets based on environment and application types.
183183
* Includes an `enabled` flag to return a true zero-overhead NoOp agent.
184184
*
185185
* Set `appType` to `'auto'` to auto-detect from `package.json` dependencies.
186186
*/
187-
public static createProfile(config: AgentProfileConfig): DiagnosticAgent {
188-
const agent = new DiagnosticAgent();
187+
public static createProfile(config: AgentProfileConfig): ArgusAgent {
188+
const agent = new ArgusAgent();
189189

190190
// Globally kill-switch the agent; .start() and .stop() will become 0-overhead.
191191
// Environment variables take precedence over the config object.
@@ -500,27 +500,24 @@ export class DiagnosticAgent extends EventEmitter {
500500
if (checkClockIntegrity(claims.tier, Date.now()) === "rollback") {
501501
this.emit(
502502
"error",
503-
new Error("DiagnosticAgent: system clock anomaly detected — running in free mode"),
503+
new Error("ArgusAgent: system clock anomaly detected — running in free mode"),
504504
);
505505
} else {
506506
licenseClaims.set(this, claims);
507507
this.emit(
508508
"info",
509-
`DiagnosticAgent: tier=${claims.tier}, exp=${new Date(claims.exp * 1000).toISOString()}`,
509+
`ArgusAgent: tier=${claims.tier}, exp=${new Date(claims.exp * 1000).toISOString()}`,
510510
);
511511
}
512512
} catch (err) {
513513
if ((err as Error).message === "EXPIRED") {
514514
writeExpirySignal("Renew at: https://argus.dev/billing");
515515
this.emit(
516516
"info",
517-
"DiagnosticAgent: license expired — running in free mode. Renew at: https://argus.dev/billing",
517+
"ArgusAgent: license expired — running in free mode. Renew at: https://argus.dev/billing",
518518
);
519519
} else {
520-
this.emit(
521-
"error",
522-
new Error(`DiagnosticAgent: invalid license — ${(err as Error).message}`),
523-
);
520+
this.emit("error", new Error(`ArgusAgent: invalid license — ${(err as Error).message}`));
524521
}
525522
}
526523
}

packages/agent/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,4 @@ export * from "./licensing/clock-guard.ts";
5151
export * from "./licensing/expiry-signal.ts";
5252

5353
// Top-level builder
54-
export * from "./diagnostic-agent.ts";
54+
export * from "./argus-agent.ts";

packages/agent/src/instrumentation/drivers/patch-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export interface PatchRecord {
4949

5050
export const activePatches: PatchRecord[] = [];
5151

52-
export const PATCHED_SYMBOL = Symbol.for("diagnostic-agent.patched");
52+
export const PATCHED_SYMBOL = Symbol.for("argus-agent.patched");
5353

5454
export function isAlreadyPatched(target: AnyTarget, methodName: string): boolean {
5555
return (target[methodName] as Record<symbol, unknown>)[PATCHED_SYMBOL] === true;

packages/agent/src/internal/console-logger.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
2-
* Console debug logger for DiagnosticAgent.
2+
* Console debug logger for ArgusAgent.
33
*
4-
* Extracted from DiagnosticAgent to keep the main class focused on lifecycle.
4+
* Extracted from ArgusAgent to keep the main class focused on lifecycle.
55
* When DIAGNOSTIC_DEBUG=true the agent calls installConsoleLogger() once during
66
* start() — all registered listeners are returned so the agent can remove them
77
* on stop() without leaking event subscriptions.
@@ -19,7 +19,7 @@ export type DebugListener = [string, (...args: unknown[]) => void];
1919
* Registers coloured console output for every agent event and returns the
2020
* registered listener pairs so the caller can remove them on shutdown.
2121
*
22-
* @param emitter The DiagnosticAgent instance (typed as EventEmitter to avoid circular dep).
22+
* @param emitter The ArgusAgent instance (typed as EventEmitter to avoid circular dep).
2323
* @param prefix Log line prefix — default `"[DiagAgent]"`.
2424
* @param level `"warn"` — anomalies/crashes/errors only.
2525
* `"verbose"` — also logs every query and HTTP request.

packages/agent/src/internal/profile-factory.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
/**
2-
* Profile factory — pure configuration logic for DiagnosticAgent.createProfile().
2+
* Profile factory — pure configuration logic for ArgusAgent.createProfile().
33
*
4-
* Kept separate from DiagnosticAgent to keep the main class focused on lifecycle
4+
* Kept separate from ArgusAgent to keep the main class focused on lifecycle
55
* and public API, not preset decision-making.
66
*/
77

8-
import type { DiagnosticAgent, AgentProfileConfig, AppType } from "../diagnostic-agent.ts";
8+
import type { ArgusAgent, AgentProfileConfig, AppType } from "../argus-agent.ts";
99
import { detectAppTypes } from "../profiling/app-type-detector.ts";
1010

1111
/**
1212
* Applies profile-based configuration to an already-constructed (but not yet started)
13-
* `DiagnosticAgent` instance. Calls only the agent's public builder methods.
13+
* `ArgusAgent` instance. Calls only the agent's public builder methods.
1414
*
1515
* Separated from the static `createProfile()` factory so the decision logic can be
1616
* tested and reasoned about independently of the class lifecycle.
1717
*
18-
* @param agent Fresh `DiagnosticAgent` instance (pre-disabled check done by caller).
18+
* @param agent Fresh `ArgusAgent` instance (pre-disabled check done by caller).
1919
* @param config Profile configuration from the caller.
2020
*/
21-
export function buildAgentProfile(agent: DiagnosticAgent, config: AgentProfileConfig): void {
21+
export function buildAgentProfile(agent: ArgusAgent, config: AgentProfileConfig): void {
2222
const env = config.environment ?? "prod";
2323

2424
// Resolve app types — 'auto' triggers package.json scanning
@@ -38,7 +38,7 @@ export function buildAgentProfile(agent: DiagnosticAgent, config: AgentProfileCo
3838
setImmediate(() => {
3939
agent.emit(
4040
"info",
41-
"DiagnosticAgent: auto-detection found no recognized app type in package.json. " +
41+
"ArgusAgent: auto-detection found no recognized app type in package.json. " +
4242
'Pass appType explicitly ("web" | "db" | "worker") to enable app-specific monitoring.',
4343
);
4444
});

packages/agent/src/internal/query-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Query event handler factory.
33
*
4-
* Extracts the dense per-query processing logic out of DiagnosticAgent so that
4+
* Extracts the dense per-query processing logic out of ArgusAgent so that
55
* wireInstrumentationEngine() becomes a lean wiring step, not a policy file.
66
*
77
* The handler is constructed once per agent start() and registered on the engine's

packages/agent/src/licensing/expiry-signal.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const SIGNAL_FILENAME = "diagnostic_agent_EXPIRED.txt";
1313
* Final fallback: writes to process.stderr (cannot be silenced without redirecting stderr).
1414
*/
1515
export function writeExpirySignal(message: string): void {
16-
const content = `[DiagnosticAgent] License expired — ${new Date().toISOString()}\n${message}\n`;
16+
const content = `[ArgusAgent] License expired — ${new Date().toISOString()}\n${message}\n`;
1717

1818
const candidates = [
1919
join(process.cwd(), SIGNAL_FILENAME),
@@ -31,5 +31,5 @@ export function writeExpirySignal(message: string): void {
3131
}
3232

3333
// All file paths failed — stderr is the final fallback
34-
process.stderr.write(`[DiagnosticAgent] EXPIRED: ${content}`);
34+
process.stderr.write(`[ArgusAgent] EXPIRED: ${content}`);
3535
}

0 commit comments

Comments
 (0)