\x89PNG\r\n\x1a\n\x00\x00\x00\x0DIHDR\x00\x00\x00\x01\x00 \x00\x00\x01\x08\x06\x00\x00\x00\x1F\x15\xC4\x89\x00\x00\x00 \x0AIDATx\x9Ccb\x00\x00\x00\x06\x00\x03\x1A\x05\x9D\x00\x00 \x00\x00IEND\xAE\x42\x60\x82 csarite.com
KUJUNTI.ID MINISH3LL
Path : /var/www/html/yedekledb24/DatabaseBackupMasterv8/
(S)h3ll Cr3at0r :
F!le Upl0ad :

B-Con CMD Config cPanel C-Rdp D-Log Info Jump Mass Ransom Symlink vHost Zone-H

Current File : /var/www/html/yedekledb24/DatabaseBackupMasterv8/mysql_performance_charts.py


"""
MySQL/MariaDB performans verilerini görselleştirmek için script.

Bu script, MySQL/MariaDB'den alınan sorgu performans verilerini Pandas DataFrame'e dönüştürür 
ve Matplotlib kullanarak statik grafikler oluşturur.
"""

import os
import sys
import json
import logging
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
from datetime import datetime
import pymysql

# Türkçe karakterleri düzgün gösterme
plt.rcParams['font.family'] = 'DejaVu Sans'

# Log yapılandırması
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# Grafik dizini
CHART_DIR = os.path.join('static', 'charts')
os.makedirs(CHART_DIR, exist_ok=True)

def get_top_queries(connection_info, limit=10, order_by='total_time'):
    """
    MySQL/MariaDB veritabanından en çok kaynak tüketen sorguları alır ve DataFrame olarak döndürür.
    """
    try:
        # Bağlantı kur
        connection = pymysql.connect(
            host=connection_info['host'],
            port=connection_info['port'],
            user=connection_info['username'],
            password=connection_info['password'],
            database=connection_info['database']
        )
        cursor = connection.cursor()
        
        # Performance Schema etkin mi kontrol et
        cursor.execute("SHOW VARIABLES LIKE 'performance_schema'")
        performance_schema_enabled = cursor.fetchone()
        
        if not performance_schema_enabled or performance_schema_enabled[1].lower() != 'on':
            logger.error("Performance Schema etkin değil.")
            return pd.DataFrame(), {'total_calls': 0, 'total_time': 0, 'query_count': 0}
        
        # Sıralama sütununu belirle
        order_column = "SUM_TIMER_WAIT DESC"
        if order_by == "calls":
            order_column = "COUNT_STAR DESC"
        elif order_by == "rows":
            order_column = "SUM_ROWS_AFFECTED DESC"
        
        # Sorguyu çalıştır
        query = """
        SELECT 
            DIGEST_TEXT as query,
            COUNT_STAR as calls,
            SUM_ROWS_AFFECTED as affected_rows,
            SUM_TIMER_WAIT/1000000000 as total_time,
            AVG_TIMER_WAIT/1000000000 as avg_time,
            ROUND(100 * SUM_TIMER_WAIT / (SELECT SUM(SUM_TIMER_WAIT) 
                                         FROM performance_schema.events_statements_summary_by_digest), 2) as percentage_cpu
        FROM performance_schema.events_statements_summary_by_digest
        WHERE SCHEMA_NAME = %s
        ORDER BY {}
        LIMIT %s
        """.format(order_column)
        
        cursor.execute(query, (connection_info['database'], limit))
        
        # Sonuçları DataFrame'e dönüştür
        columns = [desc[0] for desc in cursor.description]
        rows = cursor.fetchall()
        
        if not rows:
            logger.warning("Sorgu sonucu boş.")
            return pd.DataFrame(), {'total_calls': 0, 'total_time': 0, 'query_count': 0}
            
        df = pd.DataFrame(rows, columns=columns)
        
        # Özet bilgileri al
        summary_query = """
        SELECT 
            COALESCE(SUM(COUNT_STAR), 0) as total_calls,
            COALESCE(SUM(SUM_TIMER_WAIT)/1000000000, 0) as total_time,
            COUNT(*) as query_count
        FROM performance_schema.events_statements_summary_by_digest
        WHERE SCHEMA_NAME = %s
        """
        cursor.execute(summary_query, (connection_info['database'],))
        summary_row = cursor.fetchone()
        
        summary = {
            'total_calls': int(summary_row[0]),
            'total_time': float(summary_row[1]),
            'query_count': int(summary_row[2])
        }
        
        # Bağlantıyı kapat
        cursor.close()
        connection.close()
        
        # DataFrame'i biraz düzenle
        # Kısa sorgu etiketleri oluştur
        df['short_query'] = df['query'].apply(lambda x: (str(x)[:20] + '...') if x and len(str(x)) > 20 else x)
        
        # affected_rows sütun adını rows olarak değiştir (geriye dönük uyumluluk için)
        if 'affected_rows' in df.columns and 'rows' not in df.columns:
            df['rows'] = df['affected_rows']
        
        return df, summary
        
    except Exception as e:
        logger.error(f"MySQL sorgu verisi alınırken hata: {str(e)}")
        # Boş DataFrame ve özet bilgi döndür
        return pd.DataFrame(), {'total_calls': 0, 'total_time': 0, 'query_count': 0}

