Files
haproxy-dashboard/templates/logs.html
Mateusz Gruszczyński df70118653 new options
2025-11-03 10:18:10 +01:00

163 lines
7.5 KiB
HTML

{% extends "base.html" %}
{% set active_page = "logs" %}
{% block title %}HAProxy • Access Logs{% endblock %}
{% block breadcrumb %}Access Logs{% endblock %}
{% block content %}
<div class="card shadow-sm mb-4">
<div class="card-header bg-info text-white">
<h5 class="mb-0"><i class="bi bi-file-text me-2"></i>HAProxy Access Logs & Security Analysis</h5>
</div>
<div class="card-body">
{% if logs %}
<!-- Statistics Cards -->
<div class="row mb-4">
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<h6 class="text-muted">Total Requests</h6>
<div class="fs-3 fw-bold text-primary">{{ logs|length }}</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<h6 class="text-muted">Threats Detected</h6>
<div class="fs-3 fw-bold text-danger">
{{ logs|selectattr('is_threat')|list|length }}
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<h6 class="text-muted">Unique IPs</h6>
<div class="fs-3 fw-bold text-warning">
{{ logs|map(attribute='ip_address')|unique|list|length }}
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<h6 class="text-muted">Success Rate</h6>
<div class="fs-3 fw-bold text-success">
{% set success_count = logs|selectattr('status_code')|selectattr('status_code', 'ge', 200)|selectattr('status_code', 'lt', 300)|list|length %}
{{ ((success_count / logs|length * 100)|round(1)) if logs else 0 }}%
</div>
</div>
</div>
</div>
</div>
<!-- Filters -->
<div class="card mb-4 bg-light">
<div class="card-body">
<h6 class="mb-3"><i class="bi bi-funnel me-2"></i>Filters</h6>
<div class="row g-3">
<div class="col-md-3">
<label class="form-label small">Status Code</label>
<select class="form-select form-select-sm" id="filter_status">
<option value="">All</option>
{% for log in logs %}
<option value="{{ log.status_code }}">{{ log.status_code }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-3">
<label class="form-label small">Threat Level</label>
<select class="form-select form-select-sm" id="filter_threat">
<option value="">All</option>
<option value="danger">Danger</option>
<option value="warning">Warning</option>
<option value="info">Info</option>
</select>
</div>
<div class="col-md-3">
<label class="form-label small">HTTP Method</label>
<select class="form-select form-select-sm" id="filter_method">
<option value="">All</option>
{% set methods = logs|map(attribute='http_method')|unique %}
{% for method in methods %}
<option value="{{ method }}">{{ method }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-3">
<label class="form-label small">Show Threats Only</label>
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" id="filter_threats_only">
<label class="form-check-label" for="filter_threats_only">
Threats
</label>
</div>
</div>
</div>
</div>
</div>
<!-- Logs Table -->
<div class="table-responsive">
<table class="table table-striped table-hover table-sm">
<thead class="table-dark">
<tr>
<th>Timestamp</th>
<th>IP Address</th>
<th>Method</th>
<th>URL</th>
<th>Status</th>
<th>Threats</th>
</tr>
</thead>
<tbody id="logs_table_body">
{% for log in logs %}
<tr class="log-row" data-status="{{ log.status_code }}" data-threat="{{ log.threat_level }}" data-method="{{ log.http_method }}" data-threat-count="{{ 1 if log.is_threat else 0 }}">
<td class="small">{{ log.timestamp }}</td>
<td>
<span class="badge bg-secondary">{{ log.ip_address }}</span>
</td>
<td>
<span class="badge bg-primary">{{ log.http_method }}</span>
</td>
<td class="text-truncate" style="max-width: 300px;" title="{{ log.requested_url }}">
{{ log.requested_url }}
</td>
<td>
<span class="badge bg-{{ log.status_category }}">{{ log.status_code }}</span>
</td>
<td>
{% if log.is_threat %}
{% for threat in log.threats %}
<span class="badge bg-{{ log.threat_level }} me-1">{{ threat }}</span>
{% endfor %}
{% else %}
<span class="text-muted small"></span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="alert alert-info">
<i class="bi bi-info-circle me-2"></i>No log entries found.
</div>
{% endif %}
</div>
</div>
<script src="{{ url_for('static', filename='js/logs.js') }}"></script>
{% endblock %}