{% extends "base.html" %} {% block title %}Monitoring uptime - Admin{% endblock %} {% block extra_css %} {% endblock %} {% block content %}

Monitoring uptime

Dostepnosc portalu nordabiznes.pl z perspektywy uzytkownikow zewnetrznych

Ostatnia aktualizacja
{{ now.strftime('%H:%M:%S') if now is defined else '--:--:--' }}
{% if not data.has_data %}

Monitoring nie jest jeszcze skonfigurowany

Aby uruchomic monitoring, wykonaj ponizsza konfiguracje:

  1. Zaloz konto na uptimerobot.com (darmowy plan)
  2. Dodaj monitor: HTTPS, URL https://nordabiznes.pl/health, interwal 5 min
  3. Skopiuj Main API Key z ustawien konta
  4. Dodaj do .env: UPTIMEROBOT_API_KEY=twoj_klucz
  5. Dodaj cron jobs na serwerze:
    */5 * * * * cd /var/www/nordabiznes && ... (health logger)
    0 * * * * cd /var/www/nordabiznes && ... (UptimeRobot sync)
{% else %}
{% if data.current_status == 'up' %} Portal dziala poprawnie {% elif data.current_status == 'down' %} Portal niedostepny! {% else %} Status nieznany {% endif %}
{% if data.last_checked %} Ostatnie sprawdzenie: {{ data.last_checked }} {% if data.last_response_time %} | Czas odpowiedzi: {{ data.last_response_time }}ms{% endif %} {% endif %} | Monitor: {{ data.monitor.name }} ({{ data.monitor.url }})
{% for period, label in [('24h', 'Ostatnie 24h'), ('7d', 'Ostatnie 7 dni'), ('30d', 'Ostatnie 30 dni'), ('90d', 'Ostatnie 90 dni')] %}
{{ label }}
{% if data.uptime[period].percent is not none %} {% set pct = data.uptime[period].percent %}
{{ '%.2f' % pct }}%
{{ data.uptime[period].down_checks }} awarii / {{ data.uptime[period].total_checks }} sprawdzen
{% else %}
--
Brak danych
{% endif %}
{% endfor %}
Czas odpowiedzi {% if data.avg_response_time %} (sredni: {{ data.avg_response_time }}ms) {% endif %}
Incydenty ({{ data.incidents|length }})
{% if data.incidents %}
{% for inc in data.incidents %} {% endfor %}
Data Czas trwania Przyczyna Notatki
{{ inc.started_at }} {% if inc.ended_at %}
do {{ inc.ended_at }}{% endif %}
{{ inc.duration_human }}
{% else %}

Brak zarejestrowanych incydentow

{% endif %}
Wzorce awarii
{% if data.incidents %}

Awarie wg godziny

Awarie wg dnia tygodnia

{% else %}

Brak danych do analizy wzorcow

