obzervo-agent 1.0.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.
Files changed (2) hide show
  1. package/bin/index.js +147 -0
  2. package/package.json +32 -0
package/bin/index.js ADDED
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { Command } = require('commander');
4
+ const axios = require('axios');
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+
8
+ const program = new Command();
9
+
10
+ program
11
+ .name('obzervo')
12
+ .description('Obzervo Local CLI Observability and Monitoring Agent')
13
+ .version('1.0.0');
14
+
15
+ program
16
+ .command('monitor')
17
+ .description('Monitor a local or private HTTP endpoint and stream telemetry to Obzervo')
18
+ .option('-e, --endpointId <id>', 'Target endpoint ID in Obzervo')
19
+ .option('-t, --targetUrl <url>', 'Local target URL, for example http://localhost:3000/health')
20
+ .option('-k, --key <apiKey>', 'Obzervo API key, for example obz_live_...')
21
+ .option('-m, --method <httpMethod>', 'HTTP method (GET, POST, PUT, etc.)', 'GET')
22
+ .option('-c, --expectedStatus <status>', 'Expected HTTP status code', 200)
23
+ .option('-s, --serverUrl <serverUrl>', 'Obzervo API server URL', 'http://localhost:5000')
24
+ .option('-i, --interval <intervalMs>', 'Ping interval in milliseconds', 10000)
25
+ .action(async (options) => {
26
+ let { endpointId, targetUrl, key, method, expectedStatus, serverUrl, interval } = options;
27
+
28
+ const configPath = path.join(process.cwd(), 'obzervo.json');
29
+ if (fs.existsSync(configPath)) {
30
+ try {
31
+ const fileConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
32
+ endpointId = endpointId || fileConfig.endpointId;
33
+ targetUrl = targetUrl || fileConfig.targetUrl;
34
+ key = key || fileConfig.apiKey;
35
+ method = method || fileConfig.method || 'GET';
36
+ expectedStatus = expectedStatus || fileConfig.expectedStatus || 200;
37
+ serverUrl = serverUrl || fileConfig.serverUrl || 'http://localhost:5000';
38
+ interval = interval || fileConfig.interval || 10000;
39
+ console.log('[Obzervo Agent] Loaded local configuration from obzervo.json');
40
+ } catch (err) {
41
+ console.error('[Obzervo Agent Error] Failed to parse obzervo.json:', err.message);
42
+ }
43
+ }
44
+
45
+ if (!endpointId || !targetUrl || !key) {
46
+ console.error('\nMissing required parameters.');
47
+ console.error('Usage: obzervo monitor --endpointId <ID> --targetUrl <URL> --key <API_KEY>');
48
+ console.error('Or create an obzervo.json config file in the project directory.\n');
49
+ process.exit(1);
50
+ }
51
+
52
+ const targetExpectedStatus = Number(expectedStatus) || 200;
53
+ const targetMethod = (method || 'GET').toUpperCase();
54
+
55
+ console.log('\n======================================================');
56
+ console.log('Obzervo Local CLI Monitoring Agent Started');
57
+ console.log('======================================================');
58
+ console.log(` Target URL: ${targetUrl}`);
59
+ console.log(` Method: ${targetMethod}`);
60
+ console.log(` Expected Status: ${targetExpectedStatus}`);
61
+ console.log(` Endpoint ID: ${endpointId}`);
62
+ console.log(` API Server: ${serverUrl}`);
63
+ console.log(` Interval: Every ${Number(interval) / 1000}s`);
64
+ console.log('======================================================\n');
65
+
66
+ const runPingCycle = async () => {
67
+ const startTime = process.hrtime();
68
+ let statusCode = 0;
69
+ let latencyMs = 0;
70
+ let responseSize = 0;
71
+ let isSuccess = false;
72
+ let errorMessage = null;
73
+
74
+ try {
75
+ const response = await axios({
76
+ method: targetMethod,
77
+ url: targetUrl,
78
+ timeout: 5000,
79
+ validateStatus: () => true
80
+ });
81
+
82
+ const diff = process.hrtime(startTime);
83
+ latencyMs = parseFloat((diff[0] * 1000 + diff[1] / 1e6).toFixed(2));
84
+ statusCode = response.status;
85
+
86
+ const rawData = JSON.stringify(response.data || '');
87
+ responseSize = Buffer.byteLength(rawData, 'utf8');
88
+
89
+ isSuccess = statusCode === targetExpectedStatus;
90
+ if (!isSuccess) {
91
+ errorMessage = `HTTP Status ${statusCode} did not match expected status ${targetExpectedStatus}`;
92
+ }
93
+ } catch (err) {
94
+ const diff = process.hrtime(startTime);
95
+ latencyMs = parseFloat((diff[0] * 1000 + diff[1] / 1e6).toFixed(2));
96
+
97
+ if (err.response) {
98
+ statusCode = err.response.status;
99
+ errorMessage = `HTTP ${statusCode}: ${err.response.statusText}`;
100
+ } else if (err.code === 'ECONNABORTED') {
101
+ statusCode = 408;
102
+ errorMessage = 'Local HTTP request timeout after 5000ms';
103
+ } else {
104
+ statusCode = 0;
105
+ errorMessage = err.message || 'Connection refused or DNS failure';
106
+ }
107
+ isSuccess = false;
108
+ }
109
+
110
+
111
+ try {
112
+ await axios.post(
113
+ `${serverUrl}/api/v1/telemetry/push`,
114
+ {
115
+ endpointId,
116
+ statusCode,
117
+ latencyMs,
118
+ responseSize,
119
+ isSuccess,
120
+ errorMessage
121
+ },
122
+ {
123
+ headers: {
124
+ 'x-api-key': key,
125
+ 'Content-Type': 'application/json'
126
+ },
127
+ timeout: 5000
128
+ }
129
+ );
130
+
131
+ const timestamp = new Date().toLocaleTimeString();
132
+ if (isSuccess) {
133
+ console.log(`[${timestamp}] PING OK | ${statusCode} | ${latencyMs}ms | ${responseSize} B`);
134
+ } else {
135
+ console.log(`[${timestamp}] PING FAIL | ${statusCode} | ${latencyMs}ms | Error: ${errorMessage}`);
136
+ }
137
+ } catch (pushErr) {
138
+ const timestamp = new Date().toLocaleTimeString();
139
+ console.error(`[${timestamp}] Telemetry Push Failed:`, pushErr.response?.data?.message || pushErr.message);
140
+ }
141
+ };
142
+
143
+ await runPingCycle();
144
+ setInterval(runPingCycle, Number(interval));
145
+ });
146
+
147
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "obzervo-agent",
3
+ "version": "1.0.0",
4
+ "description": "Obzervo Local & VPC Microservice Monitoring CLI Agent",
5
+ "bin": {
6
+ "obzervo": "./bin/index.js",
7
+ "obzervo-agent": "./bin/index.js"
8
+ },
9
+ "main": "./bin/index.js",
10
+ "files": [
11
+ "bin/"
12
+ ],
13
+ "preferGlobal": true,
14
+ "scripts": {
15
+ "start": "node ./bin/index.js"
16
+ },
17
+ "keywords": [
18
+ "obzervo",
19
+ "monitoring",
20
+ "cli",
21
+ "observability",
22
+ "sre",
23
+ "telemetry",
24
+ "agent"
25
+ ],
26
+ "author": "Obzervo SRE Team",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "axios": "^1.6.8",
30
+ "commander": "^12.0.0"
31
+ }
32
+ }