Skip to content

Commit 689e1d5

Browse files
committed
debug mode default for dev
1 parent e6f3d32 commit 689e1d5

10 files changed

Lines changed: 49 additions & 30 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ import { ArgusAgent } from 'argus-apm';
9393
const { ArgusAgent } = require('argus-apm');
9494

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

9999
---
@@ -160,7 +160,7 @@ import { ArgusAgent } from 'argus-apm';
160160
// import { ArgusAgent } from './packages/agent/src/index.ts';
161161

162162
const agent = await ArgusAgent.createProfile({
163-
environment: 'prod', // or 'dev' | 'test'
163+
environment: 'dev', // 'dev' prints all events to console automatically; silence with 'prod' or ARGUS_DEBUG=false
164164
appType: ['web', 'db'],
165165
}).start();
166166
// SIGTERM / SIGINT → flush telemetry → process.exit is wired automatically
@@ -763,7 +763,7 @@ runWithContext(agent.createContext('WORKER', '/process-job'), async () => {
763763
});
764764
```
765765

766-
> **Source mode (contributors):** replace `'argus'` with `'./packages/agent/src/index.ts'` and run with `node --experimental-strip-types` on Node 22.6+.
766+
> **Source mode (contributors):** replace `'argus-apm'` with `'./packages/agent/src/index.ts'` and run with `node --experimental-strip-types` on Node 22.6+.
767767
768768
---
769769

packages/agent/src/argus-agent.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ export class ArgusAgent extends EventEmitter {
152152
private running = false;
153153
// Listeners added by useConsoleLogger — kept so they can be removed on stop().
154154
private debugListeners: DebugListener[] = [];
155+
/** Set by buildAgentProfile when environment === 'dev'. */
156+
isDevMode = false;
155157

156158
// Private constructor — use ArgusAgent.create()
157159
private constructor() {
@@ -471,7 +473,11 @@ export class ArgusAgent extends EventEmitter {
471473
public async start(): Promise<this> {
472474
if (this.globallyDisabled || this.running) return this;
473475

474-
if (process.env.ARGUS_DEBUG === "true") {
476+
const debugEnv = process.env.ARGUS_DEBUG;
477+
const debugEnabled = debugEnv !== undefined
478+
? debugEnv !== "false" && debugEnv !== "0"
479+
: this.isDevMode;
480+
if (debugEnabled) {
475481
this.useConsoleLogger();
476482
}
477483

@@ -840,7 +846,7 @@ export class ArgusAgent extends EventEmitter {
840846
* @param level `'warn'` — anomalies/crashes/errors only (default)
841847
* `'verbose'` — also logs every query and HTTP request
842848
*/
843-
private useConsoleLogger(prefix = "[DiagAgent]", level: "warn" | "verbose" = "verbose"): this {
849+
private useConsoleLogger(prefix = "[Argus]", level: "warn" | "verbose" = "verbose"): this {
844850
const registered = installConsoleLogger(this, prefix, level);
845851
this.debugListeners.push(...registered);
846852
return this;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { detectAppTypes } from "../profiling/app-type-detector.ts";
2020
*/
2121
export function buildAgentProfile(agent: ArgusAgent, config: AgentProfileConfig): void {
2222
const env = config.environment ?? "prod";
23+
agent.isDevMode = env === "dev";
2324

2425
// Resolve app types — 'auto' triggers package.json scanning
2526
let appTypes: AppType[];

packages/agent/src/profiling/runtime-monitor.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ export class RuntimeMonitor extends EventEmitter {
212212
const now = Date.now();
213213

214214
if (now - this.lastCpuProfileTime < this.options.cpuProfileCooldownMs!) {
215-
// Fallback to simple emission if in cooldown
216215
this.emit("anomaly", {
217216
type: "event-loop-lag",
218217
lagMs,
@@ -225,28 +224,31 @@ export class RuntimeMonitor extends EventEmitter {
225224
this.isProfiling = true;
226225
this.lastCpuProfileTime = now;
227226

227+
let profileDataPath: string | undefined;
228228
try {
229229
if (!this.inspectorSession) {
230230
this.inspectorSession = new Session();
231231
this.inspectorSession.connect();
232232
}
233233

234234
const profileData = await this.captureCpuProfile();
235-
if (!profileData) return; // Session detached or failed
236-
const tempPath = join(tmpdir(), `cpu-profile-${Date.now()}.cpuprofile`);
237-
await writeFile(tempPath, JSON.stringify(profileData), "utf-8");
238-
239-
this.emit("anomaly", {
240-
type: "event-loop-lag",
241-
lagMs,
242-
profileDataPath: tempPath,
243-
timestamp: Date.now(),
244-
} satisfies ProfilerEvent);
235+
if (profileData) {
236+
const tempPath = join(tmpdir(), `cpu-profile-${Date.now()}.cpuprofile`);
237+
await writeFile(tempPath, JSON.stringify(profileData), "utf-8");
238+
profileDataPath = tempPath;
239+
}
245240
} catch (err) {
246241
this.emit("error", err);
247242
} finally {
248243
this.isProfiling = false;
249244
}
245+
246+
this.emit("anomaly", {
247+
type: "event-loop-lag",
248+
lagMs,
249+
profileDataPath,
250+
timestamp: Date.now(),
251+
} satisfies ProfilerEvent);
250252
}
251253

252254
/** Test helper — directly fire the heap-oom-risk logic without waiting for a real threshold. */

packages/agent/tests/profiling/runtime-monitor.test.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,33 +61,41 @@ describe("RuntimeMonitor", () => {
6161
});
6262

6363
it("should detect event loop lag and capture CPU profile", async () => {
64-
monitor.start();
64+
// Use a dedicated monitor with a very low threshold (5ms) and fast check interval
65+
// so detection is reliable regardless of host load or timer resolution.
66+
const lagMonitor = new RuntimeMonitor({
67+
checkIntervalMs: 50,
68+
eventLoopThresholdMs: 5,
69+
cpuProfileDurationMs: 50,
70+
cpuProfileCooldownMs: 1000,
71+
});
72+
lagMonitor.start();
6573

6674
const p = new Promise<ProfilerEvent[]>((resolve) => {
6775
const handler = (event: ProfilerEvent) => {
6876
if (event.type === "event-loop-lag") {
69-
monitor.off("anomaly", handler);
77+
lagMonitor.off("anomaly", handler);
7078
resolve([event]);
7179
}
7280
};
73-
monitor.on("anomaly", handler);
81+
lagMonitor.on("anomaly", handler);
7482
});
7583

7684
await sleep(10); // allow baseline to settle
7785

78-
// Create an artificial event loop block synchronously
86+
// Block the event loop long enough to guarantee detection on any machine.
7987
const start = Date.now();
80-
while (Date.now() - start < 150) {
88+
while (Date.now() - start < 300) {
8189
// busy wait
8290
}
8391

8492
const timeoutPromise = new Promise<never>((_, reject) =>
85-
setTimeout(() => reject(new Error("Timeout waiting for lag event")), 1000),
93+
setTimeout(() => reject(new Error("Timeout waiting for lag event")), 3000),
8694
);
8795
const [event] = await Promise.race([p, timeoutPromise]);
8896

8997
assert.strictEqual(event.type, "event-loop-lag");
90-
assert.ok(event.lagMs! >= 20);
98+
assert.ok(event.lagMs! >= 5);
9199
// profileDataPath may be undefined if the inspector session didn't start in time (test-runner load).
92100
// When it is present it must be a string path.
93101
if (event.profileDataPath !== undefined) {
@@ -97,5 +105,7 @@ describe("RuntimeMonitor", () => {
97105
"profileDataPath should be a valid string path",
98106
);
99107
}
108+
109+
lagMonitor.stop();
100110
});
101111
});

quotes-demo-app/bin/www

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Module dependencies.
55
*/
66

7-
// ⚡ DiagnosticAgent — must be first, before Express loads
7+
// ⚡ ArgusAgent — must be first, before Express loads
88
require('../diagnostic');
99

1010
var app = require('../app');

quotes-demo-app/diagnostic.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
const path = require('path');
4-
const { DiagnosticAgent } = require(path.resolve(__dirname, '../packages/agent/dist/cjs/index.cjs'));
4+
const { ArgusAgent } = require(path.resolve(__dirname, '../packages/agent/dist/cjs/index.cjs'));
55

66
// ── colour helpers (no deps) ──────────────────────────────────────────────────
77
const c = {
@@ -12,7 +12,7 @@ const c = {
1212
const stamp = () => new Date().toISOString().slice(11, 23); // HH:MM:SS.mmm
1313
const tag = (colour, label) => `${colour}${c.bold}[${label}]${c.reset}`;
1414

15-
const agent = DiagnosticAgent.createProfile({
15+
const agent = ArgusAgent.createProfile({
1616
environment: process.env.NODE_ENV === 'production' ? 'prod' : 'dev',
1717
appType: ['web', 'db'],
1818
workspaceDir: path.resolve(__dirname, '..'),

quotes-demo-app/routes/debug.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
/**
4-
* Debug routes — intentionally trigger every DiagnosticAgent monitoring feature.
4+
* Debug routes — intentionally trigger every ArgusAgent monitoring feature.
55
* Never use patterns like these in production code.
66
*/
77

quotes-demo-app/services/db.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ const dbChannel = diagnostics_channel.channel('db.query.execution');
99

1010
/**
1111
* Query the database using the pool.
12-
* Also publishes to diagnostics_channel so the DiagnosticAgent can trace it.
12+
* Also publishes to diagnostics_channel so the ArgusAgent can trace it.
1313
*/
1414
async function query(sql, params) {
1515
const start = performance.now();
1616
const {rows} = await pool.query(sql, params);
1717
const durationMs = performance.now() - start;
1818

19-
// Broadcast to DiagnosticAgent
19+
// Broadcast to ArgusAgent
2020
if (dbChannel.hasSubscribers) {
2121
dbChannel.publish({ query: sql, durationMs });
2222
}

quotes-demo-app/simulate.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
const http = require('http');
1010

11-
// ── 1. Boot DiagnosticAgent (must be first) ───────────────────────────────────
11+
// ── 1. Boot ArgusAgent (must be first) ───────────────────────────────────────
1212
const agent = require('./diagnostic');
1313

1414
// ── 2. Boot Express app ───────────────────────────────────────────────────────

0 commit comments

Comments
 (0)