statsu
This commit is contained in:
@@ -7,11 +7,11 @@ WORKDIR /opt/app
|
|||||||
# Copy the current directory contents into the container
|
# Copy the current directory contents into the container
|
||||||
COPY . /opt/app/
|
COPY . /opt/app/
|
||||||
|
|
||||||
# Install system dependencies required for lxml
|
# Install system dependencies required for lxml and matplotlib
|
||||||
RUN apt-get update && apt-get install -y libxml2-dev libxslt1-dev
|
RUN apt-get update && apt-get install -y libxml2-dev libxslt1-dev
|
||||||
|
|
||||||
# Install Python packages
|
# Install Python packages
|
||||||
RUN pip install --no-cache-dir Flask requests python-dotenv beautifulsoup4 gunicorn lxml
|
RUN pip install --no-cache-dir Flask requests python-dotenv beautifulsoup4 gunicorn lxml pandas matplotlib
|
||||||
|
|
||||||
# Make port 8182 available to the world outside this container
|
# Make port 8182 available to the world outside this container
|
||||||
EXPOSE 8182
|
EXPOSE 8182
|
||||||
|
|||||||
77
app.py
77
app.py
@@ -1,14 +1,23 @@
|
|||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
|
import time
|
||||||
|
from collections import defaultdict
|
||||||
from flask import Flask, render_template, request, redirect, url_for, Response
|
from flask import Flask, render_template, request, redirect, url_for, Response
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
import pandas as pd
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from io import BytesIO
|
||||||
|
import base64
|
||||||
|
|
||||||
# Load environment variables from .env file
|
# Load environment variables from .env file
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
app = Flask(__name__, template_folder='templates')
|
app = Flask(__name__, template_folder='templates')
|
||||||
|
|
||||||
|
# Data structure to store request statistics
|
||||||
|
request_stats = defaultdict(lambda: defaultdict(int))
|
||||||
|
|
||||||
def get_config():
|
def get_config():
|
||||||
"""Retrieve configuration from environment variables."""
|
"""Retrieve configuration from environment variables."""
|
||||||
return {
|
return {
|
||||||
@@ -18,21 +27,18 @@ def get_config():
|
|||||||
"min_preference": os.getenv('MIN_PREFERENCE', '0')
|
"min_preference": os.getenv('MIN_PREFERENCE', '0')
|
||||||
}
|
}
|
||||||
|
|
||||||
@app.route('/dash/config', methods=['GET', 'POST'])
|
def log_request(repo, arch, protocol):
|
||||||
def config():
|
"""Log request statistics."""
|
||||||
if request.method == 'POST':
|
timestamp = int(time.time())
|
||||||
# Update environment variables with form data
|
hour = time.strftime('%Y-%m-%d %H', time.localtime(timestamp))
|
||||||
os.environ['EXCLUDED_COUNTRIES'] = request.form.get('excluded_countries', '')
|
day = time.strftime('%Y-%m-%d', time.localtime(timestamp))
|
||||||
os.environ['PREFERRED_PROTOCOLS'] = request.form.get('preferred_protocols', '')
|
week = time.strftime('%Y-%U', time.localtime(timestamp))
|
||||||
os.environ['PREFERRED_TYPES'] = request.form.get('preferred_types', '')
|
month = time.strftime('%Y-%m', time.localtime(timestamp))
|
||||||
os.environ['MIN_PREFERENCE'] = request.form.get('min_preference', '')
|
|
||||||
|
|
||||||
return redirect(url_for('config'))
|
|
||||||
|
|
||||||
# Retrieve the current configuration
|
|
||||||
config = get_config()
|
|
||||||
return render_template('config.html', **config)
|
|
||||||
|
|
||||||
|
request_stats[hour][(repo, arch, protocol)] += 1
|
||||||
|
request_stats[day][(repo, arch, protocol)] += 1
|
||||||
|
request_stats[week][(repo, arch, protocol)] += 1
|
||||||
|
request_stats[month][(repo, arch, protocol)] += 1
|
||||||
@app.route('/metalink')
|
@app.route('/metalink')
|
||||||
def get_metalink():
|
def get_metalink():
|
||||||
# Get query parameters from the request
|
# Get query parameters from the request
|
||||||
@@ -89,9 +95,50 @@ def filter_urls(content, excluded_countries, preferred_protocols, preferred_type
|
|||||||
|
|
||||||
return filtered_content
|
return filtered_content
|
||||||
|
|
||||||
|
@app.route('/dash')
|
||||||
@app.route('/dash/stats')
|
@app.route('/dash/stats')
|
||||||
def stats():
|
def stats():
|
||||||
return render_template('stats.html')
|
# Generate some statistics
|
||||||
|
stats_data = {
|
||||||
|
'hourly': request_stats.get(time.strftime('%Y-%m-%d %H', time.localtime()), {}),
|
||||||
|
'daily': request_stats.get(time.strftime('%Y-%m-%d', time.localtime()), {}),
|
||||||
|
'weekly': request_stats.get(time.strftime('%Y-%U', time.localtime()), {}),
|
||||||
|
'monthly': request_stats.get(time.strftime('%Y-%m', time.localtime()), {})
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert stats data to a DataFrame for easier manipulation
|
||||||
|
df = pd.DataFrame.from_dict(stats_data, orient='index').fillna(0)
|
||||||
|
|
||||||
|
# Generate a simple plot
|
||||||
|
plt.figure(figsize=(10, 6))
|
||||||
|
df.sum(axis=1).plot(kind='bar')
|
||||||
|
plt.title('Request Statistics')
|
||||||
|
plt.ylabel('Number of Requests')
|
||||||
|
|
||||||
|
# Save plot to a BytesIO object
|
||||||
|
img = BytesIO()
|
||||||
|
plt.savefig(img, format='png')
|
||||||
|
plt.close()
|
||||||
|
img.seek(0)
|
||||||
|
|
||||||
|
# Encode the plot to base64 for embedding in HTML
|
||||||
|
plot_url = base64.b64encode(img.getvalue()).decode('utf8')
|
||||||
|
|
||||||
|
return render_template('stats.html', plot_url=plot_url)
|
||||||
|
|
||||||
|
@app.route('/dash/config', methods=['GET', 'POST'])
|
||||||
|
def config():
|
||||||
|
if request.method == 'POST':
|
||||||
|
# Update environment variables with form data
|
||||||
|
os.environ['EXCLUDED_COUNTRIES'] = request.form.get('excluded_countries', '')
|
||||||
|
os.environ['PREFERRED_PROTOCOLS'] = request.form.get('preferred_protocols', '')
|
||||||
|
os.environ['PREFERRED_TYPES'] = request.form.get('preferred_types', '')
|
||||||
|
os.environ['MIN_PREFERENCE'] = request.form.get('min_preference', '')
|
||||||
|
|
||||||
|
return redirect(url_for('config'))
|
||||||
|
|
||||||
|
config = get_config()
|
||||||
|
return render_template('config.html', **config)
|
||||||
|
|
||||||
@app.route('/dash/logs')
|
@app.route('/dash/logs')
|
||||||
def logs():
|
def logs():
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="tab-pane fade show active">
|
<div class="tab-pane fade show active">
|
||||||
<h2>Statistics</h2>
|
<h2>Statistics</h2>
|
||||||
<p>Statistics content goes here.</p>
|
<div>
|
||||||
|
<img src="data:image/png;base64,{{ plot_url }}" alt="Request Statistics" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user