Add features to collect multiple agents, specify in env Var

This commit is contained in:
proitlab committed 2026-07-10 16:45:46 +07:00
1 parent 1ced34230a
commit 997aba0b12
5 files changed
+100 -19

No files matched your search

+15 -2
View File
@@ -41,7 +41,7 @@ Produk BackOne oleh **PT. Data Bisnis Solusi** — Dashboard monitoring jaringan
## 📡 Proxy — 2 Mode Pengambilan Data ## 📡 Proxy — 2 Mode Pengambilan Data
Proxy server (port 4000) mendukung 2 mode yang dikontrol via environment variable: Proxy server (port 4000) mendukung 3 mode yang dikontrol via environment variable:
### Mode 1: Semua Network Agent (Admin BackOne) ### Mode 1: Semua Network Agent (Admin BackOne)
@@ -62,14 +62,26 @@ PROXY_AGENT_UUID=2F-TF-1D-GK # UUID Network Agent CPI Balaraja
Proxy hanya mengambil data dari **satu Network Agent spesifik** (berdasarkan UUID). Data agent lain tidak pernah masuk ke database. Cocok untuk deployment di sisi client (Pihak A, B, C) agar mereka hanya punya data milik mereka sendiri. Proxy hanya mengambil data dari **satu Network Agent spesifik** (berdasarkan UUID). Data agent lain tidak pernah masuk ke database. Cocok untuk deployment di sisi client (Pihak A, B, C) agar mereka hanya punya data milik mereka sendiri.
### Mode 3: Beberapa Agent Spesifik (Multi-Agent)
```env
# .env.local
PROXY_COLLECT_MODE=agents
PROXY_AGENT_UUIDS=UUID-AGENT-A,UUID-AGENT-B,UUID-AGENT-C # comma-separated list
PROXY_AGENT_DELAY_MS=5000 # delay antar agent (default: 5000ms)
```
Proxy mengambil data dari **beberapa Network Agent spesifik** (berdasarkan daftar UUID yang dipisahkan koma). Data agent di luar daftar tidak pernah masuk ke database. Delay antar agent dapat diatur dengan `PROXY_AGENT_DELAY_MS` untuk menghindari rate-limit.
### Contoh Multi-Tenant Deployment ### Contoh Multi-Tenant Deployment
| Deployment | PROXY_COLLECT_MODE | PROXY_AGENT_UUID | Data yang disimpan | | Deployment | PROXY_COLLECT_MODE | PROXY_AGENT_UUID / PROXY_AGENT_UUIDS | Data yang disimpan |
|---|---|---|---| |---|---|---|---|
| Kantor BackOne (Admin) | `all` | _(kosong)_ | Semua agent | | Kantor BackOne (Admin) | `all` | _(kosong)_ | Semua agent |
| Pihak A | `agent` | `UUID-AGENT-A` | Hanya data Pihak A | | Pihak A | `agent` | `UUID-AGENT-A` | Hanya data Pihak A |
| Pihak B | `agent` | `UUID-AGENT-B` | Hanya data Pihak B | | Pihak B | `agent` | `UUID-AGENT-B` | Hanya data Pihak B |
| Pihak C | `agent` | `UUID-AGENT-C` | Hanya data Pihak C | | Pihak C | `agent` | `UUID-AGENT-C` | Hanya data Pihak C |
| Multi-Client | `agents` | `UUID-A,UUID-B` | Data Pihak A dan B |
--- ---
@@ -82,6 +94,7 @@ Proxy hanya mengambil data dari **satu Network Agent spesifik** (berdasarkan UUI
| GET | `/agents` | List semua agent UUID yang ada di MongoDB | | GET | `/agents` | List semua agent UUID yang ada di MongoDB |
| POST | `/collect/all` | Trigger manual — kumpulkan semua agent | | POST | `/collect/all` | Trigger manual — kumpulkan semua agent |
| POST | `/collect/:uuid` | Trigger manual — kumpulkan agent spesifik | | POST | `/collect/:uuid` | Trigger manual — kumpulkan agent spesifik |
| POST | `/collect/agents` | Trigger manual — kumpulkan multiple agents (body: `{"uuids": [...], "delay_ms": 5000}`) |
--- ---
+4 -1
View File
@@ -53,9 +53,12 @@ services:
- MONGODB_URI=mongodb://mongodb:27017/backone_dpi - MONGODB_URI=mongodb://mongodb:27017/backone_dpi
- PROXY_PORT=4000 - PROXY_PORT=4000
# Mode 1: kumpulkan SEMUA agent (default) # Mode 1: kumpulkan SEMUA agent (default)
# Ubah ke PROXY_COLLECT_MODE=agent dan isi PROXY_AGENT_UUID untuk mode spesifik # Ubah ke PROXY_COLLECT_MODE=agent dan isi PROXY_AGENT_UUID untuk mode spesifik (1 agent)
# Ubah ke PROXY_COLLECT_MODE=agents dan isi PROXY_AGENT_UUIDS untuk mode multi-agent
- PROXY_COLLECT_MODE=${PROXY_COLLECT_MODE:-all} - PROXY_COLLECT_MODE=${PROXY_COLLECT_MODE:-all}
- PROXY_AGENT_UUID=${PROXY_AGENT_UUID:-} - PROXY_AGENT_UUID=${PROXY_AGENT_UUID:-}
- PROXY_AGENT_UUIDS=${PROXY_AGENT_UUIDS:-}
- PROXY_AGENT_DELAY_MS=${PROXY_AGENT_DELAY_MS:-5000}
- PROXY_CRON_SCHEDULE=${PROXY_CRON_SCHEDULE:-*/5 * * * *} - PROXY_CRON_SCHEDULE=${PROXY_CRON_SCHEDULE:-*/5 * * * *}
networks: networks:
- backone-infra - backone-infra
+23 -1
View File
@@ -144,7 +144,29 @@ async function collectSpecificAgent(agentUuid) {
return { success: result.success, mode: 'specific', agent_uuid: agentUuid }; return { success: result.success, mode: 'specific', agent_uuid: agentUuid };
} }
async function collectSpecificAgents(agentUuids, delayMs = 5000) {
const timestamp = new Date();
const timeString = timestamp.toLocaleString('id-ID', { timeZone: 'Asia/Jakarta' }) + ' WIB';
console.log(`[Collector] === MODE: SPECIFIC AGENTS [${agentUuids.join(', ')}] === Started at ${timeString}`);
const results = [];
for (let i = 0; i < agentUuids.length; i++) {
if (i > 0) {
console.log(`[Collector] Waiting ${delayMs}ms before next agent...`);
await new Promise(resolve => setTimeout(resolve, delayMs));
}
const result = await collectForAgent(agentUuids[i], timestamp);
results.push(result);
}
const successful = results.filter(r => r.success).length;
console.log(`[Collector] === SPECIFIC AGENTS DONE === ${successful}/${agentUuids.length} successful`);
await pruneOldData().catch(err => console.error('[Collector] [Retention] error:', err.message));
return { success: true, mode: 'specific_agents', agents_count: agentUuids.length, successful, results };
}
module.exports = { module.exports = {
collectAllAgents, collectAllAgents,
collectSpecificAgent collectSpecificAgent,
collectSpecificAgents
}; };
+33 -2
View File
@@ -10,8 +10,10 @@
// //
// Environment Variables: // Environment Variables:
// MONGODB_URI - MongoDB connection string (default: localhost:27017) // MONGODB_URI - MongoDB connection string (default: localhost:27017)
// PROXY_COLLECT_MODE - 'all' (default) | 'agent' // PROXY_COLLECT_MODE - 'all' (default) | 'agent' | 'agents'
// PROXY_AGENT_UUID - Required if PROXY_COLLECT_MODE=agent // PROXY_AGENT_UUID - Required if PROXY_COLLECT_MODE=agent
// PROXY_AGENT_UUIDS - Comma-separated list of agent UUIDs, required if PROXY_COLLECT_MODE=agents
// PROXY_AGENT_DELAY_MS - Delay between agent collections in ms (default: 5000)
// PROXY_CRON_SCHEDULE - Default: '*/5 * * * *' (setiap 5 menit) // PROXY_CRON_SCHEDULE - Default: '*/5 * * * *' (setiap 5 menit)
// PROXY_PORT - Port untuk REST API (default: 4000) // PROXY_PORT - Port untuk REST API (default: 4000)
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
@@ -131,6 +133,29 @@ app.post('/collect/:agentUuid', async (req, res) => {
} }
}); });
/**
* POST /collect/agents
* Manual trigger — collect multiple specific agents
* Body: { "uuids": ["uuid1", "uuid2", ...], "delay_ms": 5000 }
*/
app.post('/collect/agents', async (req, res) => {
if (mongoose.connection.readyState !== 1) {
return res.status(503).json({ ok: false, error: 'MongoDB not connected. Cannot collect.' });
}
const { uuids, delay_ms } = req.body;
if (!uuids || !Array.isArray(uuids) || uuids.length === 0) {
return res.status(400).json({ ok: false, error: 'Body must include "uuids" as a non-empty array of agent UUIDs.' });
}
const { collectSpecificAgents } = require('./collector');
console.log(`[Proxy API] Manual trigger: collect agents ${uuids.join(', ')}`);
try {
const result = await collectSpecificAgents(uuids, delay_ms || 5000);
res.json({ ok: result.success, ...result });
} catch (err) {
res.status(500).json({ ok: false, error: err.message });
}
});
/** /**
* GET /agents * GET /agents
* List all agent UUIDs yang sudah tersimpan di MongoDB * List all agent UUIDs yang sudah tersimpan di MongoDB
@@ -179,6 +204,11 @@ async function main() {
if (process.env.PROXY_COLLECT_MODE === 'agent') { if (process.env.PROXY_COLLECT_MODE === 'agent') {
console.log(`[Proxy] Agent UUID: ${process.env.PROXY_AGENT_UUID || '(not set!)'}`); console.log(`[Proxy] Agent UUID: ${process.env.PROXY_AGENT_UUID || '(not set!)'}`);
} }
if (process.env.PROXY_COLLECT_MODE === 'agents') {
const agents = (process.env.PROXY_AGENT_UUIDS || '').split(',').map(s => s.trim()).filter(Boolean);
console.log(`[Proxy] Agent UUIDs: ${agents.length > 0 ? agents.join(', ') : '(not set!)'}`);
console.log(`[Proxy] Agent delay: ${parseInt(process.env.PROXY_AGENT_DELAY_MS || '5000')}ms`);
}
// 1. Start REST API server FIRST (so /health is always available) // 1. Start REST API server FIRST (so /health is always available)
app.listen(PORT, '0.0.0.0', () => { app.listen(PORT, '0.0.0.0', () => {
@@ -187,7 +217,8 @@ async function main() {
console.log(` GET /status → scheduler + DB status`); console.log(` GET /status → scheduler + DB status`);
console.log(` GET /agents → list agent UUIDs in MongoDB`); console.log(` GET /agents → list agent UUIDs in MongoDB`);
console.log(` POST /collect/all → trigger manual collect all`); console.log(` POST /collect/all → trigger manual collect all`);
console.log(` POST /collect/:agentUuid → trigger manual collect specific\n`); console.log(` POST /collect/:agentUuid → trigger manual collect specific`);
console.log(` POST /collect/agents → trigger manual collect multiple\n`);
}); });
// 2. Connect to MongoDB (retry in background) // 2. Connect to MongoDB (retry in background)
+25 -13
View File
@@ -3,12 +3,14 @@
// Runs every 5 minutes, collecting data for all agents or a specific agent. // Runs every 5 minutes, collecting data for all agents or a specific agent.
const cron = require('node-cron'); const cron = require('node-cron');
const { collectAllAgents, collectSpecificAgent } = require('./collector'); const { collectAllAgents, collectSpecificAgent, collectSpecificAgents } = require('./collector');
// Mode: 'all' = collect all agents, 'agent' = collect specific agent // Mode: 'all' = collect all agents, 'agent' = collect one specific agent, 'agents' = collect multiple agents
const COLLECT_MODE = process.env.PROXY_COLLECT_MODE || 'all'; const COLLECT_MODE = process.env.PROXY_COLLECT_MODE || 'all';
const SPECIFIC_AGENT = process.env.PROXY_AGENT_UUID || null; const SPECIFIC_AGENT = process.env.PROXY_AGENT_UUID || null;
const CRON_SCHEDULE = process.env.PROXY_CRON_SCHEDULE || '*/5 * * * *'; const SPECIFIC_AGENTS = (process.env.PROXY_AGENT_UUIDS || '').split(',').map(s => s.trim()).filter(Boolean);
const AGENT_DELAY_MS = parseInt(process.env.PROXY_AGENT_DELAY_MS || '5000');
const CRON_SCHEDULE = process.env.PROXY_CRON_SCHEDULE || '*/5 * * * *';
// Capacity logging is an expensive full-scan aggregation. Run it at most once per // Capacity logging is an expensive full-scan aggregation. Run it at most once per
// interval (default 24h) instead of every collection cycle to reduce CPU/DB load. // interval (default 24h) instead of every collection cycle to reduce CPU/DB load.
@@ -39,6 +41,9 @@ async function runCollection() {
if (COLLECT_MODE === 'agent' && SPECIFIC_AGENT) { if (COLLECT_MODE === 'agent' && SPECIFIC_AGENT) {
console.log(`[Scheduler] Run #${runCount} - Mode: SPECIFIC AGENT (${SPECIFIC_AGENT})`); console.log(`[Scheduler] Run #${runCount} - Mode: SPECIFIC AGENT (${SPECIFIC_AGENT})`);
result = await collectSpecificAgent(SPECIFIC_AGENT); result = await collectSpecificAgent(SPECIFIC_AGENT);
} else if (COLLECT_MODE === 'agents' && SPECIFIC_AGENTS.length > 0) {
console.log(`[Scheduler] Run #${runCount} - Mode: SPECIFIC AGENTS (${SPECIFIC_AGENTS.join(', ')})`);
result = await collectSpecificAgents(SPECIFIC_AGENTS, AGENT_DELAY_MS);
} else { } else {
console.log(`[Scheduler] Run #${runCount} - Mode: ALL AGENTS`); console.log(`[Scheduler] Run #${runCount} - Mode: ALL AGENTS`);
result = await collectAllAgents(); result = await collectAllAgents();
@@ -69,7 +74,12 @@ async function runCollection() {
*/ */
function startScheduler() { function startScheduler() {
console.log(`[Scheduler] Starting proxy data collector`); console.log(`[Scheduler] Starting proxy data collector`);
console.log(`[Scheduler] Mode : ${COLLECT_MODE === 'agent' ? 'SPECIFIC AGENT (' + SPECIFIC_AGENT + ')' : 'ALL AGENTS'}`); const modeLabel = COLLECT_MODE === 'agent'
? `SPECIFIC AGENT (${SPECIFIC_AGENT})`
: COLLECT_MODE === 'agents'
? `SPECIFIC AGENTS (${SPECIFIC_AGENTS.join(', ')})`
: 'ALL AGENTS';
console.log(`[Scheduler] Mode : ${modeLabel}`);
console.log(`[Scheduler] Schedule : ${CRON_SCHEDULE} (every 5 minutes by default)`); console.log(`[Scheduler] Schedule : ${CRON_SCHEDULE} (every 5 minutes by default)`);
// Validate cron expression // Validate cron expression
@@ -95,13 +105,15 @@ function startScheduler() {
*/ */
function getStatus() { function getStatus() {
return { return {
is_running: isRunning, is_running: isRunning,
run_count: runCount, run_count: runCount,
last_run_at: lastRunAt?.toISOString() ?? null, last_run_at: lastRunAt?.toISOString() ?? null,
collect_mode: COLLECT_MODE, collect_mode: COLLECT_MODE,
agent_uuid: SPECIFIC_AGENT, agent_uuid: SPECIFIC_AGENT,
cron_schedule: CRON_SCHEDULE, agent_uuids: COLLECT_MODE === 'agents' ? SPECIFIC_AGENTS : [],
last_result: lastRunResult, agent_delay_ms: AGENT_DELAY_MS,
cron_schedule: CRON_SCHEDULE,
last_result: lastRunResult,
}; };
} }