def create_charts(df, db_id, timestamp=None):
    """
    DataFrame'deki verilerden dört farklı grafik oluşturur ve kaydeder.
    
    Returns:
        dict: Grafik dosyalarının yollarını içeren bir sözlük
    """
    if df.empty:
        logger.warning("Boş DataFrame, grafikler oluşturulamadı.")
        return {}
    
    # Zaman damgası
    ts = timestamp or datetime.now().strftime("%Y%m%d%H%M%S")
    
    # Grafik dosya adları
    chart_files = {
        'execution_time': f"{CHART_DIR}/mysql_exec_time_{db_id}_{ts}.png",
        'cpu_percentage': f"{CHART_DIR}/mysql_cpu_pct_{db_id}_{ts}.png",
        'calls': f"{CHART_DIR}/mysql_calls_{db_id}_{ts}.png",
        'scatter': f"{CHART_DIR}/mysql_scatter_{db_id}_{ts}.png"
    }
    
    # Görsel stil ayarları
    plt.style.use('dark_background')
    mpl.rcParams['axes.edgecolor'] = '#666'
    mpl.rcParams['axes.facecolor'] = '#222'
    mpl.rcParams['figure.facecolor'] = '#222'
    mpl.rcParams['grid.color'] = '#444'
    mpl.rcParams['text.color'] = '#DDD'
    mpl.rcParams['axes.labelcolor'] = '#DDD'
    mpl.rcParams['xtick.color'] = '#DDD'
    mpl.rcParams['ytick.color'] = '#DDD'
    
    # Renkler
    colors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12', '#9b59b6', 
              '#1abc9c', '#d35400', '#34495e', '#7f8c8d', '#27ae60']
    
    try:
        # 1. Çalışma Süresi Grafiği
        plt.figure(figsize=(10, 6))
        bars = plt.bar(range(len(df)), df['total_time'], color=colors[:len(df)])
        plt.xticks(range(len(df)), df['short_query'], rotation=45, ha='right')
        plt.xlabel('Sorgular')
        plt.ylabel('Çalışma Süresi (ns)')
        plt.title('Sorgu Çalışma Süresi Dağılımı (MySQL/MariaDB)')
        plt.tight_layout()
        plt.savefig(chart_files['execution_time'], dpi=100)
        plt.close()
        
        # 2. CPU Yüzdesi Grafiği (Pasta)
        plt.figure(figsize=(10, 6))
        plt.pie(df['percentage_cpu'], labels=df['short_query'], autopct='%1.1f%%', startangle=90, colors=colors[:len(df)])
        plt.axis('equal')
        plt.title('CPU Kullanım Yüzdesi (MySQL/MariaDB)')
        plt.tight_layout()
        plt.savefig(chart_files['cpu_percentage'], dpi=100)
        plt.close()
        
        # 3. Çağrı Sayısı Grafiği
        plt.figure(figsize=(10, 6))
        plt.bar(range(len(df)), df['calls'], color='#2ecc71')
        plt.xticks(range(len(df)), df['short_query'], rotation=45, ha='right')
        plt.xlabel('Sorgular')
        plt.ylabel('Çağrı Sayısı')
        plt.title('Sorgu Çağrı Sayısı (MySQL/MariaDB)')
        plt.tight_layout()
        plt.savefig(chart_files['calls'], dpi=100)
        plt.close()
        
        # 4. Scatter Plot (Çalışma Süresi vs CPU Yüzdesi)
        plt.figure(figsize=(10, 6))
        scatter = plt.scatter(df['total_time'], df['percentage_cpu'], s=df['calls'], 
                             alpha=0.6, c=range(len(df)), cmap='viridis')
        
        # Nokta etiketleri
        for i, txt in enumerate(df['short_query']):
            plt.annotate(txt, (df['total_time'].iloc[i], df['percentage_cpu'].iloc[i]),
                         xytext=(5, 5), textcoords='offset points', fontsize=8)
            
        plt.xlabel('Çalışma Süresi (ns)')
        plt.ylabel('CPU Kullanımı (%)')
        plt.title('Süre ve CPU Kullanımı İlişkisi (MySQL/MariaDB)')
        plt.tight_layout()
        plt.savefig(chart_files['scatter'], dpi=100)
        plt.close()
        
        logger.info(f"MySQL grafikleri başarıyla oluşturuldu ve {CHART_DIR} dizinine kaydedildi.")
        return chart_files
        
    except Exception as e:
        logger.error(f"MySQL grafikleri oluşturulurken hata: {str(e)}")
        return {}

