@ebowwa/crm 0.1.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/README.md +174 -0
- package/dist/cli/commands/activities.d.ts +11 -0
- package/dist/cli/commands/activities.d.ts.map +1 -0
- package/dist/cli/commands/activities.js +427 -0
- package/dist/cli/commands/activities.js.map +1 -0
- package/dist/cli/commands/contacts.d.ts +11 -0
- package/dist/cli/commands/contacts.d.ts.map +1 -0
- package/dist/cli/commands/contacts.js +458 -0
- package/dist/cli/commands/contacts.js.map +1 -0
- package/dist/cli/commands/deals.d.ts +11 -0
- package/dist/cli/commands/deals.d.ts.map +1 -0
- package/dist/cli/commands/deals.js +498 -0
- package/dist/cli/commands/deals.js.map +1 -0
- package/dist/cli/commands/media.d.ts +11 -0
- package/dist/cli/commands/media.d.ts.map +1 -0
- package/dist/cli/commands/media.js +417 -0
- package/dist/cli/commands/media.js.map +1 -0
- package/dist/cli/commands/search.d.ts +11 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +346 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +173 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/repl.d.ts +15 -0
- package/dist/cli/repl.d.ts.map +1 -0
- package/dist/cli/repl.js +318 -0
- package/dist/cli/repl.js.map +1 -0
- package/dist/cli/utils/config.d.ts +91 -0
- package/dist/cli/utils/config.d.ts.map +1 -0
- package/dist/cli/utils/config.js +212 -0
- package/dist/cli/utils/config.js.map +1 -0
- package/dist/cli/utils/output.d.ts +136 -0
- package/dist/cli/utils/output.d.ts.map +1 -0
- package/dist/cli/utils/output.js +323 -0
- package/dist/cli/utils/output.js.map +1 -0
- package/dist/cli/utils/prompt.d.ts +81 -0
- package/dist/cli/utils/prompt.d.ts.map +1 -0
- package/dist/cli/utils/prompt.js +341 -0
- package/dist/cli/utils/prompt.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +8 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +32 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/schemas.d.ts +3050 -0
- package/dist/core/schemas.d.ts.map +1 -0
- package/dist/core/schemas.js +667 -0
- package/dist/core/schemas.js.map +1 -0
- package/dist/core/types.d.ts +597 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +8 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.ts +14 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +18 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/storage/client.d.ts +109 -0
- package/dist/mcp/storage/client.d.ts.map +1 -0
- package/dist/mcp/storage/client.js +355 -0
- package/dist/mcp/storage/client.js.map +1 -0
- package/dist/mcp/storage/index.d.ts +7 -0
- package/dist/mcp/storage/index.d.ts.map +1 -0
- package/dist/mcp/storage/index.js +6 -0
- package/dist/mcp/storage/index.js.map +1 -0
- package/dist/mcp/storage/types.d.ts +44 -0
- package/dist/mcp/storage/types.d.ts.map +1 -0
- package/dist/mcp/storage/types.js +35 -0
- package/dist/mcp/storage/types.js.map +1 -0
- package/dist/mcp/tools/definitions.d.ts +16 -0
- package/dist/mcp/tools/definitions.d.ts.map +1 -0
- package/dist/mcp/tools/definitions.js +914 -0
- package/dist/mcp/tools/definitions.js.map +1 -0
- package/dist/mcp/tools/handlers.d.ts +50 -0
- package/dist/mcp/tools/handlers.d.ts.map +1 -0
- package/dist/mcp/tools/handlers.js +760 -0
- package/dist/mcp/tools/handlers.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +7 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +6 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/types.d.ts +314 -0
- package/dist/mcp/tools/types.d.ts.map +1 -0
- package/dist/mcp/tools/types.js +5 -0
- package/dist/mcp/tools/types.js.map +1 -0
- package/dist/mcp/transports/stdio.d.ts +27 -0
- package/dist/mcp/transports/stdio.d.ts.map +1 -0
- package/dist/mcp/transports/stdio.js +237 -0
- package/dist/mcp/transports/stdio.js.map +1 -0
- package/dist/telemetry/index.d.ts +58 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +109 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/logger.d.ts +116 -0
- package/dist/telemetry/logger.d.ts.map +1 -0
- package/dist/telemetry/logger.js +256 -0
- package/dist/telemetry/logger.js.map +1 -0
- package/dist/telemetry/metrics.d.ts +115 -0
- package/dist/telemetry/metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics.js +292 -0
- package/dist/telemetry/metrics.js.map +1 -0
- package/dist/telemetry/tracer.d.ts +227 -0
- package/dist/telemetry/tracer.d.ts.map +1 -0
- package/dist/telemetry/tracer.js +355 -0
- package/dist/telemetry/tracer.js.map +1 -0
- package/dist/web/app.d.ts +2 -0
- package/dist/web/app.d.ts.map +1 -0
- package/dist/web/app.js +115 -0
- package/dist/web/app.js.map +1 -0
- package/dist/web/components/ContactList.d.ts +3 -0
- package/dist/web/components/ContactList.d.ts.map +1 -0
- package/dist/web/components/ContactList.js +262 -0
- package/dist/web/components/ContactList.js.map +1 -0
- package/dist/web/components/Dashboard.d.ts +3 -0
- package/dist/web/components/Dashboard.d.ts.map +1 -0
- package/dist/web/components/Dashboard.js +158 -0
- package/dist/web/components/Dashboard.js.map +1 -0
- package/dist/web/components/DealPipeline.d.ts +3 -0
- package/dist/web/components/DealPipeline.d.ts.map +1 -0
- package/dist/web/components/DealPipeline.js +306 -0
- package/dist/web/components/DealPipeline.js.map +1 -0
- package/dist/web/index.d.ts +2 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +269 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/types.d.ts +75 -0
- package/dist/web/types.d.ts.map +1 -0
- package/dist/web/types.js +3 -0
- package/dist/web/types.js.map +1 -0
- package/native/index.d.ts +571 -0
- package/native/index.js +687 -0
- package/package.json +105 -0
- package/src/cli/commands/activities.ts +543 -0
- package/src/cli/commands/contacts.ts +563 -0
- package/src/cli/commands/deals.ts +637 -0
- package/src/cli/commands/media.ts +521 -0
- package/src/cli/commands/search.ts +426 -0
- package/src/cli/index.ts +203 -0
- package/src/cli/repl.ts +379 -0
- package/src/cli/utils/config.ts +299 -0
- package/src/cli/utils/output.ts +386 -0
- package/src/cli/utils/prompt.ts +444 -0
- package/src/cli.ts +11 -0
- package/src/core/index.ts +184 -0
- package/src/core/schemas.ts +770 -0
- package/src/core/types.ts +969 -0
- package/src/index.ts +8 -0
- package/src/mcp/index.ts +17 -0
- package/src/mcp/server.ts +26 -0
- package/src/mcp/storage/client.ts +408 -0
- package/src/mcp/storage/index.ts +7 -0
- package/src/mcp/storage/types.ts +72 -0
- package/src/mcp/tools/definitions.ts +961 -0
- package/src/mcp/tools/handlers.ts +805 -0
- package/src/mcp/tools/index.ts +7 -0
- package/src/mcp/tools/types.ts +390 -0
- package/src/mcp/transports/stdio.ts +225 -0
- package/src/telemetry/index.ts +131 -0
- package/src/telemetry/logger.ts +318 -0
- package/src/telemetry/metrics.ts +393 -0
- package/src/telemetry/tracer.ts +487 -0
- package/src/web/api/activities.ts +41 -0
- package/src/web/api/contacts.ts +114 -0
- package/src/web/api/deals.ts +108 -0
- package/src/web/api/media.ts +98 -0
- package/src/web/app.tsx +143 -0
- package/src/web/components/ActivityFeed.tsx +195 -0
- package/src/web/components/ContactList.tsx +340 -0
- package/src/web/components/Dashboard.tsx +214 -0
- package/src/web/components/DealPipeline.tsx +405 -0
- package/src/web/components/MediaGallery.tsx +334 -0
- package/src/web/index.html +14 -0
- package/src/web/index.ts +326 -0
- package/src/web/styles/main.css +180 -0
- package/src/web/types.ts +311 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger module for CRM system
|
|
3
|
+
*
|
|
4
|
+
* Provides structured logging with multiple log levels and formatters.
|
|
5
|
+
* Supports JSON output for production and pretty printing for development.
|
|
6
|
+
*/
|
|
7
|
+
const LOG_LEVELS = {
|
|
8
|
+
trace: 0,
|
|
9
|
+
debug: 1,
|
|
10
|
+
info: 2,
|
|
11
|
+
warn: 3,
|
|
12
|
+
error: 4,
|
|
13
|
+
fatal: 5,
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Structured logger with context support
|
|
17
|
+
*/
|
|
18
|
+
export class Logger {
|
|
19
|
+
level;
|
|
20
|
+
config;
|
|
21
|
+
defaultContext;
|
|
22
|
+
constructor(config) {
|
|
23
|
+
this.config = {
|
|
24
|
+
level: config.level ?? (process.env.NODE_ENV === 'production' ? 'info' : 'debug'),
|
|
25
|
+
version: config.version ?? '0.1.0',
|
|
26
|
+
env: config.env ?? process.env.NODE_ENV ?? 'development',
|
|
27
|
+
prettyPrint: config.prettyPrint ?? process.env.LOG_PRETTY === 'true',
|
|
28
|
+
includeStackTrace: config.includeStackTrace ?? true,
|
|
29
|
+
...config,
|
|
30
|
+
};
|
|
31
|
+
this.level = LOG_LEVELS[this.config.level];
|
|
32
|
+
this.defaultContext = {
|
|
33
|
+
service: this.config.service,
|
|
34
|
+
version: this.config.version,
|
|
35
|
+
env: this.config.env,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create a child logger with additional context
|
|
40
|
+
*/
|
|
41
|
+
child(context) {
|
|
42
|
+
return new ChildLogger(this, { ...this.defaultContext, ...context });
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Log at trace level (most verbose)
|
|
46
|
+
*/
|
|
47
|
+
trace(message, context) {
|
|
48
|
+
this.log('trace', message, context);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Log at debug level
|
|
52
|
+
*/
|
|
53
|
+
debug(message, context) {
|
|
54
|
+
this.log('debug', message, context);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Log at info level
|
|
58
|
+
*/
|
|
59
|
+
info(message, context) {
|
|
60
|
+
this.log('info', message, context);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Log at warn level
|
|
64
|
+
*/
|
|
65
|
+
warn(message, context) {
|
|
66
|
+
this.log('warn', message, context);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Log at error level
|
|
70
|
+
*/
|
|
71
|
+
error(message, error, context) {
|
|
72
|
+
const entry = this.createEntry('error', message, context);
|
|
73
|
+
if (error instanceof Error) {
|
|
74
|
+
entry.error = {
|
|
75
|
+
name: error.name,
|
|
76
|
+
message: error.message,
|
|
77
|
+
stack: this.config.includeStackTrace ? error.stack : undefined,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
else if (error !== undefined) {
|
|
81
|
+
entry.context = { ...entry.context, error: String(error) };
|
|
82
|
+
}
|
|
83
|
+
this.output(entry);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Log at fatal level (application should exit after this)
|
|
87
|
+
*/
|
|
88
|
+
fatal(message, error, context) {
|
|
89
|
+
const entry = this.createEntry('fatal', message, context);
|
|
90
|
+
if (error instanceof Error) {
|
|
91
|
+
entry.error = {
|
|
92
|
+
name: error.name,
|
|
93
|
+
message: error.message,
|
|
94
|
+
stack: this.config.includeStackTrace ? error.stack : undefined,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
else if (error !== undefined) {
|
|
98
|
+
entry.context = { ...entry.context, error: String(error) };
|
|
99
|
+
}
|
|
100
|
+
this.output(entry);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Log with timing information
|
|
104
|
+
*/
|
|
105
|
+
time(message, durationMs, context) {
|
|
106
|
+
const entry = this.createEntry('info', message, context);
|
|
107
|
+
entry.duration = durationMs;
|
|
108
|
+
this.output(entry);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Create a timer that logs duration when stopped
|
|
112
|
+
*/
|
|
113
|
+
startTimer(message, context) {
|
|
114
|
+
const start = performance.now();
|
|
115
|
+
return () => {
|
|
116
|
+
const duration = performance.now() - start;
|
|
117
|
+
this.time(message, duration, context);
|
|
118
|
+
return duration;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Add trace context to logs
|
|
123
|
+
*/
|
|
124
|
+
withTrace(traceId, spanId) {
|
|
125
|
+
const logger = new Logger(this.config);
|
|
126
|
+
logger.defaultContext = {
|
|
127
|
+
...this.defaultContext,
|
|
128
|
+
traceId,
|
|
129
|
+
spanId,
|
|
130
|
+
};
|
|
131
|
+
return logger;
|
|
132
|
+
}
|
|
133
|
+
log(level, message, context) {
|
|
134
|
+
if (LOG_LEVELS[level] < this.level) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const entry = this.createEntry(level, message, context);
|
|
138
|
+
this.output(entry);
|
|
139
|
+
}
|
|
140
|
+
createEntry(level, message, context) {
|
|
141
|
+
const entry = {
|
|
142
|
+
timestamp: new Date().toISOString(),
|
|
143
|
+
level,
|
|
144
|
+
message,
|
|
145
|
+
context: { ...this.defaultContext, ...context },
|
|
146
|
+
};
|
|
147
|
+
return entry;
|
|
148
|
+
}
|
|
149
|
+
output(entry) {
|
|
150
|
+
if (this.config.prettyPrint && this.config.env !== 'production') {
|
|
151
|
+
this.prettyOutput(entry);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
this.jsonOutput(entry);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
jsonOutput(entry) {
|
|
158
|
+
const output = JSON.stringify(entry);
|
|
159
|
+
if (entry.level === 'fatal' || entry.level === 'error') {
|
|
160
|
+
console.error(output);
|
|
161
|
+
}
|
|
162
|
+
else if (entry.level === 'warn') {
|
|
163
|
+
console.warn(output);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
console.log(output);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
prettyOutput(entry) {
|
|
170
|
+
const levelColors = {
|
|
171
|
+
trace: '\x1b[90m', // gray
|
|
172
|
+
debug: '\x1b[36m', // cyan
|
|
173
|
+
info: '\x1b[32m', // green
|
|
174
|
+
warn: '\x1b[33m', // yellow
|
|
175
|
+
error: '\x1b[31m', // red
|
|
176
|
+
fatal: '\x1b[35m', // magenta
|
|
177
|
+
};
|
|
178
|
+
const reset = '\x1b[0m';
|
|
179
|
+
const color = levelColors[entry.level];
|
|
180
|
+
const timestamp = entry.timestamp.split('T')[1]?.split('.')[0] ?? entry.timestamp;
|
|
181
|
+
const level = entry.level.toUpperCase().padEnd(5);
|
|
182
|
+
let output = `${color}[${timestamp}] ${level}${reset} ${entry.message}`;
|
|
183
|
+
if (entry.context && Object.keys(entry.context).length > 0) {
|
|
184
|
+
output += ` ${reset}\x1b[90m${JSON.stringify(entry.context)}\x1b[0m`;
|
|
185
|
+
}
|
|
186
|
+
if (entry.duration !== undefined) {
|
|
187
|
+
output += ` ${reset}\x1b[90m(${entry.duration.toFixed(2)}ms)\x1b[0m`;
|
|
188
|
+
}
|
|
189
|
+
if (entry.error) {
|
|
190
|
+
output += `\n \x1b[31m${entry.error.name}: ${entry.error.message}\x1b[0m`;
|
|
191
|
+
if (entry.error.stack && this.config.includeStackTrace) {
|
|
192
|
+
const stackLines = entry.error.stack.split('\n').slice(1, 5);
|
|
193
|
+
output += `\n \x1b[90m${stackLines.join('\n ')}\x1b[0m`;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (entry.level === 'fatal' || entry.level === 'error') {
|
|
197
|
+
console.error(output);
|
|
198
|
+
}
|
|
199
|
+
else if (entry.level === 'warn') {
|
|
200
|
+
console.warn(output);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
console.log(output);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Child logger with bound context
|
|
209
|
+
*/
|
|
210
|
+
class ChildLogger {
|
|
211
|
+
parent;
|
|
212
|
+
context;
|
|
213
|
+
constructor(parent, context) {
|
|
214
|
+
this.parent = parent;
|
|
215
|
+
this.context = context;
|
|
216
|
+
}
|
|
217
|
+
trace(message, additionalContext) {
|
|
218
|
+
this.parent.trace(message, { ...this.context, ...additionalContext });
|
|
219
|
+
}
|
|
220
|
+
debug(message, additionalContext) {
|
|
221
|
+
this.parent.debug(message, { ...this.context, ...additionalContext });
|
|
222
|
+
}
|
|
223
|
+
info(message, additionalContext) {
|
|
224
|
+
this.parent.info(message, { ...this.context, ...additionalContext });
|
|
225
|
+
}
|
|
226
|
+
warn(message, additionalContext) {
|
|
227
|
+
this.parent.warn(message, { ...this.context, ...additionalContext });
|
|
228
|
+
}
|
|
229
|
+
error(message, error, additionalContext) {
|
|
230
|
+
this.parent.error(message, error, { ...this.context, ...additionalContext });
|
|
231
|
+
}
|
|
232
|
+
fatal(message, error, additionalContext) {
|
|
233
|
+
this.parent.fatal(message, error, { ...this.context, ...additionalContext });
|
|
234
|
+
}
|
|
235
|
+
time(message, durationMs, additionalContext) {
|
|
236
|
+
const stop = this.parent.startTimer(message, { ...this.context, ...additionalContext });
|
|
237
|
+
// Already logged by startTimer
|
|
238
|
+
}
|
|
239
|
+
startTimer(message, additionalContext) {
|
|
240
|
+
return this.parent.startTimer(message, { ...this.context, ...additionalContext });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Default logger instance
|
|
245
|
+
*/
|
|
246
|
+
export const logger = new Logger({
|
|
247
|
+
service: 'crm',
|
|
248
|
+
version: '0.1.0',
|
|
249
|
+
});
|
|
250
|
+
/**
|
|
251
|
+
* Create a new logger instance
|
|
252
|
+
*/
|
|
253
|
+
export function createLogger(config) {
|
|
254
|
+
return new Logger(config);
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/telemetry/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics module for CRM system
|
|
3
|
+
*
|
|
4
|
+
* Provides a simple metrics collection system with counters, gauges, and histograms.
|
|
5
|
+
* Supports exporting metrics in Prometheus format.
|
|
6
|
+
*/
|
|
7
|
+
export type MetricType = 'counter' | 'gauge' | 'histogram';
|
|
8
|
+
export interface MetricLabel {
|
|
9
|
+
[key: string]: string | number;
|
|
10
|
+
}
|
|
11
|
+
export interface MetricValue {
|
|
12
|
+
value: number;
|
|
13
|
+
timestamp: number;
|
|
14
|
+
labels: MetricLabel;
|
|
15
|
+
}
|
|
16
|
+
export interface MetricDefinition {
|
|
17
|
+
name: string;
|
|
18
|
+
type: MetricType;
|
|
19
|
+
description: string;
|
|
20
|
+
unit?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface HistogramOptions {
|
|
23
|
+
buckets?: number[];
|
|
24
|
+
}
|
|
25
|
+
interface CounterMetric extends MetricDefinition {
|
|
26
|
+
type: 'counter';
|
|
27
|
+
values: MetricValue[];
|
|
28
|
+
}
|
|
29
|
+
interface GaugeMetric extends MetricDefinition {
|
|
30
|
+
type: 'gauge';
|
|
31
|
+
values: MetricValue[];
|
|
32
|
+
}
|
|
33
|
+
interface HistogramMetric extends MetricDefinition {
|
|
34
|
+
type: 'histogram';
|
|
35
|
+
values: {
|
|
36
|
+
sum: number;
|
|
37
|
+
count: number;
|
|
38
|
+
buckets: {
|
|
39
|
+
boundary: number;
|
|
40
|
+
count: number;
|
|
41
|
+
}[];
|
|
42
|
+
timestamp: number;
|
|
43
|
+
labels: MetricLabel;
|
|
44
|
+
}[];
|
|
45
|
+
options: HistogramOptions;
|
|
46
|
+
}
|
|
47
|
+
type Metric = CounterMetric | GaugeMetric | HistogramMetric;
|
|
48
|
+
/**
|
|
49
|
+
* Metrics registry for collecting and exporting metrics
|
|
50
|
+
*/
|
|
51
|
+
export declare class MetricsRegistry {
|
|
52
|
+
private readonly metrics;
|
|
53
|
+
private readonly prefix;
|
|
54
|
+
constructor(prefix?: string);
|
|
55
|
+
/**
|
|
56
|
+
* Register a counter metric
|
|
57
|
+
*/
|
|
58
|
+
registerCounter(name: string, description: string, unit?: string): void;
|
|
59
|
+
/**
|
|
60
|
+
* Register a gauge metric
|
|
61
|
+
*/
|
|
62
|
+
registerGauge(name: string, description: string, unit?: string): void;
|
|
63
|
+
/**
|
|
64
|
+
* Register a histogram metric
|
|
65
|
+
*/
|
|
66
|
+
registerHistogram(name: string, description: string, unit?: string, options?: HistogramOptions): void;
|
|
67
|
+
/**
|
|
68
|
+
* Increment a counter
|
|
69
|
+
*/
|
|
70
|
+
increment(name: string, value?: number, labels?: MetricLabel): void;
|
|
71
|
+
/**
|
|
72
|
+
* Decrement a counter (useful for error tracking)
|
|
73
|
+
*/
|
|
74
|
+
decrement(name: string, value?: number, labels?: MetricLabel): void;
|
|
75
|
+
/**
|
|
76
|
+
* Set a gauge value
|
|
77
|
+
*/
|
|
78
|
+
gauge(name: string, value: number, labels?: MetricLabel): void;
|
|
79
|
+
/**
|
|
80
|
+
* Observe a value for histogram
|
|
81
|
+
*/
|
|
82
|
+
observe(name: string, value: number, labels?: MetricLabel): void;
|
|
83
|
+
/**
|
|
84
|
+
* Create a timer that records duration in a histogram
|
|
85
|
+
*/
|
|
86
|
+
startTimer(name: string, labels?: MetricLabel): () => number;
|
|
87
|
+
/**
|
|
88
|
+
* Get all metrics
|
|
89
|
+
*/
|
|
90
|
+
getMetrics(): Metric[];
|
|
91
|
+
/**
|
|
92
|
+
* Export metrics in Prometheus text format
|
|
93
|
+
*/
|
|
94
|
+
exportPrometheus(): string;
|
|
95
|
+
/**
|
|
96
|
+
* Reset all metrics
|
|
97
|
+
*/
|
|
98
|
+
reset(): void;
|
|
99
|
+
/**
|
|
100
|
+
* Get metric by name
|
|
101
|
+
*/
|
|
102
|
+
getMetric(name: string): Metric | undefined;
|
|
103
|
+
private labelsMatch;
|
|
104
|
+
private formatLabels;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Default metrics registry
|
|
108
|
+
*/
|
|
109
|
+
export declare const metrics: MetricsRegistry;
|
|
110
|
+
/**
|
|
111
|
+
* Pre-registered CRM metrics
|
|
112
|
+
*/
|
|
113
|
+
export declare function initializeCrmMetrics(registry?: MetricsRegistry): void;
|
|
114
|
+
export {};
|
|
115
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics module for CRM system
|
|
3
|
+
*
|
|
4
|
+
* Provides a simple metrics collection system with counters, gauges, and histograms.
|
|
5
|
+
* Supports exporting metrics in Prometheus format.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Default histogram buckets (in seconds for latency)
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_BUCKETS = [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];
|
|
11
|
+
/**
|
|
12
|
+
* Metrics registry for collecting and exporting metrics
|
|
13
|
+
*/
|
|
14
|
+
export class MetricsRegistry {
|
|
15
|
+
metrics = new Map();
|
|
16
|
+
prefix;
|
|
17
|
+
constructor(prefix = 'crm_') {
|
|
18
|
+
this.prefix = prefix;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Register a counter metric
|
|
22
|
+
*/
|
|
23
|
+
registerCounter(name, description, unit) {
|
|
24
|
+
const metricName = this.prefix + name;
|
|
25
|
+
if (this.metrics.has(metricName)) {
|
|
26
|
+
throw new Error(`Metric ${metricName} already registered`);
|
|
27
|
+
}
|
|
28
|
+
this.metrics.set(metricName, {
|
|
29
|
+
name: metricName,
|
|
30
|
+
type: 'counter',
|
|
31
|
+
description,
|
|
32
|
+
unit,
|
|
33
|
+
values: [],
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Register a gauge metric
|
|
38
|
+
*/
|
|
39
|
+
registerGauge(name, description, unit) {
|
|
40
|
+
const metricName = this.prefix + name;
|
|
41
|
+
if (this.metrics.has(metricName)) {
|
|
42
|
+
throw new Error(`Metric ${metricName} already registered`);
|
|
43
|
+
}
|
|
44
|
+
this.metrics.set(metricName, {
|
|
45
|
+
name: metricName,
|
|
46
|
+
type: 'gauge',
|
|
47
|
+
description,
|
|
48
|
+
unit,
|
|
49
|
+
values: [],
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Register a histogram metric
|
|
54
|
+
*/
|
|
55
|
+
registerHistogram(name, description, unit, options) {
|
|
56
|
+
const metricName = this.prefix + name;
|
|
57
|
+
if (this.metrics.has(metricName)) {
|
|
58
|
+
throw new Error(`Metric ${metricName} already registered`);
|
|
59
|
+
}
|
|
60
|
+
this.metrics.set(metricName, {
|
|
61
|
+
name: metricName,
|
|
62
|
+
type: 'histogram',
|
|
63
|
+
description,
|
|
64
|
+
unit,
|
|
65
|
+
options: { buckets: options?.buckets ?? DEFAULT_BUCKETS },
|
|
66
|
+
values: [],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Increment a counter
|
|
71
|
+
*/
|
|
72
|
+
increment(name, value = 1, labels = {}) {
|
|
73
|
+
const metricName = this.prefix + name;
|
|
74
|
+
const metric = this.metrics.get(metricName);
|
|
75
|
+
if (!metric) {
|
|
76
|
+
throw new Error(`Metric ${metricName} not found`);
|
|
77
|
+
}
|
|
78
|
+
if (metric.type !== 'counter') {
|
|
79
|
+
throw new Error(`Metric ${metricName} is not a counter`);
|
|
80
|
+
}
|
|
81
|
+
const existingIndex = metric.values.findIndex(v => this.labelsMatch(v.labels, labels));
|
|
82
|
+
if (existingIndex >= 0) {
|
|
83
|
+
metric.values[existingIndex].value += value;
|
|
84
|
+
metric.values[existingIndex].timestamp = Date.now();
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
metric.values.push({
|
|
88
|
+
value,
|
|
89
|
+
timestamp: Date.now(),
|
|
90
|
+
labels,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Decrement a counter (useful for error tracking)
|
|
96
|
+
*/
|
|
97
|
+
decrement(name, value = 1, labels = {}) {
|
|
98
|
+
this.increment(name, -value, labels);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Set a gauge value
|
|
102
|
+
*/
|
|
103
|
+
gauge(name, value, labels = {}) {
|
|
104
|
+
const metricName = this.prefix + name;
|
|
105
|
+
const metric = this.metrics.get(metricName);
|
|
106
|
+
if (!metric) {
|
|
107
|
+
throw new Error(`Metric ${metricName} not found`);
|
|
108
|
+
}
|
|
109
|
+
if (metric.type !== 'gauge') {
|
|
110
|
+
throw new Error(`Metric ${metricName} is not a gauge`);
|
|
111
|
+
}
|
|
112
|
+
const existingIndex = metric.values.findIndex(v => this.labelsMatch(v.labels, labels));
|
|
113
|
+
if (existingIndex >= 0) {
|
|
114
|
+
metric.values[existingIndex].value = value;
|
|
115
|
+
metric.values[existingIndex].timestamp = Date.now();
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
metric.values.push({
|
|
119
|
+
value,
|
|
120
|
+
timestamp: Date.now(),
|
|
121
|
+
labels,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Observe a value for histogram
|
|
127
|
+
*/
|
|
128
|
+
observe(name, value, labels = {}) {
|
|
129
|
+
const metricName = this.prefix + name;
|
|
130
|
+
const metric = this.metrics.get(metricName);
|
|
131
|
+
if (!metric) {
|
|
132
|
+
throw new Error(`Metric ${metricName} not found`);
|
|
133
|
+
}
|
|
134
|
+
if (metric.type !== 'histogram') {
|
|
135
|
+
throw new Error(`Metric ${metricName} is not a histogram`);
|
|
136
|
+
}
|
|
137
|
+
const existingIndex = metric.values.findIndex(v => this.labelsMatch(v.labels, labels));
|
|
138
|
+
if (existingIndex >= 0) {
|
|
139
|
+
const existing = metric.values[existingIndex];
|
|
140
|
+
existing.sum += value;
|
|
141
|
+
existing.count += 1;
|
|
142
|
+
for (const bucket of existing.buckets) {
|
|
143
|
+
if (value <= bucket.boundary) {
|
|
144
|
+
bucket.count += 1;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
existing.timestamp = Date.now();
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
const buckets = metric.options.buckets ?? DEFAULT_BUCKETS;
|
|
151
|
+
metric.values.push({
|
|
152
|
+
sum: value,
|
|
153
|
+
count: 1,
|
|
154
|
+
buckets: buckets.map(boundary => ({
|
|
155
|
+
boundary,
|
|
156
|
+
count: value <= boundary ? 1 : 0,
|
|
157
|
+
})),
|
|
158
|
+
timestamp: Date.now(),
|
|
159
|
+
labels,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Create a timer that records duration in a histogram
|
|
165
|
+
*/
|
|
166
|
+
startTimer(name, labels = {}) {
|
|
167
|
+
const start = process.hrtime.bigint();
|
|
168
|
+
return () => {
|
|
169
|
+
const end = process.hrtime.bigint();
|
|
170
|
+
const durationSeconds = Number(end - start) / 1e9;
|
|
171
|
+
this.observe(name, durationSeconds, labels);
|
|
172
|
+
return durationSeconds;
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get all metrics
|
|
177
|
+
*/
|
|
178
|
+
getMetrics() {
|
|
179
|
+
return Array.from(this.metrics.values());
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Export metrics in Prometheus text format
|
|
183
|
+
*/
|
|
184
|
+
exportPrometheus() {
|
|
185
|
+
const lines = [];
|
|
186
|
+
for (const metric of this.metrics.values()) {
|
|
187
|
+
// Add help and type comments
|
|
188
|
+
lines.push(`# HELP ${metric.name} ${metric.description}`);
|
|
189
|
+
lines.push(`# TYPE ${metric.name} ${metric.type}`);
|
|
190
|
+
if (metric.type === 'counter' || metric.type === 'gauge') {
|
|
191
|
+
for (const value of metric.values) {
|
|
192
|
+
const labelStr = this.formatLabels(value.labels);
|
|
193
|
+
lines.push(`${metric.name}${labelStr} ${value.value}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else if (metric.type === 'histogram') {
|
|
197
|
+
for (const value of metric.values) {
|
|
198
|
+
const labelStr = this.formatLabels(value.labels);
|
|
199
|
+
// Bucket counts
|
|
200
|
+
for (const bucket of value.buckets) {
|
|
201
|
+
const bucketLabels = { ...value.labels, le: bucket.boundary.toString() };
|
|
202
|
+
const bucketLabelStr = this.formatLabels(bucketLabels);
|
|
203
|
+
lines.push(`${metric.name}_bucket${bucketLabelStr} ${bucket.count}`);
|
|
204
|
+
}
|
|
205
|
+
// +Inf bucket (same as count)
|
|
206
|
+
const infLabels = { ...value.labels, le: '+Inf' };
|
|
207
|
+
const infLabelStr = this.formatLabels(infLabels);
|
|
208
|
+
lines.push(`${metric.name}_bucket${infLabelStr} ${value.count}`);
|
|
209
|
+
// Sum and count
|
|
210
|
+
lines.push(`${metric.name}_sum${labelStr} ${value.sum}`);
|
|
211
|
+
lines.push(`${metric.name}_count${labelStr} ${value.count}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
lines.push(''); // Empty line between metrics
|
|
215
|
+
}
|
|
216
|
+
return lines.join('\n');
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Reset all metrics
|
|
220
|
+
*/
|
|
221
|
+
reset() {
|
|
222
|
+
for (const metric of this.metrics.values()) {
|
|
223
|
+
if (metric.type === 'histogram') {
|
|
224
|
+
metric.values = [];
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
metric.values = [];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get metric by name
|
|
233
|
+
*/
|
|
234
|
+
getMetric(name) {
|
|
235
|
+
return this.metrics.get(this.prefix + name);
|
|
236
|
+
}
|
|
237
|
+
labelsMatch(a, b) {
|
|
238
|
+
const keysA = Object.keys(a).sort();
|
|
239
|
+
const keysB = Object.keys(b).sort();
|
|
240
|
+
if (keysA.length !== keysB.length)
|
|
241
|
+
return false;
|
|
242
|
+
return keysA.every((key, i) => {
|
|
243
|
+
if (key !== keysB[i])
|
|
244
|
+
return false;
|
|
245
|
+
return a[key] === b[key];
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
formatLabels(labels) {
|
|
249
|
+
const entries = Object.entries(labels);
|
|
250
|
+
if (entries.length === 0)
|
|
251
|
+
return '';
|
|
252
|
+
const formatted = entries.map(([key, value]) => {
|
|
253
|
+
const escapedValue = String(value).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
254
|
+
return `${key}="${escapedValue}"`;
|
|
255
|
+
});
|
|
256
|
+
return `{${formatted.join(',')}}`;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Default metrics registry
|
|
261
|
+
*/
|
|
262
|
+
export const metrics = new MetricsRegistry('crm_');
|
|
263
|
+
/**
|
|
264
|
+
* Pre-registered CRM metrics
|
|
265
|
+
*/
|
|
266
|
+
export function initializeCrmMetrics(registry = metrics) {
|
|
267
|
+
// Contact metrics
|
|
268
|
+
registry.registerCounter('contacts_created_total', 'Total number of contacts created');
|
|
269
|
+
registry.registerCounter('contacts_updated_total', 'Total number of contacts updated');
|
|
270
|
+
registry.registerCounter('contacts_deleted_total', 'Total number of contacts deleted');
|
|
271
|
+
registry.registerGauge('contacts_active_count', 'Current number of active contacts');
|
|
272
|
+
// Deal metrics
|
|
273
|
+
registry.registerCounter('deals_created_total', 'Total number of deals created');
|
|
274
|
+
registry.registerCounter('deals_won_total', 'Total number of deals won');
|
|
275
|
+
registry.registerCounter('deals_lost_total', 'Total number of deals lost');
|
|
276
|
+
registry.registerGauge('deals_active_count', 'Current number of active deals');
|
|
277
|
+
registry.registerGauge('deals_pipeline_value', 'Total value of deals in pipeline', 'USD');
|
|
278
|
+
// Activity metrics
|
|
279
|
+
registry.registerCounter('activities_created_total', 'Total number of activities created');
|
|
280
|
+
registry.registerCounter('activities_completed_total', 'Total number of activities completed');
|
|
281
|
+
registry.registerGauge('activities_pending_count', 'Current number of pending activities');
|
|
282
|
+
// API metrics
|
|
283
|
+
registry.registerHistogram('api_request_duration_seconds', 'API request duration in seconds');
|
|
284
|
+
registry.registerCounter('api_requests_total', 'Total number of API requests');
|
|
285
|
+
registry.registerCounter('api_errors_total', 'Total number of API errors');
|
|
286
|
+
// Search metrics
|
|
287
|
+
registry.registerHistogram('search_duration_seconds', 'Search query duration in seconds');
|
|
288
|
+
registry.registerCounter('search_queries_total', 'Total number of search queries');
|
|
289
|
+
}
|
|
290
|
+
// Initialize default metrics
|
|
291
|
+
initializeCrmMetrics();
|
|
292
|
+
//# sourceMappingURL=metrics.js.map
|