File size: 4,117 Bytes
6d12932 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
import pandas as pd
import altair as alt
import streamlit as st
import json
from datetime import datetime, timedelta
from db.database import get_analytics_summary, get_top_users, get_audit_logs
def render_dashboard():
"""Render the advanced analytics dashboard."""
st.title("π Advanced Analytics Dashboard")
# Date Range Filter
col1, col2 = st.columns(2)
with col1:
start_date = st.date_input("Start Date", datetime.now() - timedelta(days=30))
with col2:
end_date = st.date_input("End Date", datetime.now())
s_str = start_date.strftime("%Y-%m-%d")
e_str = end_date.strftime("%Y-%m-%d")
# Fetch Data
summary_data = get_analytics_summary(start_date=s_str, end_date=e_str)
# KPI Cards
total_events = sum(d['total_events'] for d in summary_data)
unique_users = sum(d['unique_users'] for d in summary_data) # Approximation
kpi1, kpi2, kpi3 = st.columns(3)
kpi1.metric("Total Events", total_events)
# kpi2.metric("Active Users", unique_users)
# Tabs
tab1, tab2, tab3 = st.tabs(["π Overview", "π₯ User Engagement", "π‘οΈ Compliance & Audit"])
with tab1:
st.subheader("Event Trends")
if summary_data:
df = pd.DataFrame(summary_data)
# Ensure proper types
df['total_events'] = df['total_events'].astype(int)
# Line Chart: Events over time by Type
chart = alt.Chart(df).mark_line(point=True).encode(
x='event_date:T',
y='total_events:Q',
color='event_type:N',
tooltip=['event_date', 'event_type', 'total_events']
).interactive()
st.altair_chart(chart, use_container_width=True)
# Bar Chart: Distribution
st.subheader("Event Distribution")
bar = alt.Chart(df).mark_bar().encode(
x='event_type:N',
y='sum(total_events):Q',
color='event_type:N',
tooltip=['event_type', 'sum(total_events)']
)
st.altair_chart(bar, use_container_width=True)
else:
st.info("No data available for this range.")
with tab2:
st.subheader("Top Active Users")
top_users = get_top_users(limit=10)
if top_users:
top_df = pd.DataFrame(top_users)
st.table(top_df)
user_chart = alt.Chart(top_df).mark_bar().encode(
x='event_count:Q',
y=alt.Y('username:N', sort='-x'),
tooltip=['username', 'event_count']
)
st.altair_chart(user_chart, use_container_width=True)
else:
st.info("No user activity recorded.")
with tab3:
st.subheader("Security Audit Logs")
# Filters
uid_filter = st.text_input("Filter by User ID (Optional)")
uid = int(uid_filter) if uid_filter.isdigit() else None
audit_logs = get_audit_logs(user_id=uid, start_date=s_str, end_date=e_str, limit=50)
if audit_logs:
audit_df = pd.DataFrame(audit_logs)
# Expand JSON changes for readability
if 'changes' in audit_df.columns:
audit_df['changes'] = audit_df['changes'].apply(lambda x: json.dumps(x) if isinstance(x, (dict, list)) else str(x))
st.dataframe(
audit_df[['created_at', 'action', 'resource_type', 'user_id', 'ip_address', 'changes']],
use_container_width=True
)
csv = audit_df.to_csv(index=False).encode('utf-8')
st.download_button(
"Download Audit Logs (CSV)",
csv,
"audit_logs.csv",
"text/csv",
key='download-csv'
)
else:
st.info("No audit logs found.")
|