@rudderjs/pulse 0.0.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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +107 -0
  3. package/boost/guidelines.md +33 -0
  4. package/dist/aggregators/cache.d.ts +11 -0
  5. package/dist/aggregators/cache.d.ts.map +1 -0
  6. package/dist/aggregators/cache.js +34 -0
  7. package/dist/aggregators/cache.js.map +1 -0
  8. package/dist/aggregators/exception.d.ts +11 -0
  9. package/dist/aggregators/exception.d.ts.map +1 -0
  10. package/dist/aggregators/exception.js +30 -0
  11. package/dist/aggregators/exception.js.map +1 -0
  12. package/dist/aggregators/query.d.ts +12 -0
  13. package/dist/aggregators/query.d.ts.map +1 -0
  14. package/dist/aggregators/query.js +39 -0
  15. package/dist/aggregators/query.js.map +1 -0
  16. package/dist/aggregators/queue.d.ts +12 -0
  17. package/dist/aggregators/queue.d.ts.map +1 -0
  18. package/dist/aggregators/queue.js +43 -0
  19. package/dist/aggregators/queue.js.map +1 -0
  20. package/dist/aggregators/request.d.ts +15 -0
  21. package/dist/aggregators/request.d.ts.map +1 -0
  22. package/dist/aggregators/request.js +46 -0
  23. package/dist/aggregators/request.js.map +1 -0
  24. package/dist/aggregators/server.d.ts +13 -0
  25. package/dist/aggregators/server.d.ts.map +1 -0
  26. package/dist/aggregators/server.js +35 -0
  27. package/dist/aggregators/server.js.map +1 -0
  28. package/dist/aggregators/user.d.ts +17 -0
  29. package/dist/aggregators/user.d.ts.map +1 -0
  30. package/dist/aggregators/user.js +48 -0
  31. package/dist/aggregators/user.js.map +1 -0
  32. package/dist/api/routes.d.ts +6 -0
  33. package/dist/api/routes.d.ts.map +1 -0
  34. package/dist/api/routes.js +167 -0
  35. package/dist/api/routes.js.map +1 -0
  36. package/dist/index.d.ts +37 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +143 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/storage.d.ts +28 -0
  41. package/dist/storage.d.ts.map +1 -0
  42. package/dist/storage.js +219 -0
  43. package/dist/storage.js.map +1 -0
  44. package/dist/types.d.ts +77 -0
  45. package/dist/types.d.ts.map +1 -0
  46. package/dist/types.js +19 -0
  47. package/dist/types.js.map +1 -0
  48. package/dist/ui/dashboard.d.ts +5 -0
  49. package/dist/ui/dashboard.d.ts.map +1 -0
  50. package/dist/ui/dashboard.js +234 -0
  51. package/dist/ui/dashboard.js.map +1 -0
  52. package/dist/ui/layout.d.ts +6 -0
  53. package/dist/ui/layout.d.ts.map +1 -0
  54. package/dist/ui/layout.js +54 -0
  55. package/dist/ui/layout.js.map +1 -0
  56. package/dist/utils.d.ts +6 -0
  57. package/dist/utils.d.ts.map +1 -0
  58. package/dist/utils.js +19 -0
  59. package/dist/utils.js.map +1 -0
  60. package/package.json +66 -0
