Skip to content

Commit e6e282a

Browse files
betegonclaude
andcommitted
feat(dsn): add verbose debug logging for DSN discovery flow
Surfaces DSN detection details when running any command with --verbose, following the existing log.debug() + withTag() pattern. Logs project root detection, cache hits/misses, scan stats, each found DSN with source, and org/project resolution results. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 73573b9 commit e6e282a

File tree

5 files changed

+68
-0
lines changed

5 files changed

+68
-0
lines changed

src/lib/dsn/code-scanner.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,10 @@ function scanDirectory(
686686

687687
const { files, dirMtimes } = collectResult;
688688

689+
log.debug(
690+
`Code scan: collected ${files.length} files from ${Object.keys(dirMtimes).length} directories`
691+
);
692+
689693
span.setAttribute("dsn.files_collected", files.length);
690694

691695
if (files.length === 0) {
@@ -699,6 +703,10 @@ function scanDirectory(
699703
stopOnFirst
700704
);
701705

706+
log.debug(
707+
`Code scan: scanned ${filesScanned} files, found ${results.size} DSN(s)`
708+
);
709+
702710
span.setAttributes({
703711
"dsn.files_scanned": filesScanned,
704712
"dsn.dsns_found": results.size,

src/lib/dsn/detector.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
detectFromEnvFiles,
3636
extractDsnFromEnvContent,
3737
} from "./env-file.js";
38+
import { logger } from "../logger.js";
3839
import { createDetectedDsn, createDsnFingerprint, parseDsn } from "./parser.js";
3940
import { findProjectRoot } from "./project-root.js";
4041
import type {
@@ -44,6 +45,8 @@ import type {
4445
DsnSource,
4546
} from "./types.js";
4647

48+
const log = logger.withTag("dsn-detect");
49+
4750
/**
4851
* Detect DSN with project root detection and caching support.
4952
*
@@ -86,6 +89,7 @@ export async function detectDsn(cwd: string): Promise<DetectedDsn | null> {
8689
}
8790

8891
// Cache hit! Return with resolved info if available
92+
log.debug(`DSN cache hit for ${projectRoot}`);
8993
return {
9094
...verified,
9195
resolved: cached.resolved,
@@ -98,6 +102,9 @@ export async function detectDsn(cwd: string): Promise<DetectedDsn | null> {
98102
const detected = await fullScanFirst(projectRoot);
99103

100104
if (detected) {
105+
log.debug(
106+
`DSN detected: ${detected.raw} from ${getDsnSourceDescription(detected)}`
107+
);
101108
// Cache for next time (without resolved info yet)
102109
setCachedDsn(projectRoot, {
103110
dsn: detected.raw,
@@ -106,6 +113,8 @@ export async function detectDsn(cwd: string): Promise<DetectedDsn | null> {
106113
source: detected.source,
107114
sourcePath: detected.sourcePath,
108115
});
116+
} else {
117+
log.debug(`No DSN found after full scan of ${projectRoot}`);
109118
}
110119

111120
return detected;
@@ -144,11 +153,16 @@ export async function detectAllDsns(cwd: string): Promise<DsnDetectionResult> {
144153
});
145154
}
146155

156+
log.debug(`DSN detection starting from project root: ${projectRoot}`);
157+
147158
// 2. Try cached detection result
148159
const cachedDetection = await getCachedDetection(projectRoot);
149160

150161
if (cachedDetection) {
151162
// Cache hit! Return cached result
163+
log.debug(
164+
`DSN detection cache hit: ${cachedDetection.allDsns.length} DSN(s) cached`
165+
);
152166
return {
153167
primary: cachedDetection.allDsns[0] ?? null,
154168
all: cachedDetection.allDsns,
@@ -182,6 +196,9 @@ export async function detectAllDsns(cwd: string): Promise<DsnDetectionResult> {
182196
}
183197
Object.assign(allSourceMtimes, codeMtimes);
184198
Object.assign(allDirMtimes, codeDirMtimes);
199+
if (codeDsns.length > 0) {
200+
log.debug(`Found ${codeDsns.length} DSN(s) in source code`);
201+
}
185202

186203
// 3b. Check all .env files from project root (includes monorepo packages/apps)
187204
const { dsns: envFileDsns, sourceMtimes: envMtimes } =
@@ -190,11 +207,15 @@ export async function detectAllDsns(cwd: string): Promise<DsnDetectionResult> {
190207
addDsn(dsn);
191208
}
192209
Object.assign(allSourceMtimes, envMtimes);
210+
if (envFileDsns.length > 0) {
211+
log.debug(`Found ${envFileDsns.length} DSN(s) in .env files`);
212+
}
193213

194214
// 3c. Check env var (lowest priority) - no mtime for env vars
195215
const envDsn = detectFromEnv();
196216
if (envDsn) {
197217
addDsn(envDsn);
218+
log.debug("Found DSN in SENTRY_DSN environment variable");
198219
}
199220

200221
// 4. Compute fingerprint and cache result
@@ -222,6 +243,18 @@ export async function detectAllDsns(cwd: string): Promise<DsnDetectionResult> {
222243
// Multiple DSNs is valid in monorepos (different packages/apps)
223244
const hasMultiple = allDsns.length > 1;
224245

246+
if (allDsns.length > 0) {
247+
log.debug(`DSN detection complete: ${allDsns.length} total DSN(s) found`);
248+
for (const dsn of allDsns) {
249+
const isPrimary = dsn === allDsns[0] ? " [primary]" : "";
250+
log.debug(
251+
` ${dsn.raw}${getDsnSourceDescription(dsn)}${isPrimary}`
252+
);
253+
}
254+
} else {
255+
log.debug("DSN detection complete: no DSNs found");
256+
}
257+
225258
return {
226259
primary: allDsns[0] ?? null,
227260
all: allDsns,

src/lib/dsn/env-file.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010

1111
import { opendir } from "node:fs/promises";
1212
import { join } from "node:path";
13+
import { logger } from "../logger.js";
1314
import { withTracingSpan } from "../telemetry.js";
1415
import { createDetectedDsn } from "./parser.js";
1516
import { scanSpecificFiles } from "./scanner.js";
1617
import type { DetectedDsn } from "./types.js";
1718
import { MONOREPO_ROOTS } from "./types.js";
1819

20+
const log = logger.withTag("dsn-env-file");
21+
1922
/**
2023
* Result of scanning env files, including mtimes for caching.
2124
*/
@@ -156,6 +159,9 @@ export async function detectFromAllEnvFiles(
156159
});
157160
allDsns.push(...rootDsns);
158161
Object.assign(allMtimes, rootMtimes);
162+
if (rootDsns.length > 0) {
163+
log.debug(`Found ${rootDsns.length} DSN(s) in root .env files`);
164+
}
159165

160166
// 2. Check monorepo package directories
161167
const {
@@ -165,6 +171,11 @@ export async function detectFromAllEnvFiles(
165171
} = await detectFromMonorepoEnvFiles(cwd);
166172
allDsns.push(...monorepoDsns);
167173
Object.assign(allMtimes, monorepoMtimes);
174+
if (packagesScanned > 0) {
175+
log.debug(
176+
`Scanned ${packagesScanned} monorepo packages, found ${monorepoDsns.length} DSN(s) in package .env files`
177+
);
178+
}
168179

169180
// Root checks ENV_FILES.length names; each monorepo package also checks ENV_FILES.length
170181
const filesChecked = ENV_FILES.length * (1 + packagesScanned);

src/lib/dsn/project-root.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@
1616
import { opendir, stat } from "node:fs/promises";
1717
import { homedir } from "node:os";
1818
import { dirname, join, resolve } from "node:path";
19+
import { logger } from "../logger.js";
1920
import { anyTrue } from "../promises.js";
2021
import { withFsSpan, withTracingSpan } from "../telemetry.js";
2122
import { ENV_FILES, extractDsnFromEnvContent } from "./env-file.js";
2223
import { handleFileError } from "./fs-utils.js";
2324
import { createDetectedDsn } from "./parser.js";
2425
import type { DetectedDsn } from "./types.js";
2526

27+
const log = logger.withTag("dsn-project-root");
28+
2629
/** Why a directory was chosen as project root */
2730
export type ProjectRootReason =
2831
| "env_dsn" // Found .env with SENTRY_DSN
@@ -554,6 +557,10 @@ export function findProjectRoot(startDir: string): Promise<ProjectRootResult> {
554557

555558
const result = await walkUpDirectories(resolvedStart, stopBoundary);
556559

560+
log.debug(
561+
`Project root: ${result.projectRoot} (reason: ${result.reason})`
562+
);
563+
557564
span.setAttributes({
558565
"dsn.found": result.foundDsn !== undefined,
559566
"dsn.reason": result.reason,

src/lib/resolve-target.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,15 @@ async function resolveDetectedDsns(
926926
// Count DSNs that couldn't be resolved (API errors, permissions, etc.)
927927
const unresolvedCount = resolvedTargets.filter((t) => t === null).length;
928928

929+
for (const t of targets) {
930+
log.debug(`Resolved: ${t.org}/${t.project} (from DSN)`);
931+
}
932+
if (unresolvedCount > 0) {
933+
log.debug(
934+
`DSN resolution: ${unresolvedCount} DSN(s) could not be resolved`
935+
);
936+
}
937+
929938
if (targets.length === 0) {
930939
return {
931940
targets: [],

0 commit comments

Comments
 (0)