@jhits/plugin-telemetry 0.0.4 → 0.0.5
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/package.json +52 -51
- package/src/server.ts +141 -0
package/package.json
CHANGED
|
@@ -1,56 +1,57 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@jhits/plugin-telemetry",
|
|
3
|
+
"version": "0.0.5",
|
|
4
|
+
"description": "System logging and telemetry utilities for the JHITS ecosystem",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
7
14
|
},
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
".": {
|
|
12
|
-
"types": "./src/index.ts",
|
|
13
|
-
"default": "./src/index.ts"
|
|
14
|
-
},
|
|
15
|
-
"./server": {
|
|
16
|
-
"types": "./src/server.ts",
|
|
17
|
-
"default": "./src/server.ts"
|
|
18
|
-
},
|
|
19
|
-
"./api/route": {
|
|
20
|
-
"types": "./src/api/route.ts",
|
|
21
|
-
"default": "./src/api/route.ts"
|
|
22
|
-
},
|
|
23
|
-
"./api/handler": {
|
|
24
|
-
"types": "./src/api/handler.ts",
|
|
25
|
-
"default": "./src/api/handler.ts"
|
|
26
|
-
},
|
|
27
|
-
"./utils/logCleaner": {
|
|
28
|
-
"types": "./src/utils/logCleaner.ts",
|
|
29
|
-
"default": "./src/utils/logCleaner.ts"
|
|
30
|
-
}
|
|
15
|
+
"./server": {
|
|
16
|
+
"types": "./dist/server.d.ts",
|
|
17
|
+
"default": "./dist/server.js"
|
|
31
18
|
},
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
19
|
+
"./api/route": {
|
|
20
|
+
"types": "./dist/api/route.d.ts",
|
|
21
|
+
"default": "./dist/api/route.js"
|
|
35
22
|
},
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"react-dom": ">=18.0.0"
|
|
23
|
+
"./api/handler": {
|
|
24
|
+
"types": "./dist/api/handler.d.ts",
|
|
25
|
+
"default": "./dist/api/handler.js"
|
|
40
26
|
},
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
27
|
+
"./utils/logCleaner": {
|
|
28
|
+
"types": "./dist/utils/logCleaner.d.ts",
|
|
29
|
+
"default": "./dist/utils/logCleaner.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@jhits/plugin-core": "^0.0.2"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"next": ">=15.0.0",
|
|
37
|
+
"react": ">=18.0.0",
|
|
38
|
+
"react-dom": ">=18.0.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.2.3",
|
|
42
|
+
"@types/react": "^19.2.14",
|
|
43
|
+
"@types/react-dom": "^19.2.3",
|
|
44
|
+
"next": "16.1.6",
|
|
45
|
+
"react": "19.2.4",
|
|
46
|
+
"react-dom": "19.2.4",
|
|
47
|
+
"typescript": "^5.9.3"
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"dist",
|
|
51
|
+
"src",
|
|
52
|
+
"package.json"
|
|
53
|
+
],
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "tsc"
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/server.ts
CHANGED
|
@@ -5,6 +5,19 @@ import 'server-only';
|
|
|
5
5
|
* These exports should only be used in server-side code (API routes, server components)
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
// Type definition to avoid circular dependency
|
|
9
|
+
interface PluginRegistration {
|
|
10
|
+
name: string;
|
|
11
|
+
version: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
routes: Array<{ path: string; component: string }>;
|
|
14
|
+
apiHandlers: Array<{ method: string; path: string; handler: string }>;
|
|
15
|
+
cssFiles: string[];
|
|
16
|
+
setup?: () => Promise<void>;
|
|
17
|
+
dependencies?: string[];
|
|
18
|
+
config?: Record<string, any>;
|
|
19
|
+
}
|
|
20
|
+
|
|
8
21
|
import { NextRequest, NextResponse } from 'next/server';
|
|
9
22
|
import fs from 'fs/promises';
|
|
10
23
|
import path from 'path';
|
|
@@ -73,6 +86,134 @@ async function rotateLogIfNeeded(): Promise<void> {
|
|
|
73
86
|
}
|
|
74
87
|
}
|
|
75
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Main API handler for telemetry plugin
|
|
91
|
+
*/
|
|
92
|
+
export async function handleApi(
|
|
93
|
+
req: NextRequest,
|
|
94
|
+
path: string[],
|
|
95
|
+
config: any
|
|
96
|
+
): Promise<NextResponse> {
|
|
97
|
+
try {
|
|
98
|
+
const { searchParams } = new URL(req.url);
|
|
99
|
+
const action = path[0] || 'log';
|
|
100
|
+
|
|
101
|
+
switch (action) {
|
|
102
|
+
case 'log':
|
|
103
|
+
const data = await req.json();
|
|
104
|
+
const result = await telemetryHandler(data, {
|
|
105
|
+
userId: req.headers.get('x-user-id') || undefined,
|
|
106
|
+
sessionId: req.headers.get('x-session-id') || undefined
|
|
107
|
+
});
|
|
108
|
+
return NextResponse.json(result);
|
|
109
|
+
|
|
110
|
+
case 'logs':
|
|
111
|
+
return await getLogsHandler(req, path, config);
|
|
112
|
+
|
|
113
|
+
default:
|
|
114
|
+
return NextResponse.json({
|
|
115
|
+
success: false,
|
|
116
|
+
error: 'Unknown telemetry action'
|
|
117
|
+
}, { status: 404 });
|
|
118
|
+
}
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error('[Telemetry API] Error:', error);
|
|
121
|
+
return NextResponse.json({
|
|
122
|
+
success: false,
|
|
123
|
+
error: 'Internal server error'
|
|
124
|
+
}, { status: 500 });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Plugin registration for auto-configuration
|
|
130
|
+
*/
|
|
131
|
+
export async function registerPlugin(): Promise<PluginRegistration> {
|
|
132
|
+
return {
|
|
133
|
+
name: 'telemetry',
|
|
134
|
+
version: '0.0.1',
|
|
135
|
+
description: 'System telemetry and logging plugin',
|
|
136
|
+
routes: [
|
|
137
|
+
{
|
|
138
|
+
path: '/dashboard/telemetry',
|
|
139
|
+
component: 'TelemetryDashboard'
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
apiHandlers: [
|
|
143
|
+
{
|
|
144
|
+
method: 'POST',
|
|
145
|
+
path: '/log',
|
|
146
|
+
handler: 'telemetryHandler'
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
method: 'GET',
|
|
150
|
+
path: '/logs',
|
|
151
|
+
handler: 'getLogsHandler'
|
|
152
|
+
}
|
|
153
|
+
],
|
|
154
|
+
cssFiles: ['telemetry-styles.css'],
|
|
155
|
+
setup: async () => {
|
|
156
|
+
// Create logs directory
|
|
157
|
+
const { mkdir } = await import('fs/promises');
|
|
158
|
+
const { join } = await import('path');
|
|
159
|
+
try {
|
|
160
|
+
await mkdir(join(process.cwd(), 'logs'), { recursive: true });
|
|
161
|
+
} catch (error) {
|
|
162
|
+
// Directory might already exist
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
dependencies: [],
|
|
166
|
+
config: {
|
|
167
|
+
maxLogSize: 10 * 1024 * 1024, // 10MB
|
|
168
|
+
maxBatchSize: 100,
|
|
169
|
+
maxEntrySize: 100 * 1024 // 100KB
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* API handler for retrieving logs
|
|
176
|
+
*/
|
|
177
|
+
export async function getLogsHandler(
|
|
178
|
+
req: NextRequest,
|
|
179
|
+
path: string[],
|
|
180
|
+
config: any
|
|
181
|
+
): Promise<NextResponse> {
|
|
182
|
+
try {
|
|
183
|
+
const fs = await import('fs/promises');
|
|
184
|
+
const path = await import('path');
|
|
185
|
+
const LOG_FILE = path.join(process.cwd(), 'logs', 'jhits-system.log');
|
|
186
|
+
|
|
187
|
+
const { searchParams } = new URL(req.url);
|
|
188
|
+
const lines = parseInt(searchParams.get('lines') || '100');
|
|
189
|
+
const category = searchParams.get('category');
|
|
190
|
+
|
|
191
|
+
// Read log file
|
|
192
|
+
const logContent = await fs.readFile(LOG_FILE, 'utf8');
|
|
193
|
+
const logLines = logContent.split('\n').filter(line => line.trim());
|
|
194
|
+
|
|
195
|
+
// Filter by category if specified
|
|
196
|
+
const filteredLines = category
|
|
197
|
+
? logLines.filter(line => line.includes(`[${category}]`))
|
|
198
|
+
: logLines;
|
|
199
|
+
|
|
200
|
+
// Get last N lines
|
|
201
|
+
const recentLines = filteredLines.slice(-lines);
|
|
202
|
+
|
|
203
|
+
return NextResponse.json({
|
|
204
|
+
success: true,
|
|
205
|
+
logs: recentLines,
|
|
206
|
+
total: filteredLines.length
|
|
207
|
+
});
|
|
208
|
+
} catch (error) {
|
|
209
|
+
return NextResponse.json({
|
|
210
|
+
success: false,
|
|
211
|
+
error: 'Failed to read logs',
|
|
212
|
+
logs: []
|
|
213
|
+
}, { status: 500 });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
76
217
|
/**
|
|
77
218
|
* Format log entry as single-line JSON (or pretty-printed in debug mode)
|
|
78
219
|
* CRITICAL: Single-line format for easier grep/tailing, but pretty-printed if debug flag is on
|