def main(db_id=None, limit=10, order_by='total_time'):
    """
    Ana fonksiyon - veritabanı ID'si için grafikleri oluşturur.
    """
    from models import DatabaseConnection
    from sqlalchemy.orm import scoped_session, sessionmaker
    from app import db
    
    try:
        # Oturum oluştur
        Session = scoped_session(sessionmaker(bind=db.engine))
        session = Session()
        
        # Veritabanı bağlantısını al
        db_conn = session.query(DatabaseConnection).filter_by(id=db_id).first()
        
        if not db_conn:
            logger.error(f"ID={db_id} olan veritabanı bulunamadı.")
            return None
            
        # Bağlantı bilgilerini hazırla
        connection_info = {
            'host': db_conn.host,
            'port': db_conn.port,
            'username': db_conn.username,
            'password': db_conn.password,
            'database': db_conn.database
        }
        
        # Sadece MySQL/MariaDB için çalışır
        if db_conn.db_type not in ['mysql', 'mariadb']:
            logger.error("Bu script sadece MySQL ve MariaDB için çalışır.")
            return None
            
        # Verileri al ve grafikleri oluştur
        df, summary = get_top_queries(connection_info, limit, order_by)
        charts = create_charts(df, db_id)
        
        Session.remove()
        
        return {
            'charts': charts,
            'summary': summary,
            'query_count': len(df)
        }
        
    except Exception as e:
        logger.error(f"Hata: {str(e)}")
        return None

if __name__ == "__main__":
    # Komut satırından çalıştırıldığında
    if len(sys.argv) > 1:
        db_id = int(sys.argv[1])
        limit = int(sys.argv[2]) if len(sys.argv) > 2 else 10
        order_by = sys.argv[3] if len(sys.argv) > 3 else 'total_time'
        
        result = main(db_id, limit, order_by)
        print(json.dumps(result, indent=2))
    else:
        print("Kullanım: python mysql_performance_charts.py <db_id> [limit] [order_by]")

© KUJUNTI.ID