@victor-studio/monitor 0.2.0 → 0.5.0
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/adapters/bullmq/bullmq.cjs +85 -0
- package/dist/adapters/bullmq/bullmq.cjs.map +1 -0
- package/dist/adapters/bullmq/bullmq.d.cts +176 -0
- package/dist/adapters/bullmq/bullmq.d.ts +176 -0
- package/dist/adapters/bullmq/bullmq.js +82 -0
- package/dist/adapters/bullmq/bullmq.js.map +1 -0
- package/dist/adapters/gemini/gemini.cjs +65 -0
- package/dist/adapters/gemini/gemini.cjs.map +1 -0
- package/dist/adapters/gemini/gemini.d.cts +173 -0
- package/dist/adapters/gemini/gemini.d.ts +173 -0
- package/dist/adapters/gemini/gemini.js +62 -0
- package/dist/adapters/gemini/gemini.js.map +1 -0
- package/dist/adapters/index.cjs +56 -0
- package/dist/adapters/index.cjs.map +1 -0
- package/dist/adapters/index.d.cts +154 -0
- package/dist/adapters/index.d.ts +154 -0
- package/dist/adapters/index.js +53 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/neon/neon.cjs +36 -0
- package/dist/adapters/neon/neon.cjs.map +1 -0
- package/dist/adapters/neon/neon.d.cts +151 -0
- package/dist/adapters/neon/neon.d.ts +151 -0
- package/dist/adapters/neon/neon.js +34 -0
- package/dist/adapters/neon/neon.js.map +1 -0
- package/dist/adapters/railway/railway.cjs +20 -0
- package/dist/adapters/railway/railway.cjs.map +1 -0
- package/dist/adapters/railway/railway.d.cts +23 -0
- package/dist/adapters/railway/railway.d.ts +23 -0
- package/dist/adapters/railway/railway.js +18 -0
- package/dist/adapters/railway/railway.js.map +1 -0
- package/dist/adapters/resend/resend.cjs +36 -0
- package/dist/adapters/resend/resend.cjs.map +1 -0
- package/dist/adapters/resend/resend.d.cts +157 -0
- package/dist/adapters/resend/resend.d.ts +157 -0
- package/dist/adapters/resend/resend.js +34 -0
- package/dist/adapters/resend/resend.js.map +1 -0
- package/dist/adapters/upstash/upstash.cjs +39 -0
- package/dist/adapters/upstash/upstash.cjs.map +1 -0
- package/dist/adapters/upstash/upstash.d.cts +150 -0
- package/dist/adapters/upstash/upstash.d.ts +150 -0
- package/dist/adapters/upstash/upstash.js +37 -0
- package/dist/adapters/upstash/upstash.js.map +1 -0
- package/dist/adapters/vercel/vercel.cjs +18 -0
- package/dist/adapters/vercel/vercel.cjs.map +1 -0
- package/dist/adapters/vercel/vercel.d.cts +23 -0
- package/dist/adapters/vercel/vercel.d.ts +23 -0
- package/dist/adapters/vercel/vercel.js +16 -0
- package/dist/adapters/vercel/vercel.js.map +1 -0
- package/dist/deploys/index.cjs +53 -0
- package/dist/deploys/index.cjs.map +1 -0
- package/dist/deploys/index.d.cts +174 -0
- package/dist/deploys/index.d.ts +174 -0
- package/dist/deploys/index.js +50 -0
- package/dist/deploys/index.js.map +1 -0
- package/dist/errors/index.cjs +93 -0
- package/dist/errors/index.cjs.map +1 -0
- package/dist/errors/index.d.cts +183 -0
- package/dist/errors/index.d.ts +183 -0
- package/dist/errors/index.js +88 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.cjs +96 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -1
- package/dist/index.d.ts +41 -1
- package/dist/index.js +95 -1
- package/dist/index.js.map +1 -1
- package/dist/next/index.d.cts +5 -0
- package/dist/next/index.d.ts +5 -0
- package/dist/react/index.d.cts +5 -0
- package/dist/react/index.d.ts +5 -0
- package/package.json +51 -1
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
interface HeartbeatData {
|
|
2
|
+
status: 'online' | 'offline';
|
|
3
|
+
latencyMs: number;
|
|
4
|
+
}
|
|
5
|
+
interface RequestData {
|
|
6
|
+
method: string;
|
|
7
|
+
route: string;
|
|
8
|
+
statusCode: number;
|
|
9
|
+
responseTimeMs: number;
|
|
10
|
+
userAgent?: string;
|
|
11
|
+
region?: string;
|
|
12
|
+
}
|
|
13
|
+
interface VitalData {
|
|
14
|
+
name: 'LCP' | 'INP' | 'CLS' | 'FCP' | 'TTFB';
|
|
15
|
+
value: number;
|
|
16
|
+
rating: 'good' | 'needs-improvement' | 'poor';
|
|
17
|
+
page?: string;
|
|
18
|
+
deviceType?: string;
|
|
19
|
+
browser?: string;
|
|
20
|
+
}
|
|
21
|
+
interface ErrorData {
|
|
22
|
+
type: 'unhandled' | 'caught' | 'promise';
|
|
23
|
+
message: string;
|
|
24
|
+
stack?: string;
|
|
25
|
+
groupingKey: string;
|
|
26
|
+
route?: string;
|
|
27
|
+
method?: string;
|
|
28
|
+
statusCode?: number;
|
|
29
|
+
environment?: string;
|
|
30
|
+
commitHash?: string;
|
|
31
|
+
extra?: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
interface DeployData {
|
|
34
|
+
commitHash: string;
|
|
35
|
+
branch?: string;
|
|
36
|
+
author?: string;
|
|
37
|
+
status: 'started' | 'succeeded' | 'failed';
|
|
38
|
+
buildDurationMs?: number;
|
|
39
|
+
url?: string;
|
|
40
|
+
environment?: string;
|
|
41
|
+
provider?: string;
|
|
42
|
+
}
|
|
43
|
+
interface AdapterData {
|
|
44
|
+
adapter: string;
|
|
45
|
+
operation: string;
|
|
46
|
+
durationMs: number;
|
|
47
|
+
success: boolean;
|
|
48
|
+
error?: string;
|
|
49
|
+
meta?: Record<string, string>;
|
|
50
|
+
}
|
|
51
|
+
type MonitorEvent = {
|
|
52
|
+
type: 'heartbeat';
|
|
53
|
+
data: HeartbeatData;
|
|
54
|
+
timestamp: string;
|
|
55
|
+
} | {
|
|
56
|
+
type: 'request';
|
|
57
|
+
data: RequestData;
|
|
58
|
+
timestamp: string;
|
|
59
|
+
} | {
|
|
60
|
+
type: 'vital';
|
|
61
|
+
data: VitalData;
|
|
62
|
+
timestamp: string;
|
|
63
|
+
} | {
|
|
64
|
+
type: 'error';
|
|
65
|
+
data: ErrorData;
|
|
66
|
+
timestamp: string;
|
|
67
|
+
} | {
|
|
68
|
+
type: 'deploy';
|
|
69
|
+
data: DeployData;
|
|
70
|
+
timestamp: string;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'adapter';
|
|
73
|
+
data: AdapterData;
|
|
74
|
+
timestamp: string;
|
|
75
|
+
};
|
|
76
|
+
/** Hook para filtrar/modificar eventos antes do envio */
|
|
77
|
+
type BeforeSendHook = (event: MonitorEvent) => MonitorEvent | null;
|
|
78
|
+
|
|
79
|
+
interface MonitorConfig {
|
|
80
|
+
/** ID do projeto no Nuvio */
|
|
81
|
+
projectId: string;
|
|
82
|
+
/** API key gerada no Nuvio */
|
|
83
|
+
apiKey: string;
|
|
84
|
+
/** URL do endpoint de ingest */
|
|
85
|
+
endpoint: string;
|
|
86
|
+
/** Intervalo do heartbeat em ms (default: 60000) */
|
|
87
|
+
heartbeatInterval?: number;
|
|
88
|
+
/** Intervalo do flush do buffer em ms (default: 30000) */
|
|
89
|
+
flushInterval?: number;
|
|
90
|
+
/** Timeout do fetch em ms (default: 10000) */
|
|
91
|
+
timeout?: number;
|
|
92
|
+
/** Max tentativas de retry (default: 3) */
|
|
93
|
+
maxRetries?: number;
|
|
94
|
+
/** Desabilitar em desenvolvimento (default: true) */
|
|
95
|
+
disableInDev?: boolean;
|
|
96
|
+
/** Taxa de amostragem 0.0-1.0 (default: 1.0). Heartbeats nunca são amostrados */
|
|
97
|
+
sampleRate?: number;
|
|
98
|
+
/** Hook chamado antes de enfileirar cada evento. Retorna null para dropar */
|
|
99
|
+
beforeSend?: BeforeSendHook;
|
|
100
|
+
/** Habilitar logs de debug no console (default: false) */
|
|
101
|
+
debug?: boolean;
|
|
102
|
+
/** Capturar erros globais automaticamente — window.onerror (default: false) */
|
|
103
|
+
captureErrors?: boolean;
|
|
104
|
+
/** Capturar unhandled promise rejections automaticamente (default: false) */
|
|
105
|
+
captureUnhandledRejections?: boolean;
|
|
106
|
+
}
|
|
107
|
+
declare class MonitorClient {
|
|
108
|
+
readonly config: MonitorConfig;
|
|
109
|
+
private readonly collector;
|
|
110
|
+
private readonly logger;
|
|
111
|
+
private heartbeatTimer;
|
|
112
|
+
private globalHandlersCleanup;
|
|
113
|
+
private active;
|
|
114
|
+
constructor(config: MonitorConfig);
|
|
115
|
+
/** Inicia o monitoring (heartbeat + collector) */
|
|
116
|
+
start(): void;
|
|
117
|
+
/** Para o monitoring */
|
|
118
|
+
stop(): void;
|
|
119
|
+
/** Força um flush imediato do buffer */
|
|
120
|
+
flush(): void;
|
|
121
|
+
/** Verifica se o monitoring está ativo */
|
|
122
|
+
get isActive(): boolean;
|
|
123
|
+
/** Registra um evento de request HTTP (usado pelo middleware) */
|
|
124
|
+
trackRequest(data: RequestData): void;
|
|
125
|
+
/** Registra um Web Vital (usado pelo MonitorScript) */
|
|
126
|
+
trackVital(data: VitalData): void;
|
|
127
|
+
/** Registra um evento de adapter (DB, cache, AI, queue, email) */
|
|
128
|
+
trackAdapter(data: AdapterData): void;
|
|
129
|
+
/** Registra um erro capturado */
|
|
130
|
+
captureError(data: ErrorData): void;
|
|
131
|
+
/** Registra um evento de deploy */
|
|
132
|
+
trackDeploy(data: DeployData): void;
|
|
133
|
+
private startHeartbeat;
|
|
134
|
+
private sendHeartbeat;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Instrumenta um comando Redis com timing.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* import { monitorRedis } from '@victor-studio/monitor/adapters/upstash'
|
|
143
|
+
*
|
|
144
|
+
* const value = await monitorRedis(monitor, 'get', () => redis.get('key'))
|
|
145
|
+
* await monitorRedis(monitor, 'set', () => redis.set('key', 'value'))
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
declare function monitorRedis<T>(monitor: MonitorClient, command: string, fn: () => Promise<T>, meta?: Record<string, string>): Promise<T>;
|
|
149
|
+
|
|
150
|
+
export { monitorRedis };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// src/adapters/core.ts
|
|
2
|
+
async function withTiming(monitor, adapter, operation, fn, meta) {
|
|
3
|
+
const start = performance.now();
|
|
4
|
+
try {
|
|
5
|
+
const result = await fn();
|
|
6
|
+
monitor.trackAdapter({
|
|
7
|
+
adapter,
|
|
8
|
+
operation,
|
|
9
|
+
durationMs: Math.round(performance.now() - start),
|
|
10
|
+
success: true,
|
|
11
|
+
meta
|
|
12
|
+
});
|
|
13
|
+
return result;
|
|
14
|
+
} catch (error) {
|
|
15
|
+
monitor.trackAdapter({
|
|
16
|
+
adapter,
|
|
17
|
+
operation,
|
|
18
|
+
durationMs: Math.round(performance.now() - start),
|
|
19
|
+
success: false,
|
|
20
|
+
error: error instanceof Error ? error.message : String(error),
|
|
21
|
+
meta
|
|
22
|
+
});
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/adapters/upstash.ts
|
|
28
|
+
function monitorRedis(monitor, command, fn, meta) {
|
|
29
|
+
return withTiming(monitor, "upstash", command, fn, {
|
|
30
|
+
command,
|
|
31
|
+
...meta
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { monitorRedis };
|
|
36
|
+
//# sourceMappingURL=upstash.js.map
|
|
37
|
+
//# sourceMappingURL=upstash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/core.ts","../../../src/adapters/upstash.ts"],"names":[],"mappings":";AAgBA,eAAsB,UAAA,CACpB,OAAA,EACA,OAAA,EACA,SAAA,EACA,IACA,IAAA,EACY;AACZ,EAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAE9B,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAM,EAAA,EAAG;AAExB,IAAA,OAAA,CAAQ,YAAA,CAAa;AAAA,MACnB,OAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAY,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,KAAQ,KAAK,CAAA;AAAA,MAChD,OAAA,EAAS,IAAA;AAAA,MACT;AAAA,KACqB,CAAA;AAEvB,IAAA,OAAO,MAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,YAAA,CAAa;AAAA,MACnB,OAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAY,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,KAAQ,KAAK,CAAA;AAAA,MAChD,OAAA,EAAS,KAAA;AAAA,MACT,OAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAAA,MAC5D;AAAA,KACqB,CAAA;AAEvB,IAAA,MAAM,KAAA;AAAA,EACR;AACF;;;ACjCO,SAAS,YAAA,CACd,OAAA,EACA,OAAA,EACA,EAAA,EACA,IAAA,EACY;AACZ,EAAA,OAAO,UAAA,CAAW,OAAA,EAAS,SAAA,EAAW,OAAA,EAAS,EAAA,EAAI;AAAA,IACjD,OAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH","file":"upstash.js","sourcesContent":["// Adapter core — utilitário genérico de instrumentação\n\nimport type { MonitorClient } from '../core/client'\nimport type { AdapterData } from '../types'\n\n/**\n * Mede a duração de uma operação assíncrona e reporta ao monitor.\n * Utilitário base usado por todos os adapters.\n *\n * @example\n * ```ts\n * const result = await withTiming(monitor, 'neon', 'query', () =>\n * db.select().from(users),\n * )\n * ```\n */\nexport async function withTiming<T>(\n monitor: MonitorClient,\n adapter: string,\n operation: string,\n fn: () => Promise<T>,\n meta?: Record<string, string>,\n): Promise<T> {\n const start = performance.now()\n\n try {\n const result = await fn()\n\n monitor.trackAdapter({\n adapter,\n operation,\n durationMs: Math.round(performance.now() - start),\n success: true,\n meta,\n } satisfies AdapterData)\n\n return result\n } catch (error) {\n monitor.trackAdapter({\n adapter,\n operation,\n durationMs: Math.round(performance.now() - start),\n success: false,\n error: error instanceof Error ? error.message : String(error),\n meta,\n } satisfies AdapterData)\n\n throw error // nunca engolir erros\n }\n}\n\n/**\n * Versão sync do withTiming para operações síncronas.\n */\nexport function withTimingSync<T>(\n monitor: MonitorClient,\n adapter: string,\n operation: string,\n fn: () => T,\n meta?: Record<string, string>,\n): T {\n const start = performance.now()\n\n try {\n const result = fn()\n\n monitor.trackAdapter({\n adapter,\n operation,\n durationMs: Math.round(performance.now() - start),\n success: true,\n meta,\n } satisfies AdapterData)\n\n return result\n } catch (error) {\n monitor.trackAdapter({\n adapter,\n operation,\n durationMs: Math.round(performance.now() - start),\n success: false,\n error: error instanceof Error ? error.message : String(error),\n meta,\n } satisfies AdapterData)\n\n throw error\n }\n}\n","// Adapter Upstash — instrumentação de comandos Redis\n\nimport type { MonitorClient } from '../core/client'\nimport { withTiming } from './core'\n\n/**\n * Instrumenta um comando Redis com timing.\n *\n * @example\n * ```ts\n * import { monitorRedis } from '@victor-studio/monitor/adapters/upstash'\n *\n * const value = await monitorRedis(monitor, 'get', () => redis.get('key'))\n * await monitorRedis(monitor, 'set', () => redis.set('key', 'value'))\n * ```\n */\nexport function monitorRedis<T>(\n monitor: MonitorClient,\n command: string,\n fn: () => Promise<T>,\n meta?: Record<string, string>,\n): Promise<T> {\n return withTiming(monitor, 'upstash', command, fn, {\n command,\n ...meta,\n })\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/adapters/vercel.ts
|
|
4
|
+
function getVercelContext() {
|
|
5
|
+
if (typeof process === "undefined") return {};
|
|
6
|
+
const env = process.env;
|
|
7
|
+
return {
|
|
8
|
+
region: env.VERCEL_REGION,
|
|
9
|
+
environment: env.VERCEL_ENV,
|
|
10
|
+
commitHash: env.VERCEL_GIT_COMMIT_SHA,
|
|
11
|
+
branch: env.VERCEL_GIT_COMMIT_REF,
|
|
12
|
+
url: env.VERCEL_URL ? `https://${env.VERCEL_URL}` : void 0
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.getVercelContext = getVercelContext;
|
|
17
|
+
//# sourceMappingURL=vercel.cjs.map
|
|
18
|
+
//# sourceMappingURL=vercel.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/vercel.ts"],"names":[],"mappings":";;;AAuBO,SAAS,gBAAA,GAAkC;AAChD,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,EAAa,OAAO,EAAC;AAC5C,EAAA,MAAM,MAAM,OAAA,CAAQ,GAAA;AAEpB,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,CAAI,aAAA;AAAA,IACZ,aAAa,GAAA,CAAI,UAAA;AAAA,IACjB,YAAY,GAAA,CAAI,qBAAA;AAAA,IAChB,QAAQ,GAAA,CAAI,qBAAA;AAAA,IACZ,KAAK,GAAA,CAAI,UAAA,GAAa,CAAA,QAAA,EAAW,GAAA,CAAI,UAAU,CAAA,CAAA,GAAK;AAAA,GACtD;AACF","file":"vercel.cjs","sourcesContent":["// Adapter Vercel — contexto de deploy e runtime\n\n/** Contexto Vercel extraído das env vars */\nexport interface VercelContext {\n region?: string\n environment?: string\n commitHash?: string\n branch?: string\n url?: string\n}\n\n/**\n * Lê contexto de runtime do Vercel via env vars.\n * Útil para enriquecer eventos com metadados de deploy.\n *\n * @example\n * ```ts\n * import { getVercelContext } from '@victor-studio/monitor/adapters/vercel'\n *\n * const ctx = getVercelContext()\n * // { region: 'iad1', environment: 'production', commitHash: 'abc123', ... }\n * ```\n */\nexport function getVercelContext(): VercelContext {\n if (typeof process === 'undefined') return {}\n const env = process.env\n\n return {\n region: env.VERCEL_REGION,\n environment: env.VERCEL_ENV,\n commitHash: env.VERCEL_GIT_COMMIT_SHA,\n branch: env.VERCEL_GIT_COMMIT_REF,\n url: env.VERCEL_URL ? `https://${env.VERCEL_URL}` : undefined,\n }\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Contexto Vercel extraído das env vars */
|
|
2
|
+
interface VercelContext {
|
|
3
|
+
region?: string;
|
|
4
|
+
environment?: string;
|
|
5
|
+
commitHash?: string;
|
|
6
|
+
branch?: string;
|
|
7
|
+
url?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Lê contexto de runtime do Vercel via env vars.
|
|
11
|
+
* Útil para enriquecer eventos com metadados de deploy.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { getVercelContext } from '@victor-studio/monitor/adapters/vercel'
|
|
16
|
+
*
|
|
17
|
+
* const ctx = getVercelContext()
|
|
18
|
+
* // { region: 'iad1', environment: 'production', commitHash: 'abc123', ... }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
declare function getVercelContext(): VercelContext;
|
|
22
|
+
|
|
23
|
+
export { type VercelContext, getVercelContext };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Contexto Vercel extraído das env vars */
|
|
2
|
+
interface VercelContext {
|
|
3
|
+
region?: string;
|
|
4
|
+
environment?: string;
|
|
5
|
+
commitHash?: string;
|
|
6
|
+
branch?: string;
|
|
7
|
+
url?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Lê contexto de runtime do Vercel via env vars.
|
|
11
|
+
* Útil para enriquecer eventos com metadados de deploy.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { getVercelContext } from '@victor-studio/monitor/adapters/vercel'
|
|
16
|
+
*
|
|
17
|
+
* const ctx = getVercelContext()
|
|
18
|
+
* // { region: 'iad1', environment: 'production', commitHash: 'abc123', ... }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
declare function getVercelContext(): VercelContext;
|
|
22
|
+
|
|
23
|
+
export { type VercelContext, getVercelContext };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/adapters/vercel.ts
|
|
2
|
+
function getVercelContext() {
|
|
3
|
+
if (typeof process === "undefined") return {};
|
|
4
|
+
const env = process.env;
|
|
5
|
+
return {
|
|
6
|
+
region: env.VERCEL_REGION,
|
|
7
|
+
environment: env.VERCEL_ENV,
|
|
8
|
+
commitHash: env.VERCEL_GIT_COMMIT_SHA,
|
|
9
|
+
branch: env.VERCEL_GIT_COMMIT_REF,
|
|
10
|
+
url: env.VERCEL_URL ? `https://${env.VERCEL_URL}` : void 0
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { getVercelContext };
|
|
15
|
+
//# sourceMappingURL=vercel.js.map
|
|
16
|
+
//# sourceMappingURL=vercel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/vercel.ts"],"names":[],"mappings":";AAuBO,SAAS,gBAAA,GAAkC;AAChD,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,EAAa,OAAO,EAAC;AAC5C,EAAA,MAAM,MAAM,OAAA,CAAQ,GAAA;AAEpB,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,CAAI,aAAA;AAAA,IACZ,aAAa,GAAA,CAAI,UAAA;AAAA,IACjB,YAAY,GAAA,CAAI,qBAAA;AAAA,IAChB,QAAQ,GAAA,CAAI,qBAAA;AAAA,IACZ,KAAK,GAAA,CAAI,UAAA,GAAa,CAAA,QAAA,EAAW,GAAA,CAAI,UAAU,CAAA,CAAA,GAAK;AAAA,GACtD;AACF","file":"vercel.js","sourcesContent":["// Adapter Vercel — contexto de deploy e runtime\n\n/** Contexto Vercel extraído das env vars */\nexport interface VercelContext {\n region?: string\n environment?: string\n commitHash?: string\n branch?: string\n url?: string\n}\n\n/**\n * Lê contexto de runtime do Vercel via env vars.\n * Útil para enriquecer eventos com metadados de deploy.\n *\n * @example\n * ```ts\n * import { getVercelContext } from '@victor-studio/monitor/adapters/vercel'\n *\n * const ctx = getVercelContext()\n * // { region: 'iad1', environment: 'production', commitHash: 'abc123', ... }\n * ```\n */\nexport function getVercelContext(): VercelContext {\n if (typeof process === 'undefined') return {}\n const env = process.env\n\n return {\n region: env.VERCEL_REGION,\n environment: env.VERCEL_ENV,\n commitHash: env.VERCEL_GIT_COMMIT_SHA,\n branch: env.VERCEL_GIT_COMMIT_REF,\n url: env.VERCEL_URL ? `https://${env.VERCEL_URL}` : undefined,\n }\n}\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/deploys/tracker.ts
|
|
4
|
+
function detectDeploy() {
|
|
5
|
+
if (typeof process === "undefined") return null;
|
|
6
|
+
const env = process.env;
|
|
7
|
+
if (env.VERCEL) {
|
|
8
|
+
const commitHash = env.VERCEL_GIT_COMMIT_SHA;
|
|
9
|
+
if (!commitHash) return null;
|
|
10
|
+
return {
|
|
11
|
+
commitHash,
|
|
12
|
+
branch: env.VERCEL_GIT_COMMIT_REF,
|
|
13
|
+
author: env.VERCEL_GIT_COMMIT_AUTHOR_LOGIN,
|
|
14
|
+
environment: env.VERCEL_ENV,
|
|
15
|
+
// 'production' | 'preview' | 'development'
|
|
16
|
+
url: env.VERCEL_URL ? `https://${env.VERCEL_URL}` : void 0,
|
|
17
|
+
provider: "vercel"
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (env.RAILWAY_ENVIRONMENT) {
|
|
21
|
+
const commitHash = env.RAILWAY_GIT_COMMIT_SHA;
|
|
22
|
+
if (!commitHash) return null;
|
|
23
|
+
return {
|
|
24
|
+
commitHash,
|
|
25
|
+
branch: env.RAILWAY_GIT_BRANCH,
|
|
26
|
+
author: env.RAILWAY_GIT_AUTHOR,
|
|
27
|
+
environment: env.RAILWAY_ENVIRONMENT,
|
|
28
|
+
url: env.RAILWAY_PUBLIC_DOMAIN ? `https://${env.RAILWAY_PUBLIC_DOMAIN}` : void 0,
|
|
29
|
+
provider: "railway"
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
function reportDeploy(monitor, overrides) {
|
|
35
|
+
const detected = detectDeploy();
|
|
36
|
+
if (!detected && !overrides?.commitHash) return;
|
|
37
|
+
const data = {
|
|
38
|
+
commitHash: overrides?.commitHash ?? detected?.commitHash ?? "unknown",
|
|
39
|
+
branch: overrides?.branch ?? detected?.branch,
|
|
40
|
+
author: overrides?.author ?? detected?.author,
|
|
41
|
+
status: overrides?.status ?? "succeeded",
|
|
42
|
+
buildDurationMs: overrides?.buildDurationMs,
|
|
43
|
+
url: overrides?.url ?? detected?.url,
|
|
44
|
+
environment: overrides?.environment ?? detected?.environment,
|
|
45
|
+
provider: overrides?.provider ?? detected?.provider
|
|
46
|
+
};
|
|
47
|
+
monitor.trackDeploy(data);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
exports.detectDeploy = detectDeploy;
|
|
51
|
+
exports.reportDeploy = reportDeploy;
|
|
52
|
+
//# sourceMappingURL=index.cjs.map
|
|
53
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/deploys/tracker.ts"],"names":[],"mappings":";;;AAqBO,SAAS,YAAA,GAAqC;AACnD,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,EAAa,OAAO,IAAA;AAC3C,EAAA,MAAM,MAAM,OAAA,CAAQ,GAAA;AAGpB,EAAA,IAAI,IAAI,MAAA,EAAQ;AACd,IAAA,MAAM,aAAa,GAAA,CAAI,qBAAA;AACvB,IAAA,IAAI,CAAC,YAAY,OAAO,IAAA;AAExB,IAAA,OAAO;AAAA,MACL,UAAA;AAAA,MACA,QAAQ,GAAA,CAAI,qBAAA;AAAA,MACZ,QAAQ,GAAA,CAAI,8BAAA;AAAA,MACZ,aAAa,GAAA,CAAI,UAAA;AAAA;AAAA,MACjB,KAAK,GAAA,CAAI,UAAA,GAAa,CAAA,QAAA,EAAW,GAAA,CAAI,UAAU,CAAA,CAAA,GAAK,MAAA;AAAA,MACpD,QAAA,EAAU;AAAA,KACZ;AAAA,EACF;AAGA,EAAA,IAAI,IAAI,mBAAA,EAAqB;AAC3B,IAAA,MAAM,aAAa,GAAA,CAAI,sBAAA;AACvB,IAAA,IAAI,CAAC,YAAY,OAAO,IAAA;AAExB,IAAA,OAAO;AAAA,MACL,UAAA;AAAA,MACA,QAAQ,GAAA,CAAI,kBAAA;AAAA,MACZ,QAAQ,GAAA,CAAI,kBAAA;AAAA,MACZ,aAAa,GAAA,CAAI,mBAAA;AAAA,MACjB,KAAK,GAAA,CAAI,qBAAA,GAAwB,CAAA,QAAA,EAAW,GAAA,CAAI,qBAAqB,CAAA,CAAA,GAAK,MAAA;AAAA,MAC1E,QAAA,EAAU;AAAA,KACZ;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAqBO,SAAS,YAAA,CAAa,SAAwB,SAAA,EAAuC;AAC1F,EAAA,MAAM,WAAW,YAAA,EAAa;AAE9B,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,SAAA,EAAW,UAAA,EAAY;AAEzC,EAAA,MAAM,IAAA,GAAmB;AAAA,IACvB,UAAA,EAAY,SAAA,EAAW,UAAA,IAAc,QAAA,EAAU,UAAA,IAAc,SAAA;AAAA,IAC7D,MAAA,EAAQ,SAAA,EAAW,MAAA,IAAU,QAAA,EAAU,MAAA;AAAA,IACvC,MAAA,EAAQ,SAAA,EAAW,MAAA,IAAU,QAAA,EAAU,MAAA;AAAA,IACvC,MAAA,EAAQ,WAAW,MAAA,IAAU,WAAA;AAAA,IAC7B,iBAAiB,SAAA,EAAW,eAAA;AAAA,IAC5B,GAAA,EAAK,SAAA,EAAW,GAAA,IAAO,QAAA,EAAU,GAAA;AAAA,IACjC,WAAA,EAAa,SAAA,EAAW,WAAA,IAAe,QAAA,EAAU,WAAA;AAAA,IACjD,QAAA,EAAU,SAAA,EAAW,QAAA,IAAY,QAAA,EAAU;AAAA,GAC7C;AAEA,EAAA,OAAA,CAAQ,YAAY,IAAI,CAAA;AAC1B","file":"index.cjs","sourcesContent":["// Deploy tracker — detecta e reporta deploys automaticamente\n\nimport type { MonitorClient } from '../core/client'\nimport type { DeployData } from '../types'\n\n/** Contexto de deploy detectado via env vars */\ninterface DeployContext {\n commitHash: string\n branch?: string\n author?: string\n environment?: string\n url?: string\n provider: string\n}\n\n/**\n * Detecta deploy info a partir das env vars do provider.\n * Suporta Vercel e Railway.\n *\n * @returns contexto do deploy ou null se não detectado\n */\nexport function detectDeploy(): DeployContext | null {\n if (typeof process === 'undefined') return null\n const env = process.env\n\n // Vercel\n if (env.VERCEL) {\n const commitHash = env.VERCEL_GIT_COMMIT_SHA\n if (!commitHash) return null\n\n return {\n commitHash,\n branch: env.VERCEL_GIT_COMMIT_REF,\n author: env.VERCEL_GIT_COMMIT_AUTHOR_LOGIN,\n environment: env.VERCEL_ENV, // 'production' | 'preview' | 'development'\n url: env.VERCEL_URL ? `https://${env.VERCEL_URL}` : undefined,\n provider: 'vercel',\n }\n }\n\n // Railway\n if (env.RAILWAY_ENVIRONMENT) {\n const commitHash = env.RAILWAY_GIT_COMMIT_SHA\n if (!commitHash) return null\n\n return {\n commitHash,\n branch: env.RAILWAY_GIT_BRANCH,\n author: env.RAILWAY_GIT_AUTHOR,\n environment: env.RAILWAY_ENVIRONMENT,\n url: env.RAILWAY_PUBLIC_DOMAIN ? `https://${env.RAILWAY_PUBLIC_DOMAIN}` : undefined,\n provider: 'railway',\n }\n }\n\n return null\n}\n\n/**\n * Reporta um deploy ao monitor. Detecta automaticamente Vercel/Railway.\n * Pode ser chamado no startup do app ou em CI/CD hooks.\n *\n * @example\n * ```ts\n * import { reportDeploy } from '@victor-studio/monitor/deploys'\n *\n * // Auto-detect (usa env vars)\n * reportDeploy(monitor)\n *\n * // Manual\n * reportDeploy(monitor, {\n * commitHash: 'abc123',\n * status: 'succeeded',\n * provider: 'vercel',\n * })\n * ```\n */\nexport function reportDeploy(monitor: MonitorClient, overrides?: Partial<DeployData>): void {\n const detected = detectDeploy()\n\n if (!detected && !overrides?.commitHash) return\n\n const data: DeployData = {\n commitHash: overrides?.commitHash ?? detected?.commitHash ?? 'unknown',\n branch: overrides?.branch ?? detected?.branch,\n author: overrides?.author ?? detected?.author,\n status: overrides?.status ?? 'succeeded',\n buildDurationMs: overrides?.buildDurationMs,\n url: overrides?.url ?? detected?.url,\n environment: overrides?.environment ?? detected?.environment,\n provider: overrides?.provider ?? detected?.provider,\n }\n\n monitor.trackDeploy(data)\n}\n"]}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
interface HeartbeatData {
|
|
2
|
+
status: 'online' | 'offline';
|
|
3
|
+
latencyMs: number;
|
|
4
|
+
}
|
|
5
|
+
interface RequestData {
|
|
6
|
+
method: string;
|
|
7
|
+
route: string;
|
|
8
|
+
statusCode: number;
|
|
9
|
+
responseTimeMs: number;
|
|
10
|
+
userAgent?: string;
|
|
11
|
+
region?: string;
|
|
12
|
+
}
|
|
13
|
+
interface VitalData {
|
|
14
|
+
name: 'LCP' | 'INP' | 'CLS' | 'FCP' | 'TTFB';
|
|
15
|
+
value: number;
|
|
16
|
+
rating: 'good' | 'needs-improvement' | 'poor';
|
|
17
|
+
page?: string;
|
|
18
|
+
deviceType?: string;
|
|
19
|
+
browser?: string;
|
|
20
|
+
}
|
|
21
|
+
interface ErrorData {
|
|
22
|
+
type: 'unhandled' | 'caught' | 'promise';
|
|
23
|
+
message: string;
|
|
24
|
+
stack?: string;
|
|
25
|
+
groupingKey: string;
|
|
26
|
+
route?: string;
|
|
27
|
+
method?: string;
|
|
28
|
+
statusCode?: number;
|
|
29
|
+
environment?: string;
|
|
30
|
+
commitHash?: string;
|
|
31
|
+
extra?: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
interface DeployData {
|
|
34
|
+
commitHash: string;
|
|
35
|
+
branch?: string;
|
|
36
|
+
author?: string;
|
|
37
|
+
status: 'started' | 'succeeded' | 'failed';
|
|
38
|
+
buildDurationMs?: number;
|
|
39
|
+
url?: string;
|
|
40
|
+
environment?: string;
|
|
41
|
+
provider?: string;
|
|
42
|
+
}
|
|
43
|
+
interface AdapterData {
|
|
44
|
+
adapter: string;
|
|
45
|
+
operation: string;
|
|
46
|
+
durationMs: number;
|
|
47
|
+
success: boolean;
|
|
48
|
+
error?: string;
|
|
49
|
+
meta?: Record<string, string>;
|
|
50
|
+
}
|
|
51
|
+
type MonitorEvent = {
|
|
52
|
+
type: 'heartbeat';
|
|
53
|
+
data: HeartbeatData;
|
|
54
|
+
timestamp: string;
|
|
55
|
+
} | {
|
|
56
|
+
type: 'request';
|
|
57
|
+
data: RequestData;
|
|
58
|
+
timestamp: string;
|
|
59
|
+
} | {
|
|
60
|
+
type: 'vital';
|
|
61
|
+
data: VitalData;
|
|
62
|
+
timestamp: string;
|
|
63
|
+
} | {
|
|
64
|
+
type: 'error';
|
|
65
|
+
data: ErrorData;
|
|
66
|
+
timestamp: string;
|
|
67
|
+
} | {
|
|
68
|
+
type: 'deploy';
|
|
69
|
+
data: DeployData;
|
|
70
|
+
timestamp: string;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'adapter';
|
|
73
|
+
data: AdapterData;
|
|
74
|
+
timestamp: string;
|
|
75
|
+
};
|
|
76
|
+
/** Hook para filtrar/modificar eventos antes do envio */
|
|
77
|
+
type BeforeSendHook = (event: MonitorEvent) => MonitorEvent | null;
|
|
78
|
+
|
|
79
|
+
interface MonitorConfig {
|
|
80
|
+
/** ID do projeto no Nuvio */
|
|
81
|
+
projectId: string;
|
|
82
|
+
/** API key gerada no Nuvio */
|
|
83
|
+
apiKey: string;
|
|
84
|
+
/** URL do endpoint de ingest */
|
|
85
|
+
endpoint: string;
|
|
86
|
+
/** Intervalo do heartbeat em ms (default: 60000) */
|
|
87
|
+
heartbeatInterval?: number;
|
|
88
|
+
/** Intervalo do flush do buffer em ms (default: 30000) */
|
|
89
|
+
flushInterval?: number;
|
|
90
|
+
/** Timeout do fetch em ms (default: 10000) */
|
|
91
|
+
timeout?: number;
|
|
92
|
+
/** Max tentativas de retry (default: 3) */
|
|
93
|
+
maxRetries?: number;
|
|
94
|
+
/** Desabilitar em desenvolvimento (default: true) */
|
|
95
|
+
disableInDev?: boolean;
|
|
96
|
+
/** Taxa de amostragem 0.0-1.0 (default: 1.0). Heartbeats nunca são amostrados */
|
|
97
|
+
sampleRate?: number;
|
|
98
|
+
/** Hook chamado antes de enfileirar cada evento. Retorna null para dropar */
|
|
99
|
+
beforeSend?: BeforeSendHook;
|
|
100
|
+
/** Habilitar logs de debug no console (default: false) */
|
|
101
|
+
debug?: boolean;
|
|
102
|
+
/** Capturar erros globais automaticamente — window.onerror (default: false) */
|
|
103
|
+
captureErrors?: boolean;
|
|
104
|
+
/** Capturar unhandled promise rejections automaticamente (default: false) */
|
|
105
|
+
captureUnhandledRejections?: boolean;
|
|
106
|
+
}
|
|
107
|
+
declare class MonitorClient {
|
|
108
|
+
readonly config: MonitorConfig;
|
|
109
|
+
private readonly collector;
|
|
110
|
+
private readonly logger;
|
|
111
|
+
private heartbeatTimer;
|
|
112
|
+
private globalHandlersCleanup;
|
|
113
|
+
private active;
|
|
114
|
+
constructor(config: MonitorConfig);
|
|
115
|
+
/** Inicia o monitoring (heartbeat + collector) */
|
|
116
|
+
start(): void;
|
|
117
|
+
/** Para o monitoring */
|
|
118
|
+
stop(): void;
|
|
119
|
+
/** Força um flush imediato do buffer */
|
|
120
|
+
flush(): void;
|
|
121
|
+
/** Verifica se o monitoring está ativo */
|
|
122
|
+
get isActive(): boolean;
|
|
123
|
+
/** Registra um evento de request HTTP (usado pelo middleware) */
|
|
124
|
+
trackRequest(data: RequestData): void;
|
|
125
|
+
/** Registra um Web Vital (usado pelo MonitorScript) */
|
|
126
|
+
trackVital(data: VitalData): void;
|
|
127
|
+
/** Registra um evento de adapter (DB, cache, AI, queue, email) */
|
|
128
|
+
trackAdapter(data: AdapterData): void;
|
|
129
|
+
/** Registra um erro capturado */
|
|
130
|
+
captureError(data: ErrorData): void;
|
|
131
|
+
/** Registra um evento de deploy */
|
|
132
|
+
trackDeploy(data: DeployData): void;
|
|
133
|
+
private startHeartbeat;
|
|
134
|
+
private sendHeartbeat;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Contexto de deploy detectado via env vars */
|
|
138
|
+
interface DeployContext {
|
|
139
|
+
commitHash: string;
|
|
140
|
+
branch?: string;
|
|
141
|
+
author?: string;
|
|
142
|
+
environment?: string;
|
|
143
|
+
url?: string;
|
|
144
|
+
provider: string;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Detecta deploy info a partir das env vars do provider.
|
|
148
|
+
* Suporta Vercel e Railway.
|
|
149
|
+
*
|
|
150
|
+
* @returns contexto do deploy ou null se não detectado
|
|
151
|
+
*/
|
|
152
|
+
declare function detectDeploy(): DeployContext | null;
|
|
153
|
+
/**
|
|
154
|
+
* Reporta um deploy ao monitor. Detecta automaticamente Vercel/Railway.
|
|
155
|
+
* Pode ser chamado no startup do app ou em CI/CD hooks.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* import { reportDeploy } from '@victor-studio/monitor/deploys'
|
|
160
|
+
*
|
|
161
|
+
* // Auto-detect (usa env vars)
|
|
162
|
+
* reportDeploy(monitor)
|
|
163
|
+
*
|
|
164
|
+
* // Manual
|
|
165
|
+
* reportDeploy(monitor, {
|
|
166
|
+
* commitHash: 'abc123',
|
|
167
|
+
* status: 'succeeded',
|
|
168
|
+
* provider: 'vercel',
|
|
169
|
+
* })
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
declare function reportDeploy(monitor: MonitorClient, overrides?: Partial<DeployData>): void;
|
|
173
|
+
|
|
174
|
+
export { detectDeploy, reportDeploy };
|