brakit 0.9.0 → 0.9.1
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/dist/api.d.ts +2 -0
- package/dist/api.js +10 -4
- package/dist/bin/brakit.js +156 -23
- package/dist/dashboard-client.global.js +30 -30
- package/dist/dashboard.html +30 -30
- package/dist/mcp/server.js +1 -1
- package/dist/runtime/index.js +178 -67
- package/package.json +1 -1
package/dist/runtime/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
// src/constants/config.ts
|
|
18
|
-
var MAX_REQUEST_ENTRIES, DEFAULT_MAX_BODY_CAPTURE, DEFAULT_API_LIMIT, MAX_TELEMETRY_ENTRIES, MAX_TAB_NAME_LENGTH, MAX_INGEST_BYTES, TERMINAL_TRUNCATE_LENGTH, SENSITIVE_MASK_MIN_LENGTH, SENSITIVE_MASK_VISIBLE_CHARS, MAX_JSON_BODY_BYTES, ANALYSIS_DEBOUNCE_MS, ISSUE_ID_HASH_LENGTH, ISSUES_DATA_VERSION, SENSITIVE_MASK_PLACEHOLDER, PROJECT_HASH_LENGTH, SECRET_SCAN_ARRAY_LIMIT, PII_SCAN_ARRAY_LIMIT, MIN_SECRET_VALUE_LENGTH, FULL_RECORD_MIN_FIELDS, LIST_PII_MIN_ITEMS, MAX_API_LIMIT, MAX_OBJECT_SCAN_DEPTH, MAX_UNIQUE_ENDPOINTS, MAX_ACCUMULATOR_ENTRIES, ISSUE_PRUNE_TTL_MS, FLOW_GAP_MS, SLOW_REQUEST_THRESHOLD_MS, MIN_POLLING_SEQUENCE, ENDPOINT_TRUNCATE_LENGTH, N1_QUERY_THRESHOLD, ERROR_RATE_THRESHOLD_PCT, MIN_REQUESTS_FOR_INSIGHT, HIGH_QUERY_COUNT_PER_REQ, CROSS_ENDPOINT_MIN_ENDPOINTS, CROSS_ENDPOINT_PCT, CROSS_ENDPOINT_MIN_OCCURRENCES, REDUNDANT_QUERY_MIN_COUNT, LARGE_RESPONSE_BYTES, HIGH_ROW_COUNT, OVERFETCH_MIN_REQUESTS, OVERFETCH_MIN_FIELDS, OVERFETCH_MIN_INTERNAL_IDS, OVERFETCH_NULL_RATIO, REGRESSION_PCT_THRESHOLD, REGRESSION_MIN_INCREASE_MS, REGRESSION_MIN_REQUESTS, QUERY_COUNT_REGRESSION_RATIO, OVERFETCH_MANY_FIELDS, OVERFETCH_UNWRAP_MIN_SIZE, MAX_DUPLICATE_INSIGHTS, INSIGHT_WINDOW_PER_ENDPOINT, CLEAN_HITS_FOR_RESOLUTION, STALE_ISSUE_TTL_MS, STRICT_MODE_MAX_GAP_MS, BASELINE_MIN_SESSIONS, BASELINE_MIN_REQUESTS_PER_SESSION, BASELINE_PENDING_POINTS_MIN, METRICS_DIR, METRICS_FILE, PORT_FILE, ISSUES_FILE, METRICS_FLUSH_INTERVAL_MS, METRICS_MAX_SESSIONS, METRICS_MAX_DATA_POINTS, ISSUES_FLUSH_INTERVAL_MS, SSE_HEARTBEAT_INTERVAL_MS, NOISE_HOSTS, NOISE_PATH_PATTERNS, VALID_ISSUE_STATES, VALID_ISSUE_CATEGORIES, VALID_AI_FIX_STATUSES;
|
|
18
|
+
var MAX_REQUEST_ENTRIES, DEFAULT_MAX_BODY_CAPTURE, DEFAULT_API_LIMIT, MAX_TELEMETRY_ENTRIES, MAX_TAB_NAME_LENGTH, MAX_INGEST_BYTES, TERMINAL_TRUNCATE_LENGTH, SENSITIVE_MASK_MIN_LENGTH, SENSITIVE_MASK_VISIBLE_CHARS, MAX_JSON_BODY_BYTES, ANALYSIS_DEBOUNCE_MS, ISSUE_ID_HASH_LENGTH, ISSUES_DATA_VERSION, SENSITIVE_MASK_PLACEHOLDER, PROJECT_HASH_LENGTH, SECRET_SCAN_ARRAY_LIMIT, PII_SCAN_ARRAY_LIMIT, MIN_SECRET_VALUE_LENGTH, FULL_RECORD_MIN_FIELDS, LIST_PII_MIN_ITEMS, MAX_API_LIMIT, MAX_OBJECT_SCAN_DEPTH, MAX_UNIQUE_ENDPOINTS, MAX_ACCUMULATOR_ENTRIES, ISSUE_PRUNE_TTL_MS, FLOW_GAP_MS, SLOW_REQUEST_THRESHOLD_MS, MIN_POLLING_SEQUENCE, ENDPOINT_TRUNCATE_LENGTH, N1_QUERY_THRESHOLD, ERROR_RATE_THRESHOLD_PCT, MIN_REQUESTS_FOR_INSIGHT, HIGH_QUERY_COUNT_PER_REQ, CROSS_ENDPOINT_MIN_ENDPOINTS, CROSS_ENDPOINT_PCT, CROSS_ENDPOINT_MIN_OCCURRENCES, REDUNDANT_QUERY_MIN_COUNT, LARGE_RESPONSE_BYTES, HIGH_ROW_COUNT, OVERFETCH_MIN_REQUESTS, OVERFETCH_MIN_FIELDS, OVERFETCH_MIN_INTERNAL_IDS, OVERFETCH_NULL_RATIO, REGRESSION_PCT_THRESHOLD, REGRESSION_MIN_INCREASE_MS, REGRESSION_MIN_REQUESTS, QUERY_COUNT_REGRESSION_RATIO, OVERFETCH_MANY_FIELDS, OVERFETCH_UNWRAP_MIN_SIZE, MAX_DUPLICATE_INSIGHTS, INSIGHT_WINDOW_PER_ENDPOINT, CLEAN_HITS_FOR_RESOLUTION, STALE_ISSUE_TTL_MS, STRICT_MODE_MAX_GAP_MS, BASELINE_MIN_SESSIONS, BASELINE_MIN_REQUESTS_PER_SESSION, BASELINE_PENDING_POINTS_MIN, METRICS_DIR, METRICS_FILE, PORT_FILE, ISSUES_FILE, METRICS_FLUSH_INTERVAL_MS, METRICS_MAX_SESSIONS, METRICS_MAX_DATA_POINTS, ISSUES_FLUSH_INTERVAL_MS, SSE_HEARTBEAT_INTERVAL_MS, NOISE_HOSTS, NOISE_PATH_PATTERNS, VALID_ISSUE_STATES, VALID_ISSUE_CATEGORIES, VALID_AI_FIX_STATUSES, TELEMETRY_EVENT_SETUP_COMPLETED, TELEMETRY_EVENT_FIRST_REQUEST, TELEMETRY_EVENT_DASHBOARD_VIEWED, TELEMETRY_EVENT_SESSION, EXIT_REASON_CLEAN, EXIT_REASON_SIGINT, EXIT_REASON_SIGTERM, DETAIL_PREVIEW_LENGTH, KNOWN_DEPENDENCY_NAMES;
|
|
19
19
|
var init_config = __esm({
|
|
20
20
|
"src/constants/config.ts"() {
|
|
21
21
|
"use strict";
|
|
@@ -90,6 +90,30 @@ var init_config = __esm({
|
|
|
90
90
|
VALID_ISSUE_STATES = /* @__PURE__ */ new Set(["open", "fixing", "resolved", "stale", "regressed"]);
|
|
91
91
|
VALID_ISSUE_CATEGORIES = /* @__PURE__ */ new Set(["security", "performance", "reliability"]);
|
|
92
92
|
VALID_AI_FIX_STATUSES = /* @__PURE__ */ new Set(["fixed", "wont_fix"]);
|
|
93
|
+
TELEMETRY_EVENT_SETUP_COMPLETED = "setup_completed";
|
|
94
|
+
TELEMETRY_EVENT_FIRST_REQUEST = "first_request";
|
|
95
|
+
TELEMETRY_EVENT_DASHBOARD_VIEWED = "dashboard_viewed";
|
|
96
|
+
TELEMETRY_EVENT_SESSION = "session";
|
|
97
|
+
EXIT_REASON_CLEAN = "clean";
|
|
98
|
+
EXIT_REASON_SIGINT = "sigint";
|
|
99
|
+
EXIT_REASON_SIGTERM = "sigterm";
|
|
100
|
+
DETAIL_PREVIEW_LENGTH = 120;
|
|
101
|
+
KNOWN_DEPENDENCY_NAMES = [
|
|
102
|
+
"next",
|
|
103
|
+
"@remix-run/dev",
|
|
104
|
+
"nuxt",
|
|
105
|
+
"vite",
|
|
106
|
+
"astro",
|
|
107
|
+
"express",
|
|
108
|
+
"fastify",
|
|
109
|
+
"hono",
|
|
110
|
+
"koa",
|
|
111
|
+
"nest",
|
|
112
|
+
"prisma",
|
|
113
|
+
"drizzle-orm",
|
|
114
|
+
"typeorm",
|
|
115
|
+
"sequelize"
|
|
116
|
+
];
|
|
93
117
|
}
|
|
94
118
|
});
|
|
95
119
|
|
|
@@ -422,6 +446,7 @@ var init_adapter_registry = __esm({
|
|
|
422
446
|
constructor() {
|
|
423
447
|
this.adapters = [];
|
|
424
448
|
this.active = [];
|
|
449
|
+
this.failed = [];
|
|
425
450
|
}
|
|
426
451
|
register(adapter) {
|
|
427
452
|
this.adapters.push(adapter);
|
|
@@ -434,6 +459,7 @@ var init_adapter_registry = __esm({
|
|
|
434
459
|
this.active.push(adapter);
|
|
435
460
|
}
|
|
436
461
|
} catch {
|
|
462
|
+
this.failed.push(adapter.name);
|
|
437
463
|
}
|
|
438
464
|
}
|
|
439
465
|
}
|
|
@@ -449,6 +475,9 @@ var init_adapter_registry = __esm({
|
|
|
449
475
|
getActive() {
|
|
450
476
|
return this.active;
|
|
451
477
|
}
|
|
478
|
+
getFailed() {
|
|
479
|
+
return this.failed;
|
|
480
|
+
}
|
|
452
481
|
};
|
|
453
482
|
}
|
|
454
483
|
});
|
|
@@ -2837,7 +2866,7 @@ var init_data_rules = __esm({
|
|
|
2837
2866
|
title: "Stack Trace Leaked to Client",
|
|
2838
2867
|
desc: `${ep} \u2014 response exposes internal stack trace`,
|
|
2839
2868
|
hint: this.hint,
|
|
2840
|
-
detail: firstLine ? `Stack trace: ${firstLine.slice(0,
|
|
2869
|
+
detail: firstLine ? `Stack trace: ${firstLine.slice(0, DETAIL_PREVIEW_LENGTH)}` : void 0,
|
|
2841
2870
|
endpoint: ep,
|
|
2842
2871
|
count: 1
|
|
2843
2872
|
}
|
|
@@ -3253,7 +3282,7 @@ var init_query_rules = __esm({
|
|
|
3253
3282
|
title: "N+1 Query Pattern",
|
|
3254
3283
|
desc: `${endpoint} runs ${shapeGroup.count}x ${info.op} ${info.table} with different params in a single request`,
|
|
3255
3284
|
hint: "This typically happens when fetching related data in a loop. Use a batch query, JOIN, or include/eager-load to fetch all records at once.",
|
|
3256
|
-
detail: `${shapeGroup.count} queries with ${shapeGroup.distinctSql.size} distinct param variations. Example: ${[...shapeGroup.distinctSql][0]?.slice(0,
|
|
3285
|
+
detail: `${shapeGroup.count} queries with ${shapeGroup.distinctSql.size} distinct param variations. Example: ${[...shapeGroup.distinctSql][0]?.slice(0, DETAIL_PREVIEW_LENGTH) ?? info.op + " " + info.table}`
|
|
3257
3286
|
});
|
|
3258
3287
|
}
|
|
3259
3288
|
}
|
|
@@ -3292,7 +3321,7 @@ var init_query_rules = __esm({
|
|
|
3292
3321
|
title: "Redundant Query",
|
|
3293
3322
|
desc: `${label} runs ${entry.count}x with identical params in ${endpoint}.`,
|
|
3294
3323
|
hint: "The exact same query with identical parameters runs multiple times in one request. Cache the first result or lift the query to a shared function.",
|
|
3295
|
-
detail: entry.first.sql ? `Query: ${entry.first.sql.slice(0,
|
|
3324
|
+
detail: entry.first.sql ? `Query: ${entry.first.sql.slice(0, DETAIL_PREVIEW_LENGTH)}` : void 0
|
|
3296
3325
|
});
|
|
3297
3326
|
}
|
|
3298
3327
|
}
|
|
@@ -3927,7 +3956,7 @@ var init_src = __esm({
|
|
|
3927
3956
|
init_engine();
|
|
3928
3957
|
init_insights2();
|
|
3929
3958
|
init_insights();
|
|
3930
|
-
VERSION = "0.9.
|
|
3959
|
+
VERSION = "0.9.1";
|
|
3931
3960
|
}
|
|
3932
3961
|
});
|
|
3933
3962
|
|
|
@@ -4817,7 +4846,7 @@ var init_page = __esm({
|
|
|
4817
4846
|
});
|
|
4818
4847
|
|
|
4819
4848
|
// src/telemetry/config.ts
|
|
4820
|
-
import { homedir as homedir2 } from "os";
|
|
4849
|
+
import { homedir as homedir2, platform } from "os";
|
|
4821
4850
|
import { join as join3 } from "path";
|
|
4822
4851
|
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
4823
4852
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
@@ -4832,11 +4861,17 @@ function readConfig() {
|
|
|
4832
4861
|
function writeConfig(config) {
|
|
4833
4862
|
try {
|
|
4834
4863
|
if (!existsSync5(CONFIG_DIR))
|
|
4835
|
-
mkdirSync3(CONFIG_DIR, { recursive: true, mode: DIR_MODE_OWNER_ONLY });
|
|
4836
|
-
writeFileSync3(
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4864
|
+
mkdirSync3(CONFIG_DIR, { recursive: true, ...IS_WINDOWS ? {} : { mode: DIR_MODE_OWNER_ONLY } });
|
|
4865
|
+
writeFileSync3(
|
|
4866
|
+
CONFIG_PATH,
|
|
4867
|
+
JSON.stringify(config, null, 2) + "\n",
|
|
4868
|
+
IS_WINDOWS ? {} : { mode: FILE_MODE_OWNER_ONLY }
|
|
4869
|
+
);
|
|
4870
|
+
} catch (err) {
|
|
4871
|
+
if (process.env.BRAKIT_DEBUG) {
|
|
4872
|
+
process.stderr.write(`[brakit] config write failed: ${err?.message ?? err}
|
|
4873
|
+
`);
|
|
4874
|
+
}
|
|
4840
4875
|
}
|
|
4841
4876
|
}
|
|
4842
4877
|
function getOrCreateConfig() {
|
|
@@ -4858,11 +4893,12 @@ function isTelemetryEnabled() {
|
|
|
4858
4893
|
cachedEnabled = readConfig()?.telemetry ?? true;
|
|
4859
4894
|
return cachedEnabled;
|
|
4860
4895
|
}
|
|
4861
|
-
var CONFIG_DIR, CONFIG_PATH, cachedEnabled;
|
|
4896
|
+
var IS_WINDOWS, CONFIG_DIR, CONFIG_PATH, cachedEnabled;
|
|
4862
4897
|
var init_config2 = __esm({
|
|
4863
4898
|
"src/telemetry/config.ts"() {
|
|
4864
4899
|
"use strict";
|
|
4865
4900
|
init_features();
|
|
4901
|
+
IS_WINDOWS = platform() === "win32";
|
|
4866
4902
|
CONFIG_DIR = join3(homedir2(), ".brakit");
|
|
4867
4903
|
CONFIG_PATH = join3(CONFIG_DIR, "config.json");
|
|
4868
4904
|
cachedEnabled = null;
|
|
@@ -4870,9 +4906,49 @@ var init_config2 = __esm({
|
|
|
4870
4906
|
});
|
|
4871
4907
|
|
|
4872
4908
|
// src/telemetry/index.ts
|
|
4873
|
-
import { platform, release, arch } from "os";
|
|
4909
|
+
import { platform as platform2, release, arch } from "os";
|
|
4874
4910
|
import { spawn } from "child_process";
|
|
4911
|
+
function commonProperties() {
|
|
4912
|
+
return {
|
|
4913
|
+
brakit_version: VERSION,
|
|
4914
|
+
node_version: process.version,
|
|
4915
|
+
os: `${platform2()}-${release()}`,
|
|
4916
|
+
arch: arch(),
|
|
4917
|
+
$lib: "brakit",
|
|
4918
|
+
$process_person_profile: false,
|
|
4919
|
+
$geoip_disable: true
|
|
4920
|
+
};
|
|
4921
|
+
}
|
|
4922
|
+
function sendToPosthog(event, properties) {
|
|
4923
|
+
if (!isTelemetryEnabled()) return;
|
|
4924
|
+
const config = getOrCreateConfig();
|
|
4925
|
+
const payload = {
|
|
4926
|
+
api_key: POSTHOG_KEY,
|
|
4927
|
+
event,
|
|
4928
|
+
distinct_id: config.anonymousId,
|
|
4929
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4930
|
+
properties: { ...commonProperties(), ...properties }
|
|
4931
|
+
};
|
|
4932
|
+
try {
|
|
4933
|
+
const body = JSON.stringify(payload);
|
|
4934
|
+
const url = `${POSTHOG_HOST}${POSTHOG_CAPTURE_PATH}`;
|
|
4935
|
+
const child = spawn(
|
|
4936
|
+
process.execPath,
|
|
4937
|
+
[
|
|
4938
|
+
"-e",
|
|
4939
|
+
`fetch(${JSON.stringify(url)},{method:"POST",headers:{"content-type":"application/json"},body:${JSON.stringify(body)},signal:AbortSignal.timeout(${POSTHOG_REQUEST_TIMEOUT_MS})}).catch(()=>{})`
|
|
4940
|
+
],
|
|
4941
|
+
{ detached: true, stdio: "ignore" }
|
|
4942
|
+
);
|
|
4943
|
+
child.unref();
|
|
4944
|
+
} catch {
|
|
4945
|
+
}
|
|
4946
|
+
}
|
|
4947
|
+
function trackEvent(event, properties) {
|
|
4948
|
+
sendToPosthog(event, { sdk: "node", ...properties });
|
|
4949
|
+
}
|
|
4875
4950
|
function initSession(framework, packageManager, isCustomCommand, adapters) {
|
|
4951
|
+
getOrCreateConfig();
|
|
4876
4952
|
session.startTime = Date.now();
|
|
4877
4953
|
session.framework = framework;
|
|
4878
4954
|
session.packageManager = packageManager;
|
|
@@ -4892,7 +4968,25 @@ function recordTabViewed(tab) {
|
|
|
4892
4968
|
session.tabsViewed.add(tab);
|
|
4893
4969
|
}
|
|
4894
4970
|
function recordDashboardOpened() {
|
|
4971
|
+
if (session.dashboardOpened) return;
|
|
4895
4972
|
session.dashboardOpened = true;
|
|
4973
|
+
session.dashboardOpenedAt = Date.now();
|
|
4974
|
+
trackEvent(TELEMETRY_EVENT_DASHBOARD_VIEWED, {
|
|
4975
|
+
time_to_dashboard_ms: session.startTime > 0 ? Date.now() - session.startTime : null,
|
|
4976
|
+
request_count_at_open: session.requestCount
|
|
4977
|
+
});
|
|
4978
|
+
}
|
|
4979
|
+
function recordSetupCompleted(info) {
|
|
4980
|
+
session.frameworkCandidates = info.frameworkCandidates;
|
|
4981
|
+
session.adaptersFailed = info.adaptersFailed;
|
|
4982
|
+
session.setupDurationMs = info.setupDurationMs;
|
|
4983
|
+
session.setupSucceeded = true;
|
|
4984
|
+
}
|
|
4985
|
+
function recordFirstRequest() {
|
|
4986
|
+
if (!session.firstRequestAt) session.firstRequestAt = Date.now();
|
|
4987
|
+
}
|
|
4988
|
+
function recordExitReason(reason) {
|
|
4989
|
+
if (session.exitReason === "unknown") session.exitReason = reason;
|
|
4896
4990
|
}
|
|
4897
4991
|
function speedBucket(ms) {
|
|
4898
4992
|
if (ms === 0) return "none";
|
|
@@ -4906,7 +5000,6 @@ function speedBucket(ms) {
|
|
|
4906
5000
|
function trackSession(services) {
|
|
4907
5001
|
if (!isTelemetryEnabled()) return;
|
|
4908
5002
|
const isFirstSession = readConfig() === null;
|
|
4909
|
-
const config = getOrCreateConfig();
|
|
4910
5003
|
const metricsStore = services.metricsStore;
|
|
4911
5004
|
const analysisEngine = services.analysisEngine;
|
|
4912
5005
|
const live = metricsStore.getLiveEndpoints();
|
|
@@ -4920,55 +5013,39 @@ function trackSession(services) {
|
|
|
4920
5013
|
totalDuration += ep.summary.p95Ms * ep.summary.totalRequests;
|
|
4921
5014
|
if (ep.summary.p95Ms > slowestP95) slowestP95 = ep.summary.p95Ms;
|
|
4922
5015
|
}
|
|
4923
|
-
const
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
}
|
|
4957
|
-
};
|
|
4958
|
-
try {
|
|
4959
|
-
const body = JSON.stringify(payload);
|
|
4960
|
-
const url = `${POSTHOG_HOST}${POSTHOG_CAPTURE_PATH}`;
|
|
4961
|
-
const child = spawn(
|
|
4962
|
-
process.execPath,
|
|
4963
|
-
[
|
|
4964
|
-
"-e",
|
|
4965
|
-
`fetch(${JSON.stringify(url)},{method:"POST",headers:{"content-type":"application/json"},body:${JSON.stringify(body)},signal:AbortSignal.timeout(${POSTHOG_REQUEST_TIMEOUT_MS})}).catch(()=>{})`
|
|
4966
|
-
],
|
|
4967
|
-
{ detached: true, stdio: "ignore" }
|
|
4968
|
-
);
|
|
4969
|
-
child.unref();
|
|
4970
|
-
} catch {
|
|
4971
|
-
}
|
|
5016
|
+
const now = Date.now();
|
|
5017
|
+
sendToPosthog(TELEMETRY_EVENT_SESSION, {
|
|
5018
|
+
sdk: "node",
|
|
5019
|
+
framework: session.framework,
|
|
5020
|
+
package_manager: session.packageManager,
|
|
5021
|
+
is_custom_command: session.isCustomCommand,
|
|
5022
|
+
first_session: isFirstSession,
|
|
5023
|
+
adapters_detected: session.adapters,
|
|
5024
|
+
request_count: session.requestCount,
|
|
5025
|
+
error_count: services.errorStore.getAll().length,
|
|
5026
|
+
query_count: services.queryStore.getAll().length,
|
|
5027
|
+
fetch_count: services.fetchStore.getAll().length,
|
|
5028
|
+
insight_count: insights.length,
|
|
5029
|
+
finding_count: findings.length,
|
|
5030
|
+
insight_types: [...session.insightTypes],
|
|
5031
|
+
rules_triggered: [...session.rulesTriggered],
|
|
5032
|
+
endpoint_count: live.length,
|
|
5033
|
+
avg_duration_ms: totalRequests > 0 ? Math.round(totalDuration / totalRequests) : 0,
|
|
5034
|
+
slowest_endpoint_bucket: speedBucket(slowestP95),
|
|
5035
|
+
tabs_viewed: [...session.tabsViewed],
|
|
5036
|
+
dashboard_opened: session.dashboardOpened,
|
|
5037
|
+
explain_used: session.explainUsed,
|
|
5038
|
+
session_duration_s: Math.round((now - session.startTime) / 1e3),
|
|
5039
|
+
// Enhanced fields
|
|
5040
|
+
setup_succeeded: session.setupSucceeded,
|
|
5041
|
+
setup_duration_ms: session.setupDurationMs,
|
|
5042
|
+
framework_detection_candidates: session.frameworkCandidates,
|
|
5043
|
+
adapters_failed: session.adaptersFailed,
|
|
5044
|
+
time_to_first_request_ms: session.firstRequestAt ? session.firstRequestAt - session.startTime : null,
|
|
5045
|
+
time_to_dashboard_ms: session.dashboardOpenedAt ? session.dashboardOpenedAt - session.startTime : null,
|
|
5046
|
+
exit_reason: session.exitReason
|
|
5047
|
+
});
|
|
5048
|
+
getOrCreateConfig();
|
|
4972
5049
|
}
|
|
4973
5050
|
var POSTHOG_KEY, session;
|
|
4974
5051
|
var init_telemetry = __esm({
|
|
@@ -4977,6 +5054,7 @@ var init_telemetry = __esm({
|
|
|
4977
5054
|
init_src();
|
|
4978
5055
|
init_config2();
|
|
4979
5056
|
init_labels();
|
|
5057
|
+
init_config();
|
|
4980
5058
|
init_config2();
|
|
4981
5059
|
POSTHOG_KEY = "phc_E9TwydCGnSfPLIUhNxChpeg32TSowjk31KiPhnLPP0x";
|
|
4982
5060
|
session = {
|
|
@@ -4990,7 +5068,14 @@ var init_telemetry = __esm({
|
|
|
4990
5068
|
rulesTriggered: /* @__PURE__ */ new Set(),
|
|
4991
5069
|
tabsViewed: /* @__PURE__ */ new Set(),
|
|
4992
5070
|
dashboardOpened: false,
|
|
4993
|
-
explainUsed: false
|
|
5071
|
+
explainUsed: false,
|
|
5072
|
+
frameworkCandidates: [],
|
|
5073
|
+
adaptersFailed: [],
|
|
5074
|
+
setupDurationMs: 0,
|
|
5075
|
+
setupSucceeded: false,
|
|
5076
|
+
firstRequestAt: 0,
|
|
5077
|
+
dashboardOpenedAt: 0,
|
|
5078
|
+
exitReason: "unknown"
|
|
4994
5079
|
};
|
|
4995
5080
|
}
|
|
4996
5081
|
});
|
|
@@ -5992,18 +6077,21 @@ function installHooks(bus) {
|
|
|
5992
6077
|
adapterRegistry.patchAll(telemetryEmit);
|
|
5993
6078
|
const cwd = process.cwd();
|
|
5994
6079
|
let framework = "unknown";
|
|
6080
|
+
let frameworkCandidates = [];
|
|
5995
6081
|
try {
|
|
5996
6082
|
const pkg = JSON.parse(
|
|
5997
|
-
// readFileSync is acceptable here — runs once at startup
|
|
5998
6083
|
__require("fs").readFileSync(resolve5(cwd, "package.json"), "utf-8")
|
|
5999
6084
|
);
|
|
6000
6085
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
6001
6086
|
framework = detectFrameworkFromDeps(allDeps);
|
|
6087
|
+
frameworkCandidates = KNOWN_DEPENDENCY_NAMES.filter((dep) => dep in allDeps);
|
|
6002
6088
|
} catch {
|
|
6003
6089
|
}
|
|
6004
6090
|
return {
|
|
6005
6091
|
framework,
|
|
6006
|
-
adapterNames: adapterRegistry.getActive().map((a) => a.name)
|
|
6092
|
+
adapterNames: adapterRegistry.getActive().map((a) => a.name),
|
|
6093
|
+
adaptersFailed: [...adapterRegistry.getFailed()],
|
|
6094
|
+
frameworkCandidates
|
|
6007
6095
|
};
|
|
6008
6096
|
}
|
|
6009
6097
|
function startAnalysis(bus, stores, dataDir, services) {
|
|
@@ -6058,7 +6146,14 @@ function registerLifecycle(allServices, stores, services, cwd) {
|
|
|
6058
6146
|
}
|
|
6059
6147
|
};
|
|
6060
6148
|
health.setTeardown(runTeardown);
|
|
6149
|
+
process.on("SIGINT", () => {
|
|
6150
|
+
recordExitReason(EXIT_REASON_SIGINT);
|
|
6151
|
+
});
|
|
6152
|
+
process.on("SIGTERM", () => {
|
|
6153
|
+
recordExitReason(EXIT_REASON_SIGTERM);
|
|
6154
|
+
});
|
|
6061
6155
|
process.on("beforeExit", () => {
|
|
6156
|
+
recordExitReason(EXIT_REASON_CLEAN);
|
|
6062
6157
|
sendTelemetry();
|
|
6063
6158
|
});
|
|
6064
6159
|
process.on("exit", () => {
|
|
@@ -6066,6 +6161,7 @@ function registerLifecycle(allServices, stores, services, cwd) {
|
|
|
6066
6161
|
});
|
|
6067
6162
|
}
|
|
6068
6163
|
async function doSetup() {
|
|
6164
|
+
const setupStart = Date.now();
|
|
6069
6165
|
brakitDebug(`[setup] doSetup called at ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
6070
6166
|
const bus = new EventBus();
|
|
6071
6167
|
const cwd = process.cwd();
|
|
@@ -6074,8 +6170,18 @@ async function doSetup() {
|
|
|
6074
6170
|
bus,
|
|
6075
6171
|
...stores
|
|
6076
6172
|
};
|
|
6077
|
-
const { framework, adapterNames } = installHooks(bus);
|
|
6173
|
+
const { framework, adapterNames, adaptersFailed, frameworkCandidates } = installHooks(bus);
|
|
6078
6174
|
initSession(framework, detectPackageManagerSync(cwd), false, adapterNames);
|
|
6175
|
+
const setupDurationMs = Date.now() - setupStart;
|
|
6176
|
+
recordSetupCompleted({ frameworkCandidates, adaptersFailed, setupDurationMs });
|
|
6177
|
+
trackEvent(TELEMETRY_EVENT_SETUP_COMPLETED, {
|
|
6178
|
+
framework,
|
|
6179
|
+
framework_detection_candidates: frameworkCandidates,
|
|
6180
|
+
adapters_detected: adapterNames,
|
|
6181
|
+
adapters_failed: adaptersFailed,
|
|
6182
|
+
hooks_installed: ["fetch", "console", "error"],
|
|
6183
|
+
setup_duration_ms: setupDurationMs
|
|
6184
|
+
});
|
|
6079
6185
|
const dataDir = getProjectDataDir(cwd);
|
|
6080
6186
|
const analysisServices = startAnalysis(bus, stores, dataDir, services);
|
|
6081
6187
|
const config = {
|
|
@@ -6092,6 +6198,11 @@ async function doSetup() {
|
|
|
6092
6198
|
onFirstRequest(port) {
|
|
6093
6199
|
setBrakitPort(port);
|
|
6094
6200
|
brakitDebug(`[setup] onFirstRequest fired, port=${port}`);
|
|
6201
|
+
recordFirstRequest();
|
|
6202
|
+
trackEvent(TELEMETRY_EVENT_FIRST_REQUEST, {
|
|
6203
|
+
port,
|
|
6204
|
+
time_to_first_request_ms: Date.now() - setupStart
|
|
6205
|
+
});
|
|
6095
6206
|
void (async () => {
|
|
6096
6207
|
try {
|
|
6097
6208
|
const dir = resolve5(cwd, METRICS_DIR);
|
package/package.json
CHANGED