{% endif %}
Raport miesieczny: {{ data.monthly_report.month }}
{{ '%.3f' % data.monthly_report.uptime_pct }}%
Uptime SLA
{{ data.monthly_report.total_downtime_human }}
Laczny przestoj
{{ data.monthly_report.incidents_count }}
Liczba incydentow
{{ data.monthly_report.longest_incident }}
Najdluzszy incydent
Trend vs {{ data.monthly_report.prev_month }}: {% if data.monthly_report.trend == 'better' %}Lepiej {% elif data.monthly_report.trend == 'worse' %}Gorzej {% else %}Bez zmian{% endif %} (poprzednio: {{ data.monthly_report.prev_downtime_human }} przestoju, {{ data.monthly_report.prev_incidents_count }} incydentow)
{% for level, limits in data.sla_context.items() %} = level|float and (loop.last or data.monthly_report.uptime_pct < data.sla_context.keys()|list|sort|reverse|first|float if not loop.first else true) %}class="sla-current"{% endif %}> {% endfor %}
Poziom SLA Max przestoj / miesiac Max przestoj / rok Twoj status
{{ level }}% {{ limits.max_downtime_month }} {{ limits.max_downtime_year }} {% if data.monthly_report.uptime_pct >= level|float %} Spelnia {% else %} Nie spelnia {% endif %}
{% endif %} {% endblock %} {% block head_extra %} {% endblock %} {% block extra_js %} {% if data.has_data %} // Dane z backendu var responseTimesData = {{ data.response_times | tojson }}; var hourData = {{ data.patterns.by_hour | tojson }}; var dowData = {{ data.patterns.by_dow | tojson }}; // Response time chart var rtCtx = document.getElementById('responseTimeChart'); var rtChart = null; function renderResponseTimeChart(days) { if (rtChart) rtChart.destroy(); var cutoff = new Date(); cutoff.setDate(cutoff.getDate() - days); var filtered = responseTimesData.filter(function(d) { return new Date(d.time) >= cutoff; }); var labels = filtered.map(function(d) { return d.time; }); var values = filtered.map(function(d) { return d.ms; }); rtChart = new Chart(rtCtx, { type: 'line', data: { labels: labels, datasets: [{ label: 'Response time (ms)', data: values, borderColor: '#3b82f6', backgroundColor: 'rgba(59, 130, 246, 0.1)', fill: true, tension: 0.3, pointRadius: days <= 1 ? 3 : (days <= 7 ? 2 : 0), borderWidth: 2 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { x: { display: true, ticks: { maxTicksLimit: 12, font: { size: 10 } } }, y: { beginAtZero: true, title: { display: true, text: 'ms' } } } } }); } function changeChartPeriod(days) { document.querySelectorAll('.chart-btn').forEach(function(b) { b.classList.toggle('active', parseInt(b.dataset.days) === days); }); renderResponseTimeChart(days); } // Patterns charts if (document.getElementById('hourChart')) { new Chart(document.getElementById('hourChart'), { type: 'bar', data: { labels: Array.from({length: 24}, function(_, i) { return i + ':00'; }), datasets: [{ data: hourData, backgroundColor: 'rgba(239, 68, 68, 0.6)', borderColor: '#ef4444', borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true, ticks: { stepSize: 1 } }, x: { ticks: { font: { size: 9 } } } } } }); } if (document.getElementById('dowChart')) { new Chart(document.getElementById('dowChart'), { type: 'bar', data: { labels: ['Pon', 'Wt', 'Sr', 'Czw', 'Pt', 'Sob', 'Nie'], datasets: [{ data: dowData, backgroundColor: 'rgba(245, 158, 11, 0.6)', borderColor: '#f59e0b', borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true, ticks: { stepSize: 1 } } } } }); } // Init renderResponseTimeChart(1); // CSRF token var csrfToken = '{{ csrf_token() }}'; // Aktualizacja incydentow function updateIncident(selectEl) { var id = selectEl.dataset.incidentId; var cause = selectEl.value; fetch('/admin/api/uptime/incident/' + id + '/notes', { method: 'POST', headers: {'Content-Type': 'application/json', 'X-CSRFToken': csrfToken}, body: JSON.stringify({cause: cause}) }); } function updateIncidentNotes(inputEl) { var id = inputEl.dataset.incidentId; var notes = inputEl.value; fetch('/admin/api/uptime/incident/' + id + '/notes', { method: 'POST', headers: {'Content-Type': 'application/json', 'X-CSRFToken': csrfToken}, body: JSON.stringify({notes: notes}) }); } // Auto-refresh co 5 min setInterval(function() { fetch('/admin/api/uptime') .then(function(r) { return r.json(); }) .then(function(data) { if (data.success) { document.getElementById('refresh-time').textContent = new Date(data.timestamp).toLocaleTimeString('pl-PL'); } }) .catch(function() {}); }, 300000); {% endif %} {% endblock %}