Merge pull request 'Fitur untuk collect multiple agents' (#2) from dsutanto/Deep-Package-Inspection:main into main

Reviewed-on: rafif/Deep-Package-Inspection#2
This commit was merged in pull request #2.
This commit is contained in:
rafif committed 2026-07-10 16:49:24 +07:00
commit 75639d3c89
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 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)
@@ -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.
### 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
| 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 |
| Pihak A | `agent` | `UUID-AGENT-A` | Hanya data Pihak A |
| Pihak B | `agent` | `UUID-AGENT-B` | Hanya data Pihak B |
| 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 |
| POST | `/collect/all` | Trigger manual — kumpulkan semua agent |
| 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
- PROXY_PORT=4000
# 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_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 * * * *}
networks:
- backone-infra
+23 -1
View File
@@ -144,7 +144,29 @@ async function collectSpecificAgent(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 = {
collectAllAgents,
collectSpecificAgent
collectSpecificAgent,
collectSpecificAgents
};
+33 -2
View File
@@ -10,8 +10,10 @@
//
// Environment Variables:
// 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_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_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
* List all agent UUIDs yang sudah tersimpan di MongoDB
@@ -179,6 +204,11 @@ async function main() {
if (process.env.PROXY_COLLECT_MODE === 'agent') {
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)
app.listen(PORT, '0.0.0.0', () => {
@@ -187,7 +217,8 @@ async function main() {
console.log(` GET /status → scheduler + DB status`);
console.log(` GET /agents → list agent UUIDs in MongoDB`);
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)
+25 -13
View File
@@ -3,12 +3,14 @@
// Runs every 5 minutes, collecting data for all agents or a specific agent.
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
const COLLECT_MODE = process.env.PROXY_COLLECT_MODE || 'all';
const SPECIFIC_AGENT = process.env.PROXY_AGENT_UUID || null;
const CRON_SCHEDULE = process.env.PROXY_CRON_SCHEDULE || '*/5 * * * *';
// Mode: 'all' = collect all agents, 'agent' = collect one specific agent, 'agents' = collect multiple agents
const COLLECT_MODE = process.env.PROXY_COLLECT_MODE || 'all';
const SPECIFIC_AGENT = process.env.PROXY_AGENT_UUID || null;
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
// 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) {
console.log(`[Scheduler] Run #${runCount} - Mode: SPECIFIC AGENT (${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 {
console.log(`[Scheduler] Run #${runCount} - Mode: ALL AGENTS`);
result = await collectAllAgents();
@@ -69,7 +74,12 @@ async function runCollection() {
*/
function startScheduler() {
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)`);
// Validate cron expression
@@ -95,13 +105,15 @@ function startScheduler() {
*/
function getStatus() {
return {
is_running: isRunning,
run_count: runCount,
last_run_at: lastRunAt?.toISOString() ?? null,
collect_mode: COLLECT_MODE,
agent_uuid: SPECIFIC_AGENT,
cron_schedule: CRON_SCHEDULE,
last_result: lastRunResult,
is_running: isRunning,
run_count: runCount,
last_run_at: lastRunAt?.toISOString() ?? null,
collect_mode: COLLECT_MODE,
agent_uuid: SPECIFIC_AGENT,
agent_uuids: COLLECT_MODE === 'agents' ? SPECIFIC_AGENTS : [],
agent_delay_ms: AGENT_DELAY_MS,
cron_schedule: CRON_SCHEDULE,
last_result: lastRunResult,
};
}