{ "name": "📋 Monitoramento Local Sistema | Sem Slack", "nodes": [ { "parameters": { "rule": { "interval": [ { "field": "cronExpression", "value": "*/10 * * * *" } ] } }, "id": "cron-monitor-trigger", "name": "Trigger Monitor 10min", "type": "n8n-nodes-base.cron", "typeVersion": 1, "position": [240, 300] }, { "parameters": { "jsCode": "// Configurar serviços para monitoramento\nconst services = [\n {\n name: 'Krayin CRM',\n url: 'https://crm.memudecore.com.br',\n expected_content: 'Krayin',\n timeout: 10000,\n critical: true\n },\n {\n name: 'BookStack Docs',\n url: 'https://docs.memudecore.com.br',\n expected_content: 'BookStack',\n timeout: 10000,\n critical: true\n },\n {\n name: 'N8N Automation',\n url: 'http://n8n.memudecore.com.br',\n expected_content: 'n8n',\n timeout: 8000,\n critical: true\n },\n {\n name: 'Evolution API',\n url: 'https://evolution.memudecore.com.br/manager',\n expected_content: 'Evolution',\n timeout: 12000,\n critical: true\n },\n {\n name: 'Site Principal',\n url: 'https://memudecore.com.br',\n expected_content: 'MeMude',\n timeout: 10000,\n critical: false\n }\n];\n\nconst config = {\n services: services,\n total_services: services.length,\n timestamp: new Date().toISOString(),\n execution_id: Date.now().toString()\n};\n\nreturn config;" }, "id": "setup-monitor-config", "name": "Configurar Monitoramento", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [460, 300] }, { "parameters": { "fieldToSplitOut": "services", "options": {} }, "id": "split-services", "name": "Dividir Serviços", "type": "n8n-nodes-base.splitOut", "typeVersion": 1, "position": [680, 300] }, { "parameters": { "method": "GET", "url": "={{$node[\"Dividir Serviços\"].json[\"url\"]}}", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "User-Agent", "value": "N8N Health Monitor/1.0" } ] }, "options": { "timeout": "={{$node[\"Dividir Serviços\"].json[\"timeout\"]}}" } }, "id": "test-service", "name": "Testar Serviço", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4, "position": [900, 300], "continueOnFail": true }, { "parameters": { "jsCode": "// Processar resultado do teste\nconst serviceData = $node[\"Dividir Serviços\"].json;\nconst testResult = $node[\"Testar Serviço\"].json;\nconst error = $node[\"Testar Serviço\"].error;\n\nconst startTime = Date.now();\nlet status = 'UNKNOWN';\nlet statusColor = '🔘';\nlet responseTime = 0;\nlet errorMessage = null;\nlet statusCode = null;\n\nif (error) {\n // Erro na requisição\n status = 'OFFLINE';\n statusColor = '❌';\n errorMessage = error.message || 'Erro desconhecido';\n responseTime = 0;\n} else {\n // Requisição bem-sucedida\n statusCode = testResult.status || testResult.statusCode;\n const responseBody = typeof testResult === 'string' ? testResult : JSON.stringify(testResult);\n \n // Verificar código de status\n if (statusCode === 200 || statusCode === 302) {\n // Verificar conteúdo esperado\n if (serviceData.expected_content && responseBody) {\n const hasExpectedContent = responseBody.toLowerCase().includes(serviceData.expected_content.toLowerCase());\n \n if (hasExpectedContent) {\n status = 'ONLINE';\n statusColor = '✅';\n } else {\n status = 'DEGRADED';\n statusColor = '⚠️';\n errorMessage = `Conteúdo esperado '${serviceData.expected_content}' não encontrado`;\n }\n } else {\n status = 'ONLINE';\n statusColor = '✅';\n }\n } else {\n status = 'DEGRADED';\n statusColor = '⚠️';\n errorMessage = `Código HTTP inesperado: ${statusCode}`;\n }\n \n responseTime = Date.now() - startTime;\n}\n\nconst result = {\n service_name: serviceData.name,\n service_url: serviceData.url,\n status: status,\n status_color: statusColor,\n status_code: statusCode,\n response_time: responseTime,\n error_message: errorMessage,\n is_critical: serviceData.critical,\n timestamp: new Date().toISOString(),\n expected_content: serviceData.expected_content,\n has_error: status !== 'ONLINE'\n};\n\nreturn result;" }, "id": "process-test-result", "name": "Processar Resultado", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [1120, 300] }, { "parameters": { "jsCode": "// Aguardar 1 segundo entre testes para não sobrecarregar\nreturn new Promise(resolve => {\n setTimeout(() => {\n resolve({ waited: true, timestamp: new Date().toISOString() });\n }, 1000);\n});" }, "id": "wait-between-tests", "name": "Aguardar 1s", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [1340, 300] }, { "parameters": { "mode": "append", "fileName": "/tmp/health-monitor-log.txt", "fileContent": "={{JSON.stringify($node[\"Processar Resultado\"].json, null, 2)}}\n" }, "id": "save-individual-result", "name": "Salvar Resultado Individual", "type": "n8n-nodes-base.writeFile", "typeVersion": 1, "position": [1560, 300] } ], "connections": { "Trigger Monitor 10min": { "main": [ [ { "node": "Configurar Monitoramento", "type": "main", "index": 0 } ] ] }, "Configurar Monitoramento": { "main": [ [ { "node": "Dividir Serviços", "type": "main", "index": 0 } ] ] }, "Dividir Serviços": { "main": [ [ { "node": "Testar Serviço", "type": "main", "index": 0 } ] ] }, "Testar Serviço": { "main": [ [ { "node": "Processar Resultado", "type": "main", "index": 0 } ] ] }, "Processar Resultado": { "main": [ [ { "node": "Aguardar 1s", "type": "main", "index": 0 } ] ] }, "Aguardar 1s": { "main": [ [ { "node": "Salvar Resultado Individual", "type": "main", "index": 0 } ] ] } }, "active": false, "settings": {}, "versionId": "1", "meta": { "instanceId": "monitor-local" }, "id": "6", "tags": [ "Monitoramento", "Health Check", "Local", "Sem Slack", "Sistema" ] }