OLicense Monitoring & Analytics
This guide covers comprehensive monitoring and analytics for OLicense servers using the Vantage License Manager. OLicense provides extensive usage data and performance metrics that, when integrated with Vantage, create powerful insights for license optimization, cost management, and capacity planning across enterprise software portfolios.
Vantage Dashboard Integration
Real-time License Monitoring
The Vantage License Manager transforms OLicense data into intuitive, actionable dashboards that provide immediate visibility into license utilization, user behavior, and system performance.
Primary Dashboard Features:
- Live License Utilization: Real-time tracking of concurrent license usage across all OLicense-managed software
- User Activity Streams: Live feed of license checkout/checkin events with user identification and session duration
- Feature-Level Analytics: Detailed breakdowns by software feature, version, and usage patterns
- Cost Analytics: Real-time cost tracking with budget alerts and optimization recommendations
- Performance Metrics: Server response times, API performance, and system health indicators
# Configure Vantage dashboard for OLicense monitoring
vantage licenses create-dashboard olicense-production \
--title "OLicense Enterprise Monitoring" \
--layout grid \
--refresh-interval 30s \
--widgets "
license_utilization,
user_activity,
feature_analytics,
cost_tracking,
server_health,
usage_trends,
alerts_summary,
capacity_planning
"
# Configure real-time data streaming
vantage licenses enable-streaming olicense-production \
--events license_checkout,license_checkin,user_login,server_status \
--buffer-size 10000 \
--flush-interval 5s \
--enable-filtering \
--priority-events server_down,license_exhausted
Advanced Analytics Configuration
import textwrap
import json
from datetime import datetime, timedelta
def configure_olicense_analytics():
"""Configure advanced analytics for OLicense monitoring."""
analytics_config = textwrap.dedent("""
#!/bin/bash
# Advanced OLicense Analytics Configuration
# Configure usage analytics
vantage licenses analytics olicense-production \\
--enable-usage-patterns \\
--enable-cost-analytics \\
--enable-predictive-modeling \\
--enable-optimization-recommendations \\
--historical-period 2years \\
--analysis-granularity hourly,daily,weekly,monthly
# Set up user behavior analytics
vantage licenses user-analytics olicense-production \\
--track-session-duration \\
--track-feature-usage \\
--track-peak-hours \\
--track-department-usage \\
--enable-user-clustering \\
--anomaly-detection true
# Configure cost optimization analytics
vantage licenses cost-analytics olicense-production \\
--enable-cost-per-feature \\
--enable-cost-per-user \\
--enable-cost-per-department \\
--enable-roi-analysis \\
--enable-license-rightsizing \\
--budget-tracking true \\
--cost-allocation department_based
# Set up predictive analytics
vantage licenses predictive-analytics olicense-production \\
--models usage_forecasting,cost_prediction,capacity_planning \\
--forecast-horizon 90days \\
--confidence-interval 95% \\
--seasonal-adjustment true \\
--trend-analysis true
# Configure performance analytics
vantage licenses performance-analytics olicense-production \\
--track-response-times \\
--track-api-performance \\
--track-database-performance \\
--track-network-latency \\
--enable-bottleneck-detection \\
--performance-baselines auto
""").strip()
return analytics_config
# Generate analytics configuration
analytics_script = configure_olicense_analytics()
print("OLicense analytics configuration ready")
Custom Dashboard Creation
import textwrap
def create_custom_dashboard_config():
"""Create custom dashboard configuration for specific OLicense use cases."""
dashboard_config = textwrap.dedent("""
# Custom OLicense Dashboard Configuration
# /opt/vantage/config/olicense-dashboards.json
{
"dashboards": [
{
"name": "Executive Summary",
"description": "High-level license portfolio overview for executives",
"layout": "executive",
"refresh_interval": "5m",
"widgets": [
{
"type": "kpi_cards",
"title": "License Portfolio KPIs",
"metrics": [
"total_license_value",
"utilization_rate",
"cost_per_user",
"roi_percentage",
"compliance_score"
],
"time_range": "last_30_days"
},
{
"type": "trend_chart",
"title": "License Utilization Trends",
"metrics": ["peak_utilization", "average_utilization"],
"time_range": "last_12_months",
"granularity": "monthly"
},
{
"type": "cost_breakdown",
"title": "Cost Distribution by Department",
"breakdown_by": "department",
"chart_type": "pie",
"time_range": "current_month"
},
{
"type": "optimization_recommendations",
"title": "Top Cost Optimization Opportunities",
"max_recommendations": 5,
"priority": "high_impact"
}
]
},
{
"name": "Engineering Team Dashboard",
"description": "Detailed view for engineering license usage",
"layout": "technical",
"refresh_interval": "30s",
"widgets": [
{
"type": "real_time_usage",
"title": "Live License Usage",
"features": ["matlab_core", "solidworks_premium", "ansys_mechanical"],
"display_mode": "gauge"
},
{
"type": "user_activity",
"title": "Active Engineering Users",
"groups": ["engineering", "research"],
"show_details": true
},
{
"type": "queue_status",
"title": "License Queue Status",
"features": ["high_demand_features"],
"alert_threshold": 5
},
{
"type": "feature_utilization",
"title": "Feature Usage Patterns",
"time_range": "last_7_days",
"granularity": "hourly"
}
]
},
{
"name": "License Administrators",
"description": "Administrative monitoring and management view",
"layout": "admin",
"refresh_interval": "15s",
"widgets": [
{
"type": "server_health",
"title": "OLicense Server Status",
"metrics": ["cpu_usage", "memory_usage", "response_time", "connection_count"],
"alert_integration": true
},
{
"type": "license_expiration",
"title": "License Expiration Tracking",
"warning_days": [30, 7, 1],
"grouping": "by_vendor"
},
{
"type": "audit_log",
"title": "Recent License Events",
"events": ["admin_changes", "policy_violations", "security_events"],
"max_entries": 20
},
{
"type": "capacity_planning",
"title": "Capacity Planning Metrics",
"predictions": ["peak_usage", "growth_trends"],
"forecast_period": "90_days"
}
]
},
{
"name": "Financial Analysis",
"description": "Cost analysis and budget tracking",
"layout": "financial",
"refresh_interval": "1h",
"widgets": [
{
"type": "cost_tracking",
"title": "License Spending Analysis",
"breakdown": ["by_department", "by_software", "by_user_group"],
"budget_comparison": true
},
{
"type": "roi_analysis",
"title": "Return on Investment",
"metrics": ["usage_efficiency", "productivity_correlation", "cost_per_outcome"],
"time_range": "last_quarter"
},
{
"type": "optimization_savings",
"title": "Realized Cost Savings",
"tracking": ["implemented_recommendations", "avoided_costs"],
"savings_target": "annual_budget_percentage"
},
{
"type": "vendor_analysis",
"title": "Vendor Portfolio Analysis",
"metrics": ["spend_by_vendor", "utilization_by_vendor", "contract_efficiency"],
"renewal_tracking": true
}
]
}
],
"alert_configurations": [
{
"name": "High Utilization Alert",
"condition": "utilization_rate > 90%",
"duration": "15m",
"severity": "warning",
"channels": ["email", "slack"]
},
{
"name": "License Exhaustion Alert",
"condition": "available_licenses = 0",
"duration": "immediate",
"severity": "critical",
"channels": ["email", "slack", "pagerduty"]
},
{
"name": "Cost Budget Alert",
"condition": "monthly_cost > budget_threshold",
"duration": "daily_check",
"severity": "warning",
"channels": ["email", "teams"]
},
{
"name": "Server Performance Alert",
"condition": "response_time > 5000ms",
"duration": "5m",
"severity": "critical",
"channels": ["email", "slack", "pagerduty"]
}
]
}
""").strip()
return dashboard_config
# Generate custom dashboard configuration
dashboard_content = create_custom_dashboard_config()
print("Custom dashboard configuration ready")
Usage Analytics and Reporting
Comprehensive Usage Analysis
import textwrap
import pandas as pd
from datetime import datetime, timedelta
def create_usage_analytics_script():
"""Create comprehensive usage analytics script for OLicense."""
analytics_script = textwrap.dedent("""
#!/usr/bin/env python3
# OLicense Usage Analytics Script
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
import requests
import json
class OLicenseAnalytics:
def __init__(self, vantage_api_key, olicense_server):
self.api_key = vantage_api_key
self.server = olicense_server
self.base_url = f"https://api.vantage.company.com/v2"
self.headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
def get_usage_data(self, start_date, end_date, granularity='hourly'):
\"\"\"Retrieve usage data from Vantage API.\"\"\"
params = {
'server': self.server,
'start_date': start_date.isoformat(),
'end_date': end_date.isoformat(),
'granularity': granularity,
'include_metadata': True
}
response = requests.get(
f"{self.base_url}/licenses/usage",
headers=self.headers,
params=params
)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"API request failed: {response.status_code}")
def analyze_peak_usage_patterns(self, days=30):
\"\"\"Analyze peak usage patterns and identify optimization opportunities.\"\"\"
end_date = datetime.now()
start_date = end_date - timedelta(days=days)
usage_data = self.get_usage_data(start_date, end_date, 'hourly')
df = pd.DataFrame(usage_data['usage_records'])
# Convert timestamp to datetime
df['timestamp'] = pd.to_datetime(df['timestamp'])
df['hour'] = df['timestamp'].dt.hour
df['day_of_week'] = df['timestamp'].dt.day_name()
# Analyze peak usage by hour
hourly_usage = df.groupby('hour')['concurrent_users'].mean()
peak_hours = hourly_usage.nlargest(5)
# Analyze peak usage by day of week
daily_usage = df.groupby('day_of_week')['concurrent_users'].mean()
# Feature-specific analysis
feature_usage = df.groupby(['feature', 'hour'])['concurrent_users'].mean().unstack()
report = {
'analysis_period': f"{start_date.date()} to {end_date.date()}",
'peak_hours': peak_hours.to_dict(),
'daily_patterns': daily_usage.to_dict(),
'feature_patterns': feature_usage.to_dict(),
'recommendations': self._generate_usage_recommendations(df)
}
return report
def analyze_user_behavior(self, days=30):
\"\"\"Analyze user behavior patterns and identify trends.\"\"\"
end_date = datetime.now()
start_date = end_date - timedelta(days=days)
# Get detailed user session data
params = {
'server': self.server,
'start_date': start_date.isoformat(),
'end_date': end_date.isoformat(),
'include_sessions': True,
'include_user_details': True
}
response = requests.get(
f"{self.base_url}/licenses/user-sessions",
headers=self.headers,
params=params
)
if response.status_code != 200:
raise Exception(f"Failed to retrieve user session data: {response.status_code}")
sessions = response.json()['sessions']
df = pd.DataFrame(sessions)
# Calculate session duration
df['start_time'] = pd.to_datetime(df['start_time'])
df['end_time'] = pd.to_datetime(df['end_time'])
df['duration_hours'] = (df['end_time'] - df['start_time']).dt.total_seconds() / 3600
# User behavior analysis
user_stats = df.groupby('user_id').agg({
'duration_hours': ['count', 'sum', 'mean'],
'feature': lambda x: len(x.unique()),
'start_time': ['min', 'max']
}).round(2)
user_stats.columns = ['session_count', 'total_hours', 'avg_session_hours',
'unique_features', 'first_session', 'last_session']
# Identify usage patterns
heavy_users = user_stats[user_stats['total_hours'] > user_stats['total_hours'].quantile(0.9)]
light_users = user_stats[user_stats['total_hours'] < user_stats['total_hours'].quantile(0.1)]
# Feature adoption analysis
feature_adoption = df.groupby('feature')['user_id'].nunique().sort_values(ascending=False)
behavior_report = {
'total_active_users': len(user_stats),
'heavy_users': len(heavy_users),
'light_users': len(light_users),
'avg_session_duration': df['duration_hours'].mean(),
'feature_adoption': feature_adoption.to_dict(),
'user_segments': {
'heavy_users': heavy_users.to_dict(),
'light_users': light_users.to_dict()
}
}
return behavior_report
def cost_optimization_analysis(self, days=90):
\"\"\"Perform cost optimization analysis and generate recommendations.\"\"\"
end_date = datetime.now()
start_date = end_date - timedelta(days=days)
# Get cost and usage data
cost_data = self._get_cost_data(start_date, end_date)
usage_data = self.get_usage_data(start_date, end_date, 'daily')
df_cost = pd.DataFrame(cost_data['cost_records'])
df_usage = pd.DataFrame(usage_data['usage_records'])
# Merge cost and usage data
df_merged = pd.merge(df_cost, df_usage, on=['date', 'feature'], how='inner')
# Calculate utilization efficiency
df_merged['utilization_rate'] = df_merged['avg_concurrent_users'] / df_merged['max_licenses']
df_merged['cost_per_hour'] = df_merged['daily_cost'] / df_merged['total_usage_hours']
# Identify optimization opportunities
underutilized = df_merged[df_merged['utilization_rate'] < 0.5]
high_cost_per_hour = df_merged[df_merged['cost_per_hour'] > df_merged['cost_per_hour'].quantile(0.8)]
# Calculate potential savings
potential_savings = self._calculate_potential_savings(df_merged)
optimization_report = {
'analysis_period': f"{start_date.date()} to {end_date.date()}",
'total_cost': df_merged['daily_cost'].sum(),
'avg_utilization_rate': df_merged['utilization_rate'].mean(),
'underutilized_features': underutilized[['feature', 'utilization_rate', 'daily_cost']].to_dict('records'),
'high_cost_features': high_cost_per_hour[['feature', 'cost_per_hour', 'daily_cost']].to_dict('records'),
'potential_savings': potential_savings,
'recommendations': self._generate_cost_recommendations(df_merged)
}
return optimization_report
def _generate_usage_recommendations(self, df):
\"\"\"Generate usage optimization recommendations.\"\"\"
recommendations = []
# Analyze queue times
if 'queue_time' in df.columns:
high_queue_features = df[df['queue_time'] > 300].groupby('feature')['queue_time'].mean()
for feature, avg_queue in high_queue_features.items():
recommendations.append({
'type': 'capacity_increase',
'feature': feature,
'issue': f'High average queue time: {avg_queue:.1f} seconds',
'recommendation': 'Consider increasing license count for this feature',
'priority': 'high' if avg_queue > 900 else 'medium'
})
# Analyze off-peak usage
off_peak_hours = [22, 23, 0, 1, 2, 3, 4, 5]
off_peak_usage = df[df['hour'].isin(off_peak_hours)]['concurrent_users'].mean()
peak_usage = df[~df['hour'].isin(off_peak_hours)]['concurrent_users'].mean()
if off_peak_usage > peak_usage * 0.3:
recommendations.append({
'type': 'usage_policy',
'feature': 'all',
'issue': 'Significant off-peak usage detected',
'recommendation': 'Consider implementing time-based usage policies',
'priority': 'medium'
})
return recommendations
def _get_cost_data(self, start_date, end_date):
\"\"\"Retrieve cost data from Vantage API.\"\"\"
params = {
'server': self.server,
'start_date': start_date.isoformat(),
'end_date': end_date.isoformat(),
'include_feature_costs': True
}
response = requests.get(
f"{self.base_url}/licenses/costs",
headers=self.headers,
params=params
)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Failed to retrieve cost data: {response.status_code}")
def _calculate_potential_savings(self, df):
\"\"\"Calculate potential cost savings from optimization.\"\"\"
# Identify licenses that could be reduced
underutilized = df[df['utilization_rate'] < 0.4]
potential_reduction = underutilized['max_licenses'] * 0.2 # Reduce by 20%
savings_per_feature = underutilized.groupby('feature').apply(
lambda x: (x['daily_cost'] * potential_reduction.loc[x.index]).sum()
)
total_potential_savings = savings_per_feature.sum()
return {
'total_potential_annual_savings': total_potential_savings * 365,
'savings_by_feature': savings_per_feature.to_dict(),
'confidence_level': 'medium' # Based on historical patterns
}
def _generate_cost_recommendations(self, df):
\"\"\"Generate cost optimization recommendations.\"\"\"
recommendations = []
# License rightsizing recommendations
underutilized = df[df['utilization_rate'] < 0.5]
for feature in underutilized['feature'].unique():
feature_data = underutilized[underutilized['feature'] == feature]
avg_utilization = feature_data['utilization_rate'].mean()
recommendations.append({
'type': 'license_rightsizing',
'feature': feature,
'current_utilization': f"{avg_utilization:.1%}",
'recommendation': f"Consider reducing license count by {int((1-avg_utilization)*100/2)}%",
'estimated_annual_savings': feature_data['daily_cost'].sum() * 365 * (1-avg_utilization) / 2,
'priority': 'high' if avg_utilization < 0.3 else 'medium'
})
return recommendations
def generate_executive_report(self):
\"\"\"Generate comprehensive executive report.\"\"\"
# Collect data for the last quarter
end_date = datetime.now()
start_date = end_date - timedelta(days=90)
usage_analysis = self.analyze_peak_usage_patterns(90)
behavior_analysis = self.analyze_user_behavior(90)
cost_analysis = self.cost_optimization_analysis(90)
executive_report = {
'report_date': datetime.now().isoformat(),
'reporting_period': f"{start_date.date()} to {end_date.date()}",
'executive_summary': {
'total_users': behavior_analysis['total_active_users'],
'total_cost': cost_analysis['total_cost'],
'avg_utilization': f"{cost_analysis['avg_utilization_rate']:.1%}",
'potential_savings': cost_analysis['potential_savings']['total_potential_annual_savings']
},
'usage_insights': usage_analysis,
'user_behavior': behavior_analysis,
'cost_optimization': cost_analysis
}
return executive_report
# Example usage
if __name__ == "__main__":
analytics = OLicenseAnalytics(
vantage_api_key="your-vantage-api-key",
olicense_server="olicense-production"
)
# Generate comprehensive report
report = analytics.generate_executive_report()
# Save report
with open(f"/opt/olicense/reports/executive_report_{datetime.now().strftime('%Y%m%d')}.json", 'w') as f:
json.dump(report, f, indent=2, default=str)
print("Executive report generated successfully")
""").strip()
return analytics_script
# Generate analytics script
analytics_content = create_usage_analytics_script()
print("Comprehensive usage analytics script ready")
Automated Reporting System
# Set up automated reporting for OLicense
sudo -u olicense mkdir -p /opt/olicense/reports/{daily,weekly,monthly,quarterly}
# Create automated daily report script
sudo -u olicense tee /opt/olicense/bin/daily-report.sh <<'EOF'
#!/bin/bash
# Daily OLicense Usage Report
REPORT_DATE=$(date '+%Y-%m-%d')
REPORT_DIR="/opt/olicense/reports/daily"
VANTAGE_CLI="/usr/local/bin/vantage"
# Generate daily usage report
"$VANTAGE_CLI" licenses report olicense-production \
--type daily \
--date "$REPORT_DATE" \
--format json \
--output "$REPORT_DIR/usage_report_$REPORT_DATE.json" \
--include-cost-data \
--include-user-details \
--include-performance-metrics
# Generate summary email
cat > "/tmp/daily_summary_$REPORT_DATE.txt" <<SUMMARY
OLicense Daily Summary - $REPORT_DATE
Key Metrics:
- Peak concurrent users: $(jq '.peak_concurrent_users' "$REPORT_DIR/usage_report_$REPORT_DATE.json")
- Total license hours: $(jq '.total_license_hours' "$REPORT_DIR/usage_report_$REPORT_DATE.json")
- Daily cost: \$$(jq '.total_daily_cost' "$REPORT_DIR/usage_report_$REPORT_DATE.json")
- Average utilization: $(jq '.average_utilization_rate' "$REPORT_DIR/usage_report_$REPORT_DATE.json")%
Top Features by Usage:
$(jq -r '.top_features[] | "\(.feature): \(.usage_hours) hours"' "$REPORT_DIR/usage_report_$REPORT_DATE.json")
Alerts:
$(jq -r '.alerts[]? | "- \(.message)"' "$REPORT_DIR/usage_report_$REPORT_DATE.json")
Full report available at: $REPORT_DIR/usage_report_$REPORT_DATE.json
SUMMARY
# Send email summary
mail -s "OLicense Daily Report - $REPORT_DATE" \
license-admins@company.com < "/tmp/daily_summary_$REPORT_DATE.txt"
# Cleanup
rm "/tmp/daily_summary_$REPORT_DATE.txt"
EOF
# Create weekly optimization report
sudo -u olicense tee /opt/olicense/bin/weekly-optimization-report.sh <<'EOF'
#!/bin/bash
# Weekly OLicense Optimization Report
REPORT_DATE=$(date '+%Y-W%U')
REPORT_DIR="/opt/olicense/reports/weekly"
VANTAGE_CLI="/usr/local/bin/vantage"
# Generate comprehensive weekly analysis
"$VANTAGE_CLI" licenses optimization-report olicense-production \
--period last-7-days \
--format pdf \
--output "$REPORT_DIR/optimization_report_$REPORT_DATE.pdf" \
--include-recommendations \
--include-cost-analysis \
--include-trend-analysis \
--include-benchmarks
# Generate optimization recommendations
"$VANTAGE_CLI" licenses optimize olicense-production \
--analyze-period last-7-days \
--output-format json \
--output "$REPORT_DIR/recommendations_$REPORT_DATE.json" \
--include-savings-potential \
--include-risk-assessment
# Create action items
python3 << 'PYTHON_EOF'
import json
import datetime
# Load recommendations
with open(f'/opt/olicense/reports/weekly/recommendations_{datetime.datetime.now().strftime("%Y-W%U")}.json', 'r') as f:
recommendations = json.load(f)
# Extract high-priority items
high_priority = [r for r in recommendations['recommendations'] if r['priority'] == 'high']
# Generate action items email
action_items = []
for item in high_priority:
action_items.append(f"- {item['type']}: {item['recommendation']} (Potential savings: ${item.get('estimated_savings', 'TBD')})")
with open('/tmp/weekly_action_items.txt', 'w') as f:
f.write(f"OLicense Weekly Optimization Action Items - {datetime.datetime.now().strftime('%Y-W%U')}\n\n")
f.write("High Priority Recommendations:\n")
f.write("\n".join(action_items))
f.write(f"\n\nTotal potential annual savings: ${recommendations.get('total_potential_savings', 'TBD')}")
f.write("\n\nFull report attached.")
print("Action items generated")
PYTHON_EOF
# Send weekly report
mail -s "OLicense Weekly Optimization Report - $REPORT_DATE" \
-a "$REPORT_DIR/optimization_report_$REPORT_DATE.pdf" \
license-admins@company.com,management@company.com < /tmp/weekly_action_items.txt
rm /tmp/weekly_action_items.txt
EOF
# Schedule automated reports
sudo -u olicense crontab -l 2>/dev/null | grep -v olicense-reports | sudo -u olicense crontab -
sudo -u olicense crontab -l 2>/dev/null; echo "0 7 * * * /opt/olicense/bin/daily-report.sh" | sudo -u olicense crontab -
sudo -u olicense crontab -l 2>/dev/null; echo "0 8 * * 1 /opt/olicense/bin/weekly-optimization-report.sh" | sudo -u olicense crontab -
sudo chmod +x /opt/olicense/bin/{daily-report.sh,weekly-optimization-report.sh}
Performance Monitoring
Server Performance Metrics
# Configure comprehensive OLicense server monitoring
vantage licenses monitor-performance olicense-production \
--metrics "
cpu_usage,
memory_usage,
disk_io,
network_io,
response_time,
concurrent_connections,
license_operations_per_second,
database_performance,
api_response_times
" \
--sampling-interval 30s \
--retention-period 90days \
--enable-alerting
# Set up performance baselines
vantage licenses set-baselines olicense-production \
--baseline-period last-30-days \
--metrics "response_time,cpu_usage,memory_usage" \
--percentile 95 \
--auto-update weekly
# Configure performance alerts
vantage licenses configure-alerts olicense-production \
--alert-type performance \
--conditions "
response_time > 5000ms for 5min,
cpu_usage > 80% for 10min,
memory_usage > 90% for 5min,
disk_usage > 85%,
concurrent_connections > 900
" \
--channels email,slack \
--escalation-policy standard
Database Performance Monitoring
import textwrap
def create_database_monitoring_script():
"""Create database performance monitoring script for OLicense."""
monitoring_script = textwrap.dedent("""
#!/usr/bin/env python3
# OLicense Database Performance Monitoring
import psycopg2
import time
import json
import logging
from datetime import datetime, timedelta
import requests
class OLicenseDatabaseMonitor:
def __init__(self, db_config, vantage_config):
self.db_config = db_config
self.vantage_config = vantage_config
self.logger = self._setup_logging()
def _setup_logging(self):
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('/opt/olicense/logs/db_monitor.log'),
logging.StreamHandler()
]
)
return logging.getLogger(__name__)
def check_database_performance(self):
\"\"\"Monitor OLicense database performance metrics.\"\"\"
try:
conn = psycopg2.connect(**self.db_config)
cursor = conn.cursor()
# Check connection count
cursor.execute(\"\"\"
SELECT count(*) as active_connections
FROM pg_stat_activity
WHERE datname = %s AND state = 'active';
\"\"\", (self.db_config['database'],))
active_connections = cursor.fetchone()[0]
# Check long-running queries
cursor.execute(\"\"\"
SELECT count(*) as long_queries
FROM pg_stat_activity
WHERE datname = %s
AND state = 'active'
AND now() - query_start > interval '30 seconds';
\"\"\", (self.db_config['database'],))
long_queries = cursor.fetchone()[0]
# Check database size
cursor.execute(\"\"\"
SELECT pg_size_pretty(pg_database_size(%s)) as db_size,
pg_database_size(%s) as db_size_bytes;
\"\"\", (self.db_config['database'], self.db_config['database']))
db_size_info = cursor.fetchone()
# Check table sizes (top 10)
cursor.execute(\"\"\"
SELECT schemaname, tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size,
pg_total_relation_size(schemaname||'.'||tablename) as size_bytes
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
LIMIT 10;
\"\"\")
table_sizes = cursor.fetchall()
# Check index usage
cursor.execute(\"\"\"
SELECT schemaname, tablename,
idx_scan, seq_scan,
CASE WHEN seq_scan + idx_scan > 0
THEN round(100.0 * idx_scan / (seq_scan + idx_scan), 2)
ELSE 0 END as index_usage_pct
FROM pg_stat_user_tables
ORDER BY seq_scan DESC
LIMIT 10;
\"\"\")
index_usage = cursor.fetchall()
# Check slow queries from pg_stat_statements (if available)
try:
cursor.execute(\"\"\"
SELECT query, calls, total_time, mean_time, rows
FROM pg_stat_statements
WHERE dbid = (SELECT oid FROM pg_database WHERE datname = %s)
ORDER BY mean_time DESC
LIMIT 10;
\"\"\", (self.db_config['database'],))
slow_queries = cursor.fetchall()
except psycopg2.ProgrammingError:
slow_queries = []
self.logger.warning("pg_stat_statements extension not available")
# Compile performance metrics
metrics = {
'timestamp': datetime.now().isoformat(),
'active_connections': active_connections,
'long_running_queries': long_queries,
'database_size_bytes': db_size_info[1],
'database_size_human': db_size_info[0],
'largest_tables': [
{
'schema': t[0],
'table': t[1],
'size_human': t[2],
'size_bytes': t[3]
} for t in table_sizes
],
'index_usage': [
{
'schema': t[0],
'table': t[1],
'idx_scan': t[2],
'seq_scan': t[3],
'index_usage_pct': t[4]
} for t in index_usage
],
'slow_queries': [
{
'query': q[0][:200] + '...' if len(q[0]) > 200 else q[0],
'calls': q[1],
'total_time': q[2],
'mean_time': q[3],
'rows': q[4]
} for q in slow_queries
]
}
cursor.close()
conn.close()
# Send metrics to Vantage
self._send_metrics_to_vantage(metrics)
# Check for performance issues
self._check_performance_issues(metrics)
return metrics
except Exception as e:
self.logger.error(f"Database monitoring failed: {e}")
return None
def _send_metrics_to_vantage(self, metrics):
\"\"\"Send database metrics to Vantage for analysis.\"\"\"
try:
headers = {
'Authorization': f"Bearer {self.vantage_config['api_key']}",
'Content-Type': 'application/json'
}
payload = {
'server': 'olicense-production',
'metric_type': 'database_performance',
'metrics': metrics
}
response = requests.post(
f"{self.vantage_config['api_endpoint']}/licenses/metrics",
headers=headers,
json=payload,
timeout=30
)
if response.status_code == 200:
self.logger.info("Database metrics sent to Vantage successfully")
else:
self.logger.error(f"Failed to send metrics to Vantage: {response.status_code}")
except Exception as e:
self.logger.error(f"Failed to send metrics to Vantage: {e}")
def _check_performance_issues(self, metrics):
\"\"\"Check for performance issues and generate alerts.\"\"\"
issues = []
# Check connection count
if metrics['active_connections'] > 80: # Assuming max 100 connections
issues.append({
'type': 'high_connection_count',
'severity': 'warning' if metrics['active_connections'] < 90 else 'critical',
'message': f"High database connection count: {metrics['active_connections']}"
})
# Check long-running queries
if metrics['long_running_queries'] > 5:
issues.append({
'type': 'long_running_queries',
'severity': 'warning',
'message': f"Multiple long-running queries detected: {metrics['long_running_queries']}"
})
# Check database size (alert if > 50GB)
if metrics['database_size_bytes'] > 50 * 1024 * 1024 * 1024:
issues.append({
'type': 'large_database_size',
'severity': 'info',
'message': f"Database size is large: {metrics['database_size_human']}"
})
# Check index usage
poor_index_usage = [t for t in metrics['index_usage'] if t['index_usage_pct'] < 50 and t['seq_scan'] > 1000]
if poor_index_usage:
issues.append({
'type': 'poor_index_usage',
'severity': 'warning',
'message': f"Tables with poor index usage: {[t['table'] for t in poor_index_usage]}"
})
# Log issues
for issue in issues:
self.logger.warning(f"Performance issue detected: {issue['message']}")
return issues
if __name__ == "__main__":
db_config = {
'host': 'localhost',
'port': 5432,
'database': 'olicense_db',
'user': 'olicense_user',
'password': 'secure_password_here'
}
vantage_config = {
'api_endpoint': 'https://api.vantage.company.com/v2',
'api_key': 'your-vantage-api-key'
}
monitor = OLicenseDatabaseMonitor(db_config, vantage_config)
metrics = monitor.check_database_performance()
if metrics:
print("Database monitoring completed successfully")
# Save metrics locally
with open('/opt/olicense/logs/db_metrics.json', 'w') as f:
json.dump(metrics, f, indent=2)
else:
print("Database monitoring failed")
""").strip()
return monitoring_script
# Generate database monitoring script
db_monitoring_content = create_database_monitoring_script()
print("Database monitoring script ready")
Cost Tracking and Optimization
Real-time Cost Monitoring
# Configure real-time cost tracking for OLicense
vantage licenses cost-tracking olicense-production \
--enable-real-time-costs \
--cost-model usage_based \
--billing-granularity hourly \
--cost-allocation department \
--budget-alerts enabled \
--optimization-suggestions enabled
# Set up cost budgets and alerts
vantage licenses set-budgets olicense-production \
--monthly-budget 50000 \
--quarterly-budget 150000 \
--annual-budget 600000 \
--alert-thresholds "75%,90%,95%,100%" \
--budget-tracking department,project,user_group
# Configure cost optimization automation
vantage licenses cost-optimization olicense-production \
--auto-optimization enabled \
--optimization-frequency daily \
--savings-target 15% \
--risk-tolerance medium \
--approval-required true \
--notification-channels email,slack
Advanced Cost Analytics
import textwrap
def create_cost_analytics_dashboard():
"""Create advanced cost analytics dashboard configuration."""
cost_dashboard = textwrap.dedent("""
# Advanced Cost Analytics Configuration
# /opt/vantage/config/olicense-cost-analytics.json
{
"cost_analytics": {
"tracking_granularity": "hourly",
"cost_allocation_methods": [
{
"name": "department_based",
"rules": [
{
"condition": "user_group = 'engineering'",
"allocation": "Engineering Department",
"cost_center": "ENG-001"
},
{
"condition": "user_group = 'research'",
"allocation": "R&D Department",
"cost_center": "RND-001"
},
{
"condition": "user_group = 'students'",
"allocation": "Training Department",
"cost_center": "TRN-001"
}
]
},
{
"name": "project_based",
"rules": [
{
"condition": "project_code IS NOT NULL",
"allocation": "project_code",
"cost_center": "project_cost_center"
}
]
}
],
"cost_models": [
{
"name": "matlab_toolboxes",
"type": "tiered_usage",
"tiers": [
{"min_hours": 0, "max_hours": 100, "rate_per_hour": 5.00},
{"min_hours": 100, "max_hours": 500, "rate_per_hour": 4.50},
{"min_hours": 500, "max_hours": 1000, "rate_per_hour": 4.00},
{"min_hours": 1000, "max_hours": null, "rate_per_hour": 3.50}
]
},
{
"name": "solidworks_premium",
"type": "subscription_based",
"monthly_cost": 2000,
"allocation_method": "equal_split"
},
{
"name": "ansys_mechanical",
"type": "usage_based",
"cost_per_hour": 12.00,
"minimum_charge": 1.0
}
],
"optimization_rules": [
{
"name": "underutilized_licenses",
"condition": "utilization_rate < 30% for 30 days",
"action": "suggest_license_reduction",
"parameters": {
"reduction_percentage": 20,
"minimum_licenses": 1
}
},
{
"name": "peak_demand_management",
"condition": "queue_time > 300 seconds",
"action": "suggest_license_increase",
"parameters": {
"increase_percentage": 10,
"cost_benefit_threshold": 0.8
}
},
{
"name": "cross_feature_optimization",
"condition": "feature_correlation > 0.8",
"action": "suggest_license_bundling",
"parameters": {
"correlation_threshold": 0.8,
"min_usage_overlap": 50
}
}
],
"reporting": {
"executive_dashboard": {
"metrics": [
"total_monthly_cost",
"cost_per_user",
"roi_metrics",
"budget_variance",
"optimization_savings"
],
"update_frequency": "daily"
},
"department_dashboards": {
"metrics": [
"department_costs",
"user_activity",
"feature_utilization",
"cost_trends"
],
"update_frequency": "hourly"
},
"automated_reports": [
{
"name": "monthly_cost_summary",
"schedule": "0 9 1 * *",
"recipients": ["finance@company.com", "license-admins@company.com"],
"format": "pdf",
"include_recommendations": true
},
{
"name": "weekly_optimization_opportunities",
"schedule": "0 9 * * 1",
"recipients": ["license-admins@company.com"],
"format": "json",
"include_implementation_guide": true
}
]
}
}
}
""").strip()
return cost_dashboard
# Generate cost analytics configuration
cost_config = create_cost_analytics_dashboard()
print("Advanced cost analytics configuration ready")
Next Steps
With comprehensive OLicense monitoring and analytics configured, you can:
- High Availability: Configure clustering and disaster recovery
- Troubleshooting: Learn to resolve monitoring and performance issues
- OLicense Introduction: Return to overview
Monitoring Best Practice: OLicense generates rich usage and performance data that becomes most valuable when integrated with Vantage's advanced analytics platform. Focus on establishing baseline performance metrics early and leveraging predictive analytics for proactive license management. The combination of real-time monitoring with historical trend analysis enables both tactical optimization and strategic planning for your software license portfolio.