@@ -0,0 +1,167 @@
1
+ import { dashboardPage } from '../ui/dashboard.js';
2
+ const PERIODS = {
3
+ '1h': 60 * 60 * 1000,
4
+ '6h': 6 * 60 * 60 * 1000,
5
+ '24h': 24 * 60 * 60 * 1000,
6
+ '7d': 7 * 24 * 60 * 60 * 1000,
7
+ };
8
+ function sinceFromPeriod(period) {
9
+ const ms = PERIODS[period] ?? PERIODS['1h'];
10
+ return new Date(Date.now() - ms);
11
+ }
12
+ /**
13
+ * Register all Pulse API routes on the router.
14
+ */
15
+ export async function registerRoutes(storage, config) {
16
+ const { router } = await import('@rudderjs/router');
17
+ const basePath = `/${config.path ?? 'pulse'}`;
18
+ const prefix = `${basePath}/api`;
19
+ const middleware = config.auth ? [authMiddleware(config)] : [];
20
+ // ── Dashboard UI ─────────────────────────────────────────
21
+ router.get(basePath, (_req, res) => {
22
+ res.header('Content-Type', 'text/html').send(dashboardPage(prefix));
23
+ }, middleware);
24
+ // ── Overview ─────────────────────────────────────────────
25
+ router.get(`${prefix}/overview`, async (req, res) => {
26
+ const since = sinceFromPeriod(req.query['period'] ?? '1h');
27
+ const aggregates = await storage.overview(since);
28
+ // Group by type and compute summary stats
29
+ const summary = {};
30
+ for (const agg of aggregates) {
31
+ if (!summary[agg.type]) {
32
+ summary[agg.type] = { count: 0, sum: 0, min: null, max: null, buckets: 0 };
33
+ }
34
+ const s = summary[agg.type];
35
+ s.count += agg.count;
36
+ s.sum += agg.sum;
37
+ s.buckets += 1;
38
+ if (agg.min !== null && (s.min === null || agg.min < s.min))
39
+ s.min = agg.min;
40
+ if (agg.max !== null && (s.max === null || agg.max > s.max))
41
+ s.max = agg.max;
42
+ }
43
+ // Compute averages
44
+ const metrics = {};
45
+ for (const [type, s] of Object.entries(summary)) {
46
+ metrics[type] = {
47
+ total: s.count,
48
+ avg: s.count > 0 ? Math.round((s.sum / s.count) * 100) / 100 : 0,
49
+ min: s.min,
50
+ max: s.max,
51
+ buckets: s.buckets,
52
+ };
53
+ }
54
+ res.json({ period: req.query['period'] ?? '1h', metrics });
55
+ }, middleware);
56
+ // ── Request metrics ──────────────────────────────────────
57
+ router.get(`${prefix}/requests`, async (req, res) => {
58
+ const since = sinceFromPeriod(req.query['period'] ?? '1h');
59
+ const counts = await storage.aggregates('request_count', since);
60
+ const durations = await storage.aggregates('request_duration', since);
61
+ res.json({
62
+ throughput: counts.map(bucketToJson),
63
+ duration: durations.map(a => ({
64
+ ...bucketToJson(a),
65
+ avg: a.count > 0 ? Math.round((a.sum / a.count) * 100) / 100 : 0,
66
+ })),
67
+ });
68
+ }, middleware);
69
+ // ── Slow requests ────────────────────────────────────────
70
+ router.get(`${prefix}/slow-requests`, async (req, res) => {
71
+ const entries = await storage.entries('slow_request', {
72
+ page: parseInt(req.query['page'] ?? '1', 10),
73
+ perPage: parseInt(req.query['per_page'] ?? '50', 10),
74
+ });
75
+ res.json({ data: entries });
76
+ }, middleware);
77
+ // ── Queue metrics ────────────────────────────────────────
78
+ router.get(`${prefix}/queues`, async (req, res) => {
79
+ const since = sinceFromPeriod(req.query['period'] ?? '1h');
80
+ const throughput = await storage.aggregates('queue_throughput', since);
81
+ const waitTimes = await storage.aggregates('queue_wait_time', since);
82
+ res.json({
83
+ throughput: throughput.map(bucketToJson),
84
+ wait_time: waitTimes.map(a => ({
85
+ ...bucketToJson(a),
86
+ avg: a.count > 0 ? Math.round((a.sum / a.count) * 100) / 100 : 0,
87
+ })),
88
+ });
89
+ }, middleware);
90
+ // ── Slow queries ─────────────────────────────────────────
91
+ router.get(`${prefix}/slow-queries`, async (req, res) => {
92
+ const entries = await storage.entries('slow_query', {
93
+ page: parseInt(req.query['page'] ?? '1', 10),
94
+ perPage: parseInt(req.query['per_page'] ?? '50', 10),
95
+ });
96
+ res.json({ data: entries });
97
+ }, middleware);
98
+ // ── Exceptions ───────────────────────────────────────────
99
+ router.get(`${prefix}/exceptions`, async (req, res) => {
100
+ const since = sinceFromPeriod(req.query['period'] ?? '1h');
101
+ const aggregates = await storage.aggregates('exceptions', since);
102
+ const entries = await storage.entries('exception', {
103
+ page: parseInt(req.query['page'] ?? '1', 10),
104
+ perPage: parseInt(req.query['per_page'] ?? '20', 10),
105
+ });
106
+ res.json({
107
+ over_time: aggregates.map(bucketToJson),
108
+ recent: entries,
109
+ });
110
+ }, middleware);
111
+ // ── Cache ────────────────────────────────────────────────
112
+ router.get(`${prefix}/cache`, async (req, res) => {
113
+ const since = sinceFromPeriod(req.query['period'] ?? '1h');
114
+ const hits = await storage.aggregates('cache_hits', since);
115
+ const misses = await storage.aggregates('cache_misses', since);
116
+ const totalHits = hits.reduce((s, a) => s + a.count, 0);
117
+ const totalMisses = misses.reduce((s, a) => s + a.count, 0);
118
+ const total = totalHits + totalMisses;
119
+ const hitRate = total > 0 ? Math.round((totalHits / total) * 10000) / 100 : 0;
120
+ res.json({
121
+ hit_rate: hitRate,
122
+ total_hits: totalHits,
123
+ total_misses: totalMisses,
124
+ hits: hits.map(bucketToJson),
125
+ misses: misses.map(bucketToJson),
126
+ });
127
+ }, middleware);
128
+ // ── Active users ─────────────────────────────────────────
129
+ router.get(`${prefix}/users`, async (req, res) => {
130
+ const since = sinceFromPeriod(req.query['period'] ?? '1h');
131
+ const aggregates = await storage.aggregates('active_users', since);
132
+ res.json({ data: aggregates.map(bucketToJson) });
133
+ }, middleware);
134
+ // ── Server stats ─────────────────────────────────────────
135
+ router.get(`${prefix}/servers`, async (req, res) => {
136
+ const since = sinceFromPeriod(req.query['period'] ?? '1h');
137
+ const cpu = await storage.aggregates('server_cpu', since);
138
+ const memory = await storage.aggregates('server_memory', since);
139
+ res.json({
140
+ cpu: cpu.map(a => ({ ...bucketToJson(a), avg: a.count > 0 ? Math.round((a.sum / a.count) * 100) / 100 : 0 })),
141
+ memory: memory.map(a => ({ ...bucketToJson(a), avg: a.count > 0 ? Math.round((a.sum / a.count) * 100) / 100 : 0 })),
142
+ });
143
+ }, middleware);
144
+ }
145
+ function bucketToJson(agg) {
146
+ return {
147
+ bucket: agg.bucket.toISOString(),
148
+ type: agg.type,
149
+ key: agg.key,
150
+ count: agg.count,
151
+ min: agg.min,
152
+ max: agg.max,
153
+ };
154
+ }
155
+ function authMiddleware(config) {
156
+ return async (req, res, next) => {
157
+ if (config.auth) {
158
+ const allowed = await config.auth(req);
159
+ if (!allowed) {
160
+ res.status(403).json({ message: 'Unauthorized.' });
161
+ return;
162
+ }
163
+ }
164
+ return next();
165
+ };
166
+ }
167
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { ServiceProvider, type Application } from '@rudderjs/core';
2
+ import { type PulseConfig, type PulseStorage, type PulseAggregate, type PulseEntry, type MetricType, type EntryType, type Aggregator, type EntryListOptions } from './types.js';
3
+ export type { PulseConfig, PulseStorage, PulseAggregate, PulseEntry, MetricType, EntryType, Aggregator, EntryListOptions };
4
+ export { MemoryStorage, SqliteStorage } from './storage.js';
5
+ export { RequestAggregator } from './aggregators/request.js';
6
+ export { QueueAggregator } from './aggregators/queue.js';
7
+ export { CacheAggregator } from './aggregators/cache.js';
8
+ export { ExceptionAggregator } from './aggregators/exception.js';
9
+ export { UserAggregator } from './aggregators/user.js';
10
+ export { QueryAggregator } from './aggregators/query.js';
11
+ export { ServerAggregator } from './aggregators/server.js';
12
+ export declare class PulseRegistry {
13
+ private static storage;
14
+ static set(storage: PulseStorage): void;
15
+ static get(): PulseStorage | null;
16
+ /** @internal — clears the registered storage. Used for testing. */
17
+ static reset(): void;
18
+ }
19
+ export declare class Pulse {
20
+ private static store;
21
+ static record(type: MetricType, value: number, key?: string | null): void | Promise<void>;
22
+ static aggregates(type: MetricType, since: Date, key?: string | null): PulseAggregate[] | Promise<PulseAggregate[]>;
23
+ static entries(type: EntryType, options?: EntryListOptions): PulseEntry[] | Promise<PulseEntry[]>;
24
+ static overview(since: Date): PulseAggregate[] | Promise<PulseAggregate[]>;
25
+ }
26
+ /**
27
+ * Returns a PulseServiceProvider class configured for the given config.
28
+ *
29
+ * Tracks request throughput/duration, queue metrics, cache hit rates,
30
+ * exception counts, active users, slow queries, and server resource usage.
31
+ *
32
+ * Usage in bootstrap/providers.ts:
33
+ * import { pulse } from '@rudderjs/pulse'
34
+ * export default [..., pulse(configs.pulse), ...]
35
+ */
36
+ export declare function pulse(config?: PulseConfig): new (app: Application) => ServiceProvider;
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAUlE,OAAO,EAEL,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EACzE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,gBAAgB,EACxE,MAAM,YAAY,CAAA;AAInB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAA;AAC1H,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAI1D,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,OAAO,CAA4B;IAElD,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IACvC,MAAM,CAAC,GAAG,IAAI,YAAY,GAAG,IAAI;IACjC,mEAAmE;IACnE,MAAM,CAAC,KAAK,IAAI,IAAI;CACrB;AAID,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAC,KAAK;IAMpB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzF,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAInH,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAIjG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,cAAc,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAG3E;AAID;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CAAC,MAAM,GAAE,WAAgB,GAAG,KAAK,GAAG,EAAE,WAAW,KAAK,eAAe,CAuFzF"}
package/dist/index.js ADDED
@@ -0,0 +1,143 @@
1
+ import { ServiceProvider } from '@rudderjs/core';
2
+ import { MemoryStorage, SqliteStorage } from './storage.js';
3
+ import { RequestAggregator } from './aggregators/request.js';
4
+ import { QueueAggregator } from './aggregators/queue.js';
5
+ import { CacheAggregator } from './aggregators/cache.js';
6
+ import { ExceptionAggregator } from './aggregators/exception.js';
7
+ import { UserAggregator } from './aggregators/user.js';
8
+ import { QueryAggregator } from './aggregators/query.js';
9
+ import { ServerAggregator } from './aggregators/server.js';
10
+ import { registerRoutes } from './api/routes.js';
11
+ import { defaultConfig, } from './types.js';
12
+ export { MemoryStorage, SqliteStorage } from './storage.js';
13
+ export { RequestAggregator } from './aggregators/request.js';
14
+ export { QueueAggregator } from './aggregators/queue.js';
15
+ export { CacheAggregator } from './aggregators/cache.js';
16
+ export { ExceptionAggregator } from './aggregators/exception.js';
17
+ export { UserAggregator } from './aggregators/user.js';
18
+ export { QueryAggregator } from './aggregators/query.js';
19
+ export { ServerAggregator } from './aggregators/server.js';
20
+ // ─── Pulse Registry ────────────────────────────────────────
21
+ export class PulseRegistry {
22
+ static storage = null;
23
+ static set(storage) { this.storage = storage; }
24
+ static get() { return this.storage; }
25
+ /** @internal — clears the registered storage. Used for testing. */
26
+ static reset() { this.storage = null; }
27
+ }
28
+ // ─── Pulse Facade ──────────────────────────────────────────
29
+ export class Pulse {
30
+ static store() {
31
+ const s = PulseRegistry.get();
32
+ if (!s)
33
+ throw new Error('[RudderJS Pulse] No storage registered. Add pulse() to providers.');
34
+ return s;
35
+ }
36
+ static record(type, value, key) {
37
+ return this.store().record(type, value, key);
38
+ }
39
+ static aggregates(type, since, key) {
40
+ return this.store().aggregates(type, since, key);
41
+ }
42
+ static entries(type, options) {
43
+ return this.store().entries(type, options);
44
+ }
45
+ static overview(since) {
46
+ return this.store().overview(since);
47
+ }
48
+ }
49
+ // ─── Service Provider Factory ──────────────────────────────
50
+ /**
51
+ * Returns a PulseServiceProvider class configured for the given config.
52
+ *
53
+ * Tracks request throughput/duration, queue metrics, cache hit rates,
54
+ * exception counts, active users, slow queries, and server resource usage.
55
+ *
56
+ * Usage in bootstrap/providers.ts:
57
+ * import { pulse } from '@rudderjs/pulse'
58
+ * export default [..., pulse(configs.pulse), ...]
59
+ */
60
+ export function pulse(config = {}) {
61
+ const resolved = {
62
+ enabled: config.enabled ?? defaultConfig.enabled,
63
+ path: config.path ?? defaultConfig.path,
64
+ storage: config.storage ?? defaultConfig.storage,
65
+ sqlitePath: config.sqlitePath ?? defaultConfig.sqlitePath,
66
+ pruneAfterHours: config.pruneAfterHours ?? defaultConfig.pruneAfterHours,
67
+ slowRequestThreshold: config.slowRequestThreshold ?? defaultConfig.slowRequestThreshold,
68
+ slowQueryThreshold: config.slowQueryThreshold ?? defaultConfig.slowQueryThreshold,
69
+ recordRequests: config.recordRequests ?? defaultConfig.recordRequests,
70
+ recordQueues: config.recordQueues ?? defaultConfig.recordQueues,
71
+ recordCache: config.recordCache ?? defaultConfig.recordCache,
72
+ recordExceptions: config.recordExceptions ?? defaultConfig.recordExceptions,
73
+ recordUsers: config.recordUsers ?? defaultConfig.recordUsers,
74
+ recordServers: config.recordServers ?? defaultConfig.recordServers,
75
+ serverStatsIntervalMs: config.serverStatsIntervalMs ?? defaultConfig.serverStatsIntervalMs,
76
+ auth: config.auth ?? defaultConfig.auth,
77
+ };
78
+ class PulseServiceProvider extends ServiceProvider {
79
+ register() {
80
+ this.publishes({
81
+ from: new URL('../../boost/guidelines.md', import.meta.url).pathname,
82
+ to: 'boost',
83
+ tag: 'pulse-boost',
84
+ });
85
+ }
86
+ async boot() {
87
+ if (!resolved.enabled)
88
+ return;
89
+ // ── Create storage ────────────────────────────────────
90
+ let storage;
91
+ if (resolved.storage === 'sqlite') {
92
+ storage = new SqliteStorage(resolved.sqlitePath);
93
+ }
94
+ else {
95
+ storage = new MemoryStorage();
96
+ }
97
+ PulseRegistry.set(storage);
98
+ this.app.instance('pulse', storage);
99
+ // ── Auto-prune ────────────────────────────────────────
100
+ const pruneHours = resolved.pruneAfterHours;
101
+ if (pruneHours > 0) {
102
+ const interval = Math.min(pruneHours * 60 * 60 * 1000, 3_600_000);
103
+ const timer = setInterval(() => {
104
+ const cutoff = new Date(Date.now() - pruneHours * 60 * 60 * 1000);
105
+ storage.pruneOlderThan(cutoff);
106
+ }, interval);
107
+ timer.unref();
108
+ }
109
+ // ── Register aggregators ──────────────────────────────
110
+ const requestAgg = new RequestAggregator(storage, resolved);
111
+ const userAgg = new UserAggregator(storage);
112
+ const aggregators = [];
113
+ if (resolved.recordQueues)
114
+ aggregators.push(new QueueAggregator(storage));
115
+ if (resolved.recordCache)
116
+ aggregators.push(new CacheAggregator(storage));
117
+ if (resolved.recordExceptions)
118
+ aggregators.push(new ExceptionAggregator(storage));
119
+ if (resolved.recordServers)
120
+ aggregators.push(new ServerAggregator(storage, resolved.serverStatsIntervalMs));
121
+ // Query aggregator for slow queries
122
+ aggregators.push(new QueryAggregator(storage, resolved));
123
+ for (const agg of aggregators) {
124
+ await agg.register();
125
+ }
126
+ // ── Register middleware ───────────────────────────────
127
+ try {
128
+ const { router } = await import('@rudderjs/router');
129
+ if (resolved.recordRequests)
130
+ router.use(requestAgg.middleware());
131
+ if (resolved.recordUsers)
132
+ router.use(userAgg.middleware());
133
+ }
134
+ catch {
135
+ // @rudderjs/router not available
136
+ }
137
+ // ── Register API routes ───────────────────────────────
138
+ await registerRoutes(storage, resolved);
139
+ }
140
+ }
141
+ return PulseServiceProvider;
142
+ }
143
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { PulseAggregate, PulseEntry, PulseStorage, MetricType, EntryType, EntryListOptions } from './types.js';
2
+ export declare class MemoryStorage implements PulseStorage {
3
+ private readonly aggregates_;
4
+ private readonly entries_;
5
+ private readonly maxEntries;
6
+ constructor(maxEntries?: number);
7
+ record(type: MetricType, value: number, key?: string | null): void;
8
+ storeEntry(type: EntryType, content: Record<string, unknown>): void;
9
+ aggregates(type: MetricType, since: Date, key?: string | null): PulseAggregate[];
10
+ entries(type: EntryType, options?: EntryListOptions): PulseEntry[];
11
+ overview(since: Date): PulseAggregate[];
12
+ pruneOlderThan(date: Date): void;
13
+ }
14
+ export declare class SqliteStorage implements PulseStorage {
15
+ private readonly dbPath;
16
+ private db;
17
+ constructor(dbPath: string);
18
+ private getDb;
19
+ private migrate;
20
+ record(type: MetricType, value: number, key?: string | null): void;
21
+ storeEntry(type: EntryType, content: Record<string, unknown>): void;
22
+ aggregates(type: MetricType, since: Date, key?: string | null): PulseAggregate[];
23
+ entries(type: EntryType, options?: EntryListOptions): PulseEntry[];
24
+ overview(since: Date): PulseAggregate[];
25
+ pruneOlderThan(date: Date): void;
26
+ private aggFromRow;
27
+ }
28
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EAAE,UAAU,EAAE,YAAY,EACxC,UAAU,EAAE,SAAS,EAAE,gBAAgB,EACxC,MAAM,YAAY,CAAA;AAiBnB,qBAAa,aAAc,YAAW,YAAY;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyC;IACrE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;gBAEvB,UAAU,SAAM;IAI5B,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAyBlE,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAYnE,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,EAAE;IAYhF,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,UAAU,EAAE;IAYlE,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,cAAc,EAAE;IAUvC,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;CAQjC;AAID,qBAAa,aAAc,YAAW,YAAY;IAGpC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,EAAE,CAAiD;gBAE9B,MAAM,EAAE,MAAM;IAE3C,OAAO,CAAC,KAAK;IAcb,OAAO,CAAC,OAAO;IA0Bf,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAuBlE,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMnE,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,EAAE;IAYhF,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,UAAU,EAAE;IAyBlE,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,cAAc,EAAE;IAOvC,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAOhC,OAAO,CAAC,UAAU;CAanB"}
@@ -0,0 +1,219 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ // ─── Helpers ───────────────────────────────────────────────
3
+ /** Round a date down to the start of its 1-minute bucket */
4
+ function bucketStart(date) {
5
+ const d = new Date(date);
6
+ d.setSeconds(0, 0);
7
+ return d;
8
+ }
9
+ function bucketKey(bucket, type, key) {
10
+ return `${bucket.toISOString()}|${type}|${key ?? ''}`;
11
+ }
12
+ // ─── Memory Storage ────────────────────────────────────────
13
+ export class MemoryStorage {
14
+ aggregates_ = new Map();
15
+ entries_ = [];
16
+ maxEntries;
17
+ constructor(maxEntries = 500) {
18
+ this.maxEntries = maxEntries;
19
+ }
20
+ record(type, value, key) {
21
+ const bucket = bucketStart(new Date());
22
+ const bk = bucketKey(bucket, type, key ?? null);
23
+ const existing = this.aggregates_.get(bk);
24
+ if (existing) {
25
+ existing.count += 1;
26
+ existing.sum += value;
27
+ if (existing.min === null || value < existing.min)
28
+ existing.min = value;
29
+ if (existing.max === null || value > existing.max)
30
+ existing.max = value;
31
+ }
32
+ else {
33
+ this.aggregates_.set(bk, {
34
+ id: randomUUID(),
35
+ bucket,
36
+ type,
37
+ key: key ?? null,
38
+ count: 1,
39
+ sum: value,
40
+ min: value,
41
+ max: value,
42
+ createdAt: new Date(),
43
+ });
44
+ }
45
+ }
46
+ storeEntry(type, content) {
47
+ this.entries_.unshift({
48
+ id: randomUUID(),
49
+ type,
50
+ content,
51
+ createdAt: new Date(),
52
+ });
53
+ if (this.entries_.length > this.maxEntries) {
54
+ this.entries_.length = this.maxEntries;
55
+ }
56
+ }
57
+ aggregates(type, since, key) {
58
+ const sinceTs = since.getTime();
59
+ const result = [];
60
+ for (const agg of this.aggregates_.values()) {
61
+ if (agg.type !== type)
62
+ continue;
63
+ if (agg.bucket.getTime() < sinceTs)
64
+ continue;
65
+ if (key !== undefined && key !== null && agg.key !== key)
66
+ continue;
67
+ result.push(agg);
68
+ }
69
+ return result.sort((a, b) => a.bucket.getTime() - b.bucket.getTime());
70
+ }
71
+ entries(type, options) {
72
+ let result = this.entries_.filter(e => e.type === type);
73
+ if (options?.search) {
74
+ const s = options.search.toLowerCase();
75
+ result = result.filter(e => JSON.stringify(e.content).toLowerCase().includes(s));
76
+ }
77
+ const page = options?.page ?? 1;
78
+ const perPage = options?.perPage ?? 50;
79
+ const start = (page - 1) * perPage;
80
+ return result.slice(start, start + perPage);
81
+ }
82
+ overview(since) {
83
+ const sinceTs = since.getTime();
84
+ const result = [];
85
+ for (const agg of this.aggregates_.values()) {
86
+ if (agg.bucket.getTime() < sinceTs)
87
+ continue;
88
+ result.push(agg);
89
+ }
90
+ return result.sort((a, b) => a.bucket.getTime() - b.bucket.getTime());
91
+ }
92
+ pruneOlderThan(date) {
93
+ const ts = date.getTime();
94
+ for (const [key, agg] of this.aggregates_.entries()) {
95
+ if (agg.bucket.getTime() < ts)
96
+ this.aggregates_.delete(key);
97
+ }
98
+ const idx = this.entries_.findIndex(e => e.createdAt.getTime() < ts);
99
+ if (idx !== -1)
100
+ this.entries_.length = idx;
101
+ }
102
+ }
103
+ // ─── SQLite Storage ────────────────────────────────────────
104
+ export class SqliteStorage {
105
+ dbPath;
106
+ db = null;
107
+ constructor(dbPath) {
108
+ this.dbPath = dbPath;
109
+ }
110
+ getDb() {
111
+ if (!this.db) {
112
+ const Database = globalThis.__betterSqlite3;
113
+ if (!Database) {
114
+ throw new Error('[RudderJS Pulse] better-sqlite3 is required for SQLite storage. Run: pnpm add better-sqlite3');
115
+ }
116
+ this.db = new Database(this.dbPath);
117
+ this.migrate();
118
+ }
119
+ return this.db;
120
+ }
121
+ migrate() {
122
+ this.db.exec(`
123
+ CREATE TABLE IF NOT EXISTS pulse_aggregates (
124
+ id TEXT PRIMARY KEY,
125
+ bucket TEXT NOT NULL,
126
+ type TEXT NOT NULL,
127
+ key TEXT,
128
+ count INTEGER NOT NULL DEFAULT 0,
129
+ sum REAL NOT NULL DEFAULT 0,
130
+ min REAL,
131
+ max REAL,
132
+ created_at TEXT NOT NULL,
133
+ UNIQUE(bucket, type, key)
134
+ );
135
+ CREATE INDEX IF NOT EXISTS idx_pulse_agg_type_bucket ON pulse_aggregates(type, bucket);
136
+
137
+ CREATE TABLE IF NOT EXISTS pulse_entries (
138
+ id TEXT PRIMARY KEY,
139
+ type TEXT NOT NULL,
140
+ content TEXT NOT NULL,
141
+ created_at TEXT NOT NULL
142
+ );
143
+ CREATE INDEX IF NOT EXISTS idx_pulse_entry_type_created ON pulse_entries(type, created_at);
144
+ `);
145
+ }
146
+ record(type, value, key) {
147
+ const bucket = bucketStart(new Date()).toISOString();
148
+ const k = key ?? null;
149
+ const existing = this.getDb().prepare('SELECT id, count, sum, min, max FROM pulse_aggregates WHERE bucket = ? AND type = ? AND key IS ?').get(bucket, type, k);
150
+ if (existing) {
151
+ this.getDb().prepare(`UPDATE pulse_aggregates SET count = count + 1, sum = sum + ?,
152
+ min = CASE WHEN min IS NULL OR ? < min THEN ? ELSE min END,
153
+ max = CASE WHEN max IS NULL OR ? > max THEN ? ELSE max END
154
+ WHERE id = ?`).run(value, value, value, value, value, existing.id);
155
+ }
156
+ else {
157
+ this.getDb().prepare(`INSERT INTO pulse_aggregates (id, bucket, type, key, count, sum, min, max, created_at)
158
+ VALUES (?, ?, ?, ?, 1, ?, ?, ?, ?)`).run(randomUUID(), bucket, type, k, value, value, value, new Date().toISOString());
159
+ }
160
+ }
161
+ storeEntry(type, content) {
162
+ this.getDb().prepare('INSERT INTO pulse_entries (id, type, content, created_at) VALUES (?, ?, ?, ?)').run(randomUUID(), type, JSON.stringify(content), new Date().toISOString());
163
+ }
164
+ aggregates(type, since, key) {
165
+ let sql = 'SELECT * FROM pulse_aggregates WHERE type = ? AND bucket >= ?';
166
+ const params = [type, since.toISOString()];
167
+ if (key !== undefined && key !== null) {
168
+ sql += ' AND key = ?';
169
+ params.push(key);
170
+ }
171
+ sql += ' ORDER BY bucket ASC';
172
+ const rows = this.getDb().prepare(sql).all(...params);
173
+ return rows.map(r => this.aggFromRow(r));
174
+ }
175
+ entries(type, options) {
176
+ const page = options?.page ?? 1;
177
+ const perPage = options?.perPage ?? 50;
178
+ const offset = (page - 1) * perPage;
179
+ let sql = 'SELECT * FROM pulse_entries WHERE type = ?';
180
+ const params = [type];
181
+ if (options?.search) {
182
+ sql += ' AND content LIKE ?';
183
+ params.push(`%${options.search}%`);
184
+ }
185
+ sql += ' ORDER BY created_at DESC LIMIT ? OFFSET ?';
186
+ params.push(perPage, offset);
187
+ const rows = this.getDb().prepare(sql).all(...params);
188
+ return rows.map(r => ({
189
+ id: r['id'],
190
+ type: r['type'],
191
+ content: JSON.parse(r['content']),
192
+ createdAt: new Date(r['created_at']),
193
+ }));
194
+ }
195
+ overview(since) {
196
+ const rows = this.getDb().prepare('SELECT * FROM pulse_aggregates WHERE bucket >= ? ORDER BY bucket ASC').all(since.toISOString());
197
+ return rows.map(r => this.aggFromRow(r));
198
+ }
199
+ pruneOlderThan(date) {
200
+ const iso = date.toISOString();
201
+ const db = this.getDb();
202
+ db.prepare('DELETE FROM pulse_aggregates WHERE bucket < ?').run(iso);
203
+ db.prepare('DELETE FROM pulse_entries WHERE created_at < ?').run(iso);
204
+ }
205
+ aggFromRow(r) {
206
+ return {
207
+ id: r['id'],
208
+ bucket: new Date(r['bucket']),
209
+ type: r['type'],
210
+ key: r['key'] || null,
211
+ count: r['count'],
212
+ sum: r['sum'],
213
+ min: r['min'] ?? null,
214
+ max: r['max'] ?? null,
215
+ createdAt: new Date(r['created_at']),
216
+ };
217
+ }
218
+ }
219
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}