import json
from datetime import datetime
import ast
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import streamlit as st
from st_aggrid import AgGrid, GridOptionsBuilder, GridUpdateMode, DataReturnMode, JsCode
from core.query_executor import query_executor
from queries.QueryBuilder import QueryBuilder
from queries.filter import CommonUI
from queries.final_last import USER_360_QUERIES
def create_snowflake_dashboard(df):
# Custom CSS for enhanced styling
st.markdown(
"""
<style>
.main-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #667eea 100%);
color: white;
padding: 30px;
border-radius: 15px;
text-align: center;
margin-bottom: 30px;
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
animation: gradient 15s ease infinite;
background-size: 400% 400%;
}
@keyframes gradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.metric-card {
background: linear-gradient(145deg, #ffffff, #f0f2f6);
padding: 25px;
border-radius: 15px;
box-shadow: 0 8px 20px rgba(0,0,0,0.1);
border: 1px solid rgba(102, 126, 234, 0.1);
margin: 15px 0;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.metric-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: linear-gradient(90deg, #667eea, #764ba2);
}
.metric-card:hover {
transform: translateY(-5px) scale(1.02);
box-shadow: 0 12px 30px rgba(102, 126, 234, 0.2);
}
.metric-value {
font-size: 2.5em;
font-weight: 700;
color: #2c3e50;
margin-bottom: 8px;
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.metric-label {
color: #5a6c7d;
font-size: 1.1em;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.back-button {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
padding: 15px 30px;
border-radius: 25px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
margin-bottom: 20px;
}
.back-button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.query-detail-container {
background: linear-gradient(145deg, #ffffff, #f8f9fa);
border-radius: 20px;
padding: 30px;
box-shadow: 0 10px 30px rgba(0,0,0,0.15);
margin: 20px 0;
border: 1px solid rgba(102, 126, 234, 0.1);
}
.query-card {
background: white;
border-radius: 12px;
padding: 20px;
margin: 15px 0;
box-shadow: 0 4px 15px rgba(0,0,0,0.08);
border-left: 4px solid #667eea;
transition: all 0.3s ease;
}
.query-card:hover {
transform: translateX(5px);
box-shadow: 0 6px 20px rgba(0,0,0,0.12);
}
.status-optimal {
background: linear-gradient(135deg, #d4edda, #c3e6cb);
color: #155724;
padding: 8px 16px;
border-radius: 20px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.status-warning {
background: linear-gradient(135deg, #fff3cd, #ffeaa7);
color: #856404;
padding: 8px 16px;
border-radius: 20px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.status-critical {
background: linear-gradient(135deg, #f8d7da, #fab1a0);
color: #721c24;
padding: 8px 16px;
border-radius: 20px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.recommendation-card {
background: linear-gradient(135deg, #fff3cd, #ffeaa7);
padding: 20px;
border-radius: 12px;
margin: 15px 0;
border-left: 4px solid #ffc107;
box-shadow: 0 4px 15px rgba(255, 193, 7, 0.2);
}
.metric-mini-card {
background: linear-gradient(145deg, #f8f9fa, #e9ecef);
border-radius: 10px;
padding: 15px;
text-align: center;
margin: 5px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
border: 1px solid rgba(102, 126, 234, 0.1);
}
.section-title {
font-size: 1.8em;
font-weight: 700;
color: #2c3e50;
margin: 30px 0 20px 0;
position: relative;
padding-bottom: 10px;
}
.section-title::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 50px;
height: 3px;
background: linear-gradient(90deg, #667eea, #764ba2);
border-radius: 2px;
}
.stButton > button {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
border-radius: 10px;
padding: 12px 24px;
font-weight: 600;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}
.stButton > button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.ag-theme-streamlit {
--ag-header-background-color: linear-gradient(135deg, #667eea, #764ba2);
--ag-header-foreground-color: white;
--ag-odd-row-background-color: #f8f9fa;
--ag-row-hover-color: rgba(102, 126, 234, 0.1);
}
.fade-in {
animation: fadeIn 0.5s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
""",
unsafe_allow_html=True,
)
# Initialize session state
if "view_mode" not in st.session_state:
st.session_state.view_mode = "table" # "table" or "details"
if "selected_user" not in st.session_state:
st.session_state.selected_user = None
if "selected_metric" not in st.session_state:
st.session_state.selected_metric = None
# Header
st.markdown(
"""
<div class="main-header fade-in">
<h1>❄️ Snowflake Query Analytics Dashboard</h1>
<p style="font-size: 1.2em; margin-top: 15px;">Monitor, analyze, and optimize your Snowflake query performance with intelligent insights</p>
</div>
""",
unsafe_allow_html=True,
)
# Sidebar for data input
with st.sidebar:
st.header("📊 Data Management")
uploaded_file = st.file_uploader("Upload JSON Data", type=["json"])
if uploaded_file is not None:
try:
new_data = json.load(uploaded_file)
if isinstance(new_data, list):
df = pd.DataFrame(new_data)
st.success("✅ Data loaded successfully!")
else:
df = pd.DataFrame([new_data])
st.success("✅ Data loaded successfully!")
except Exception as e:
st.error(f"❌ Error loading data: {e}")
st.subheader("Or paste JSON data:")
json_input = st.text_area(
"JSON Data", height=200, placeholder="Paste your JSON data here..."
)
if st.button("Load JSON Data"):
try:
new_data = json.loads(json_input)
if isinstance(new_data, list):
df = pd.DataFrame(new_data)
else:
df = pd.DataFrame([new_data])
st.success("✅ Data loaded successfully!")
st.rerun()
except Exception as e:
st.error(f"❌ Error parsing JSON: {e}")
if not df.empty:
# Show different views based on mode
if st.session_state.view_mode == "table":
show_table_view(df)
else:
show_details_view(df)
else:
show_empty_state()
def show_table_view(df):
"""Display the main table view with metrics and AgGrid table"""
# Overall metrics cards
st.markdown('<div class="section-title fade-in">📈 Overall Performance Metrics</div>', unsafe_allow_html=True)
# First row of metrics
col1, col2, col3, col4 = st.columns(4)
with col1:
total_users = len(df)
st.markdown(
f"""
<div class="metric-card fade-in">
<div class="metric-value">{total_users}</div>
<div class="metric-label">👥 Total Users</div>
</div>
""",
unsafe_allow_html=True,
)
with col2:
total_queries = df["TOTAL_QUERIES"].sum()
st.markdown(
f"""
<div class="metric-card fade-in">
<div class="metric-value">{total_queries:,}</div>
<div class="metric-label">🔍 Total Queries</div>
</div>
""",
unsafe_allow_html=True,
)
with col3:
total_credits = df["TOTAL_CREDITS"].sum()
st.markdown(
f"""
<div class="metric-card fade-in">
<div class="metric-value">${total_credits:,.2f}</div>
<div class="metric-label">💰 Total Credits</div>
</div>
""",
unsafe_allow_html=True,
)
with col4:
avg_score = df["WEIGHTED_SCORE"].mean()
st.markdown(
f"""
<div class="metric-card fade-in">
<div class="metric-value">{avg_score:.1f}</div>
<div class="metric-label">⭐ Avg Score</div>
</div>
""",
unsafe_allow_html=True,
)
# Second row of metrics
col5, col6, col7, col8 = st.columns(4)
with col5:
total_spilled = df["SPILLED_QUERIES"].sum()
st.markdown(
f"""
<div class="metric-card fade-in">
<div class="metric-value">{total_spilled}</div>
<div class="metric-label">💾 Spilled Queries</div>
</div>
""",
unsafe_allow_html=True,
)
with col6:
total_slow = df["SLOW_QUERIES"].sum()
st.markdown(
f"""
<div class="metric-card fade-in">
<div class="metric-value">{total_slow}</div>
<div class="metric-label">🐌 Slow Queries</div>
</div>
""",
unsafe_allow_html=True,
)
with col7:
total_select_star = df["SELECT_STAR_QUERIES"].sum()
st.markdown(
f"""
<div class="metric-card fade-in">
<div class="metric-value">{total_select_star}</div>
<div class="metric-label">⭐ SELECT * Queries</div>
</div>
""",
unsafe_allow_html=True,
)
with col8:
avg_failure_rate = df["FAILURE_CANCELLATION_RATE_PCT"].mean()
st.markdown(
f"""
<div class="metric-card fade-in">
<div class="metric-value">{avg_failure_rate:.1f}%</div>
<div class="metric-label">❌ Avg Failure Rate</div>
</div>
""",
unsafe_allow_html=True,
)
# Enhanced AgGrid Table
st.markdown('<div class="section-title fade-in">👥 User Analytics Table</div>', unsafe_allow_html=True)
st.markdown('<p style="color: #666; margin-bottom: 20px;">Click on any user row to view detailed query analysis and recommendations</p>', unsafe_allow_html=True)
# Prepare data for AgGrid
display_df = df.copy()
# Format columns for better display
display_df["TOTAL_CREDITS"] = display_df["TOTAL_CREDITS"].apply(lambda x: f"${x:,.2f}")
display_df["AVG_EXECUTION_TIME_MS"] = display_df["AVG_EXECUTION_TIME_MS"].apply(lambda x: f"{x:,.1f}ms")
display_df["TOTAL_DATA_SCANNED_GB"] = display_df["TOTAL_DATA_SCANNED_GB"].apply(lambda x: f"{x:,.2f}GB")
display_df["FAILURE_CANCELLATION_RATE_PCT"] = display_df["FAILURE_CANCELLATION_RATE_PCT"].apply(lambda x: f"{x:.2f}%")
# Configure AgGrid
gb = GridOptionsBuilder.from_dataframe(display_df)
# Configure selection
gb.configure_selection("single", use_checkbox=False, rowMultiSelectWithClick=False)
# Configure columns
gb.configure_column("USER_NAME", headerName="👤 User Name", width=200, pinned="left")
gb.configure_column("TOTAL_QUERIES", headerName="🔍 Total Queries", width=120)
gb.configure_column("TOTAL_CREDITS", headerName="💰 Credits", width=120)
gb.configure_column("WEIGHTED_SCORE", headerName="⭐ Score", width=100, type=["numericColumn", "numberColumnFilter"])
gb.configure_column("COST_STATUS", headerName="📊 Status", width=120)
gb.configure_column("SPILLED_QUERIES", headerName="💾 Spilled", width=100)
gb.configure_column("SLOW_QUERIES", headerName="🐌 Slow", width=100)
gb.configure_column("SELECT_STAR_QUERIES", headerName="⭐ SELECT *", width=120)
gb.configure_column("AVG_EXECUTION_TIME_MS", headerName="⏱️ Avg Time", width=120)
gb.configure_column("TOTAL_DATA_SCANNED_GB", headerName="📊 Data Scanned", width=140)
gb.configure_column("FAILURE_CANCELLATION_RATE_PCT", headerName="❌ Failure Rate", width=130)
# Hide some columns to keep the table manageable
columns_to_hide = [
"OVER_PROVISIONED_QUERIES", "PEAK_HOUR_LONG_RUNNING_QUERIES",
"UNPARTITIONED_SCAN_QUERIES", "REPEATED_QUERIES", "COMPLEX_JOIN_QUERIES",
"ZERO_RESULT_QUERIES", "HIGH_COMPILE_QUERIES", "UNTAGGED_QUERIES",
"UNLIMITED_ORDER_BY_QUERIES", "LARGE_GROUP_BY_QUERIES",
"EXPENSIVE_DISTINCT_QUERIES", "INEFFICIENT_LIKE_QUERIES",
"NO_RESULTS_WITH_SCAN_QUERIES", "CARTESIAN_JOIN_QUERIES",
"HIGH_COMPILE_RATIO_QUERIES", "QUERY_SAMPLES", "RECOMMENDATIONS"
]
for col in columns_to_hide:
if col in display_df.columns:
gb.configure_column(col, hide=True)
# Configure grid options
gb.configure_grid_options(
domLayout='normal',
enableRangeSelection=True,
enableRowGrouping=True,
enablePivot=True,
enableValue=True,
rowHeight=50,
headerHeight=60
)
grid_options = gb.build()
# Display the grid
grid_response = AgGrid(
display_df,
gridOptions=grid_options,
data_return_mode=DataReturnMode.FILTERED_AND_SORTED,
update_mode=GridUpdateMode.SELECTION_CHANGED,
fit_columns_on_grid_load=False,
theme="streamlit",
height=500,
width='100%',
reload_data=False
)
# Handle row selection
if grid_response['selected_rows'] is not None and len(grid_response['selected_rows']) > 0:
selected_row = grid_response['selected_rows'][0]
st.session_state.selected_user = selected_row['USER_NAME']
st.session_state.view_mode = "details"
st.rerun()
# Charts section
st.markdown('<div class="section-title fade-in">📊 Analytics Visualizations</div>', unsafe_allow_html=True)
col1, col2 = st.columns(2)
with col1:
fig_scatter = px.scatter(
df,
x="TOTAL_QUERIES",
y="TOTAL_CREDITS",
hover_data=["USER_NAME", "WEIGHTED_SCORE"],
title="💰 Credits vs Total Queries",
color="WEIGHTED_SCORE",
size="TOTAL_DATA_SCANNED_GB",
color_continuous_scale="Viridis"
)
fig_scatter.update_layout(
height=500,
title_font_size=16,
plot_bgcolor='rgba(0,0,0,0)',
paper_bgcolor='rgba(0,0,0,0)'
)
st.plotly_chart(fig_scatter, use_container_width=True)
with col2:
status_counts = df["COST_STATUS"].value_counts()
fig_pie = px.pie(
values=status_counts.values,
names=status_counts.index,
title="📊 Cost Status Distribution",
color_discrete_sequence=px.colors.qualitative.Set3
)
fig_pie.update_layout(
height=500,
title_font_size=16,
plot_bgcolor='rgba(0,0,0,0)',
paper_bgcolor='rgba(0,0,0,0)'
)
st.plotly_chart(fig_pie, use_container_width=True)
def show_details_view(df):
"""Display detailed view for selected user"""
# Back button
if st.button("← Back to Table", key="back_button"):
st.session_state.view_mode = "table"
st.session_state.selected_user = None
st.session_state.selected_metric = None
st.rerun()
user_data = df[df["USER_NAME"] == st.session_state.selected_user].iloc[0]
# User header
st.markdown(
f"""
<div class="query-detail-container fade-in">
<h1>🔍 Detailed Analysis for {st.session_state.selected_user}</h1>
<div style="display: flex; justify-content: space-between; align-items: center; margin: 20px 0;">
<div>
<span style="font-size: 1.2em; color: #666;">Overall Performance Score:</span>
<span style="font-size: 2em; font-weight: bold; color: #667eea; margin-left: 10px;">{user_data['WEIGHTED_SCORE']:.1f}</span>
</div>
<div>
<span class="status-{'optimal' if user_data['COST_STATUS'] == 'Optimal' else 'warning' if user_data['COST_STATUS'] == 'Warning' else 'critical'}">
{user_data['COST_STATUS']}
</span>
</div>
</div>
</div>
""",
unsafe_allow_html=True,
)
# User metrics overview
st.markdown('<div class="section-title">📊 User Performance Overview</div>', unsafe_allow_html=True)
col1, col2, col3, col4 = st.columns(4)
with col1:
st.markdown(
f"""
<div class="metric-mini-card">
<div style="font-size: 1.8em; font-weight: bold; color: #667eea;">{user_data['TOTAL_QUERIES']:,}</div>
<div style="color: #666; font-size: 0.9em;">Total Queries</div>
</div>
""",
unsafe_allow_html=True,
)
with col2:
st.markdown(
f"""
<div class="metric-mini-card">
<div style="font-size: 1.8em; font-weight: bold; color: #667eea;">${user_data['TOTAL_CREDITS']:,.2f}</div>
<div style="color: #666; font-size: 0.9em;">Total Credits</div>
</div>
""",
unsafe_allow_html=True,
)
with col3:
st.markdown(
f"""
<div class="metric-mini-card">
<div style="font-size: 1.8em; font-weight: bold; color: #667eea;">{user_data['AVG_EXECUTION_TIME_MS']:,.1f}ms</div>
<div style="color: #666; font-size: 0.9em;">Avg Execution Time</div>
</div>
""",
unsafe_allow_html=True,
)
with col4:
st.markdown(
f"""
<div class="metric-mini-card">
<div style="font-size: 1.8em; font-weight: bold; color: #667eea;">{user_data['TOTAL_DATA_SCANNED_GB']:,.2f}GB</div>
<div style="color: #666; font-size: 0.9em;">Data Scanned</div>
</div>
""",
unsafe_allow_html=True,
)
# Query type breakdown
st.markdown('<div class="section-title">🔍 Query Type Analysis</div>', unsafe_allow_html=True)
query_metrics = [
("SPILLED_QUERIES", "💾 Spilled Queries", "Queries that spilled to disk"),
("SLOW_QUERIES", "🐌 Slow Queries", "Queries with high execution time"),
("SELECT_STAR_QUERIES", "⭐ SELECT * Queries", "Queries using SELECT *"),
("COMPLEX_JOIN_QUERIES", "🔗 Complex Join Queries", "Queries with complex joins"),
("REPEATED_QUERIES", "🔄 Repeated Queries", "Frequently repeated queries"),
("HIGH_COMPILE_QUERIES", "⚙️ High Compile Queries", "Queries with high compile time")
]
cols = st.columns(3)
for i, (metric, title, description) in enumerate(query_metrics):
with cols[i % 3]:
value = user_data.get(metric, 0)
percentage = (value / user_data['TOTAL_QUERIES'] * 100) if user_data['TOTAL_QUERIES'] > 0 else 0
st.markdown(
f"""
<div class="query-card">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div>
<h4 style="margin: 0; color: #2c3e50;">{title}</h4>
<p style="margin: 5px 0; color: #666; font-size: 0.9em;">{description}</p>
</div>
<div style="text-align: right;">
<div style="font-size: 1.5em; font-weight: bold; color: #667eea;">{value}</div>
<div style="color: #666; font-size: 0.9em;">{percentage:.1f}%</div>
</div>
</div>
</div>
""",
unsafe_allow_html=True,
)
# Sample queries section
if "QUERY_SAMPLES" in user_data and user_data["QUERY_SAMPLES"]:
st.markdown('<div class="section-title">📋 Sample Query Analysis</div>', unsafe_allow_html=True)
query_samples = user_data["QUERY_SAMPLES"]
if isinstance(query_samples, str):
try:
query_samples = ast.literal_eval(query_samples)
except Exception as e:
st.error(f"Failed to parse query samples: {e}")
query_samples = {}
# Create tabs for different query types
if query_samples:
tabs = st.tabs([key.replace('_', ' ').title() for key in query_samples.keys()])
for i, (sample_key, samples) in enumerate(query_samples.items()):
with tabs[i]:
for j, sample in enumerate(samples[:3]): # Show top 3 samples
with st.expander(f"Query {j+1}: {sample.get('query_id', 'N/A')}", expanded=j==0):
st.code(
sample.get("query_text", "No query text available"),
language="sql",
)
# Metrics in columns
metric_cols = st.columns(4)
with metric_cols[0]:
execution_time = sample.get("execution_time_ms", 0)
color = "#28a745" if execution_time < 1000 else "#dc3545"
st.markdown(f"**⏱️ Execution Time**<br><span style='color: {color}; font-size: 1.2em; font-weight: bold;'>{execution_time:,}ms</span>", unsafe_allow_html=True)
with metric_cols[1]:
st.markdown(f"**📊 Bytes Scanned**<br><span style='font-size: 1.2em; font-weight: bold;'>{sample.get('bytes_scanned', 0):,}</span>", unsafe_allow_html=True)
with metric_cols[2]:
st.markdown(f"**🏭 Warehouse**<br><span style='font-size: 1.2em; font-weight: bold;'>{sample.get('warehouse_size', 'N/A')}</span>", unsafe_allow_html=True)
with metric_cols[3]:
st.markdown(f"**📅 Start Time**<br><span style='font-size: 1.2em; font-weight: bold;'>{sample.get('start_time', 'N/A')}</span>", unsafe_allow_html=True)
# Spill information if available
if "bytes_spilled_to_local_storage" in sample:
st.markdown("**💾 Spill Information:**")
spill_cols = st.columns(2)
with spill_cols[0]:
st.info(f"Local Spill: {sample.get('bytes_spilled_to_local_storage', 0):,} bytes")
with spill_cols[1]:
st.info(f"Remote Spill: {sample.get('bytes_spilled_to_remote_storage', 0):,} bytes")
# Recommendations section
if "RECOMMENDATIONS" in user_data and user_data["RECOMMENDATIONS"]:
st.markdown('<div class="section-title">💡 Optimization Recommendations</div>', unsafe_allow_html=True)
recommendations = user_data["RECOMMENDATIONS"]
if isinstance(recommendations, str):
try:
recommendations = ast.literal_eval(recommendations)
except Exception as e:
st.error(f"Failed to parse recommendations: {e}")
recommendations = []
for i, rec in enumerate(recommendations):
st.markdown(
f"""
<div class="recommendation-card">
<h4 style="margin: 0 0 10px 0; color: #856404;">💡 Recommendation {i+1}</h4>
<p style="margin: 0; font-size: 1.1em; line-height: 1.6;">{rec}</p>
</div>
""",
unsafe_allow_html=True,
)
def show_empty_state():
"""Display empty state when no data is available"""
st.markdown(
"""
<div class="query-detail-container fade-in" style="text-align: center; padding: 50px;">
<h2>📊 Welcome to Snowflake Analytics Dashboard</h2>
<p style="font-size: 1.2em; color: #666; margin: 20px 0;">
No data available. Please upload JSON data using the sidebar to get started!
</p>
<div style="background: #f8f9fa; padding: 30px; border-radius: 15px; margin: 30px 0; text-align: left; max-width: 600px; margin: 30px auto;">
<h3>📋 Expected JSON Format:</h3>
<p>Your JSON should contain user analytics data with the following structure:</p>
<ul style="text-align: left; color: #666;">
<li><strong>USER_NAME</strong> - Name of the user</li>
<li><strong>TOTAL_QUERIES</strong> - Total number of queries executed</li>
<li><strong>TOTAL_CREDITS</strong> - Total credits consumed</li>
<li><strong>WEIGHTED_SCORE</strong> - Performance score</li>
<li><strong>Various query metrics</strong> (SPILLED_QUERIES, SELECT_STAR_QUERIES, etc.)</li>
<li><strong>QUERY_SAMPLES</strong> - Detailed query information with examples</li>
<li><strong>RECOMMENDATIONS</strong> - Optimization suggestions</li>
</ul>
</div>
</div>
""",
unsafe_allow_html=True,
)
# Run the dashboard with sample data
if __name__ == "__main__":
st.subheader("🔧 Filters")
col1, col2 = st.columns(2)
with col1:
date_filter, custom_start, custom_end = CommonUI.render_date_filter()
with col2:
selected_user = CommonUI.render_object_filter("user", query_executor)
# === PREPARE QUERY PARAMETERS ===
# Get date range
start_date, end_date = query_executor.get_date_range(
date_filter, custom_start, custom_end
)
# Build object filter
object_filter = QueryBuilder.build_object_filter("user", selected_user)
print(f"this is the meeee {object_filter}")
st.markdown("---")
query_key = "user_all_quries"
df = {}
query = QueryBuilder.prepare_query(
USER_360_QUERIES, query_key, start_date, end_date, object_filter
)
if not query:
st.error(f"Failed to prepare query for {query_key}")
# continue
# Execute query
try:
data = query_executor._execute_single_query(
query, {}, query_key # Already formatted
)
df = data
except Exception as e:
st.error(f"Query execution failed for {query_key}: {str(e)}")
# Analysis type selection
s = len(df)
# sample_data = load_sample_data()
# df = pd.DataFrame(sample_data)
create_snowflake_dashboard(df)
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)