def server_drilldown(url_key, server_id=None, compound_service_id=None, timezone=None): timezone = request.args.get('timezone', None) if timezone: tz = pytz.timezone(str(timezone)) inline = server_id or compound_service_id server_id = server_id or request.args.get('server_id', None) compound_service_id = compound_service_id or request.args.get('compound_service_id', None) item = None try: pr = masterdb.PublicReportV2.selectBy(url_key=url_key)[0] customer = pr.customer if customer.status == 'disabled': raise Exception contact = customer.getMainUser().contact if pr.require_login and "tg-visit" not in request.cookies: url = customer.brand.controlpanel_url if customer.brand else config.CP_BASE_URL return redirect("%s/login?forward_url=%s" % (url.strip("/"), request.url)) # Extract the item if server_id: item = masterdb.Server.get(int(server_id)) elif compound_service_id: item = masterdb.CompoundService.get(int(compound_service_id)) else: return redirect(url_for('server_group_overview', url_key=url_key)) if item not in pr.all_items: raise Exception # Today stats local_end_time = contact.toLocalTime(datetime.now()).replace(hour=23, minute=59, second=59) local_start_time = local_end_time.replace(hour=0, minute=0, second=0) end_time = contact.fromLocalTime(local_end_time).replace(tzinfo=None) start_time = contact.fromLocalTime(local_start_time).replace(tzinfo=None) end_time = datetime.now() today_alerts = item.get_events( exclude_anomalies=not pr.include_resources, custom_filter=AND(masterdb.Event.q.start_time <= end_time, masterdb.Event.q.status == 'confirmed') ) recent_alerts = item.get_events( exclude_anomalies=not pr.include_resources, custom_filter=IN(masterdb.Event.q.status, ['confirmed', 'resolved']), count=1 ) current_alerts = len(item.get_events( exclude_anomalies=not pr.include_resources, custom_filter=AND(masterdb.Event.q.start_time <= end_time + relativedelta(seconds=-5), masterdb.Event.q.status == 'confirmed') )) if recent_alerts: if recent_alerts[0].end_time: latest_outage = datetime.now() - recent_alerts[0].end_time latest_outage = masterdb.getApproximateDuration(latest_outage, sig_digits=2, short_labels=True) else: latest_outage = 'Currently Down' today_alerts_count = item.get_events_count( exclude_anomalies=not pr.include_resources, custom_filter=OR(AND(masterdb.Event.q.start_time <= start_time, masterdb.Event.q.status == 'confirmed'), AND(masterdb.Event.q.start_time >= start_time, masterdb.Event.q.start_time <= end_time, IN(masterdb.Event.q.status, ['confirmed', 'resolved']))) ) current_month_start_range = end_time.replace(day=1, hour=0, second=0, minute=0) this_month_alerts_count = item.get_events_count( exclude_anomalies=not pr.include_resources, custom_filter=OR(AND(masterdb.Event.q.start_time <= current_month_start_range, masterdb.Event.q.status == 'confirmed'), AND(masterdb.Event.q.start_time >= current_month_start_range, masterdb.Event.q.start_time <= end_time, IN(masterdb.Event.q.status, ['confirmed', 'resolved']))) ) current_month_heatmap_data = masterdb.HeatmapCache.get_results_in_range(item, start_time, end_time, pr.include_resources) total_down_time = 0 for key in current_month_heatmap_data: total_down_time += current_month_heatmap_data[key].total_downtime if total_down_time > 0: delta_str = masterdb.getApproximateDuration(timedelta(seconds=total_down_time), sig_digits=None, short_labels=True) today_availability = "%.0f%%" % (max(item.getAvailability(start_time, end_time, include_anomalies=pr.include_resources, with_excluded_outages=False)[0], 0.0) * 100) # Maintenance schedules current_maintenance = [] for mp in masterdb.MaintenancePeriod.select(AND(masterdb.MaintenancePeriod.q.customerID == customer.id, masterdb.MaintenancePeriod.q.status == 'active'), orderBy=masterdb.MaintenancePeriod.q.start_time): ms = mp.maintenance_schedule if ms.show_in_public_report and item in ms.servers + ms.compound_services: current_maintenance.append(mp) # Outages info outages_info = "" for alert in today_alerts: description = alert.getNewDescription(exclude_agent_heartbeats=True, join_str="<br/><span style='margin-left: 20px'></span>", show_full_fqdn=not pr.hide_fqdn) if isinstance(alert, masterdb.ServerOutage) else alert.description outages_info += '<p style="color:black;!important"><i class="glyphicon glyphicon-fire"></i> %s' % (description or alert.alert_label) logs = [log for log in alert.outage_logs if log.public] if logs: outages_info += ":<ul>" for log in logs: local_time = contact.formatLocalTime(log.timestamp) if timezone: local_time = log.timestamp.replace(tzinfo=pytz.utc).astimezone(tz) outages_info += '<li style="color:black;!important">[%s] %s</li>' % (local_time, log.message) outages_info += "</ul>" outages_info += "</p>" # Network service graph mps = [mp.id for mp in item.active_monitor_points if not mp.is_panopta_agent_heartbeat] series, labels, start, end, title, width, height, label_incr_count, grid_spacing, bgcolor, zones = \ graph_utils.ServerGraphHighCharts(mps, 'hour', None, item.id, 'performance', timezone=timezone) for s in series: del s['monitor_point_obj'] graph = dict( title = title, yAxisTitle = title, xAxisLabels = labels, series = series, majorTickStep = label_incr_count, minorTickStep = grid_spacing, zones = zones ) network_service_json_data = json.dumps(graph) # Server resource graph if item.isServer(): srs = [sr.id for sr in item.active_server_resources] series, labels, start, end, title, width, height, label_incr_count, grid_spacing, bgcolor = \ graph_utils.ServerResourceGraphHighCharts(srs, 'hour', timezone=timezone) for s, d in series.items(): for val in d: del val['server_resource'] graph = dict( title = title, yAxisTitle = title, xAxisLabels = labels, series = series, majorTickStep = label_incr_count, minorTickStep = grid_spacing ) server_resource_json_data = json.dumps(graph) # Stats table stats_list = [ ["Last 24 Hours", 1], ["Last 7 Days", 7], ["Last 30 Days", 30] ] stats = [] end_time = datetime.now() for n, d in stats_list: start_time = end_time + timedelta(days=-d, seconds=1) alerts_count = item.get_events_count( exclude_anomalies=not pr.include_resources, custom_filter=OR(AND(masterdb.Event.q.start_time <= start_time, masterdb.Event.q.status == 'confirmed'), AND(masterdb.Event.q.start_time >= start_time, masterdb.Event.q.start_time <= end_time, IN(masterdb.Event.q.status, ['confirmed', 'resolved']))) ) availability = calculate_availability(end_time, item, pr, start_time) stats.append([n, availability, alerts_count]) historical_stats_list = [] for i in range(0, 12): start_range = end_time.replace(day=1, hour=0, second=0, minute=0) + relativedelta(months=-i) if start_range.year > item.created.year or (start_range.year == item.created.year and start_range.month >= item.created.month): end_range = start_range + relativedelta(months=+1, seconds=-1) label = None if i == 0: label = 'Current Month' end_range = end_time elif i == 1: label = 'Last Month' else: label = (end_time + relativedelta(months=-i)).strftime("%B") availability = calculate_availability(end_range, item, pr, start_range) historical_stats_list.append([label,availability]) # Heatmap local_end_time = contact.toLocalTime(datetime.now()).replace(hour=23, minute=59, second=59) local_start_time = (local_end_time + timedelta(weeks=-24, days=1)).replace(hour=0, minute=0, second=0) end_time = contact.fromLocalTime(local_end_time).replace(tzinfo=None) start_time = contact.fromLocalTime(local_start_time).replace(tzinfo=None) yAxisLabels = [] for weekday in range(7): next_day = local_end_time + relativedelta(days=-weekday) yAxisLabels.append(next_day.strftime("%A")) #heatmap_data = masterdb.HeatmapCache.create_cache_in_range(item, start_time, end_time, pr.include_resources) #heatmap_data = dict([(contact.toLocalTime(hc.timestamp).strftime("%Y-%m-%d"), hc) for hc in heatmap_data]) heatmap_data = masterdb.HeatmapCache.get_results_in_range(item, start_time, end_time, pr.include_resources) series = [] xAxisLabels = [] start_date = start_time for col in range(24): label = '' for row in range(7): end_date = start_date + relativedelta(days=1, seconds=-1) local_date = contact.toLocalTime(end_date) if local_date.day == 1: label = local_date.strftime("%b") tooltip = '<b>%s</b><br>' % local_date.strftime("%A %B %d, %Y") item_id = item.id if item.isServer() else -item.id url = "%s?date=%s" % (url_for('server_drilldown_data', url_key=url_key, item_id=item_id), str(start_date)) start_date = start_date + timedelta(days=1) hc = heatmap_data.get(local_date.strftime("%Y-%m-%d"), None) if hc and hc.outages_count: tooltip += '%s outages (%s)' % (hc.outages_count, hc.downtime_duration) elif hc: tooltip += 'No outages' else: tooltip += 'No data' series.append({ 'x': col, 'y': row, 'color': hc.status_color if hc else '#ffffff', 'tooltip': tooltip, 'url': url }) xAxisLabels.append(label) graph = dict( xAxisLabels = xAxisLabels, yAxisLabels = yAxisLabels[::-1], series = series, today_url = url, ) heatmap_json_data = json.dumps(graph) # Render template report_body = render_template('server_drilldown.html', **locals()) if not inline: template = pr.template.decode("utf-8") response = template.replace('REPORT_BODY', unicode(report_body)) else: response = unicode(report_body) return response except: app.log("Uncought exception in PublicReport:\n%s" % traceback.format_exc(), "CRITICAL") return redirect("http://www.panopta.com")
def server_drilldown_data(url_key, item_id): timezone = request.args.get("timezone", '') if timezone: tz = pytz.timezone(str(timezone)) try: pr = masterdb.PublicReportV2.selectBy(url_key=url_key)[0] customer = pr.customer if customer.status == 'disabled': raise Exception contact = customer.getMainUser().contact if pr.require_login and "tg-visit" not in request.cookies: url = customer.brand.controlpanel_url if customer.brand else config.CP_BASE_URL return redirect("%s/login?forward_url=%s" % (url.strip("/"), request.url)) # Extract the item item_id = int(item_id) if item_id > 0: item = masterdb.Server.get(item_id) else: item = masterdb.CompoundService.get(abs(item_id)) if item not in pr.all_items: raise Exception date = parse(request.args.get('date', str(datetime.now()))) local_start_time = contact.toLocalTime(date).replace(hour=0, minute=0, second=0) local_end_time = local_start_time.replace(hour=23, minute=59, second=59) start_time = contact.fromLocalTime(local_start_time).replace(tzinfo=None) end_time = contact.fromLocalTime(local_end_time).replace(tzinfo=None) end_time = datetime.now() alerts = item.get_events( exclude_anomalies=not pr.include_resources, custom_filter=OR(AND(masterdb.Event.q.start_time <= start_time, masterdb.Event.q.status == 'confirmed'), AND(masterdb.Event.q.start_time >= start_time, masterdb.Event.q.start_time <= end_time, IN(masterdb.Event.q.status, ['confirmed', 'resolved']))) ) availability = "%.0f%%" % (max(item.getAvailability(start_time, end_time, include_anomalies=pr.include_resources, with_excluded_outages=False)[0], 0.0) * 100) alert_list = [] for alert in alerts: localized_start = contact.toLocalTime(alert.start_time) localized_end = contact.toLocalTime(alert.end_time) if timezone: localized_start = alert.start_time.replace(tzinfo=pytz.utc) localized_start = localized_start.astimezone(tz) localized_end = alert.end_time.replace(tzinfo=pytz.utc) localized_end = localized_end.astimezone(tz) duration = masterdb.getApproximateDuration((alert.end_time or min(datetime.now(), end_time)) - alert.start_time, sig_digits=None, short_labels=True) description = alert.getNewDescription(exclude_agent_heartbeats=True, show_full_fqdn=not pr.hide_fqdn) if isinstance(alert, masterdb.ServerOutage) else alert.description alert_list.append({ 'start_time': localized_start.strftime("%Y-%m-%d %H:%M:%S"), 'end_time': localized_end.strftime("%Y-%m-%d %H:%M:%S") if alert.end_time else None, 'duration': duration, 'description': description or alert.alert_label, }) return jsonify( availability = availability, alerts_count = len(alerts), title_date = local_start_time.strftime("%B %d, %Y"), alerts = alert_list ) except: app.log("Uncought exception in PublicReport:\n%s" % traceback.format_exc(), "CRITICAL") return jsonify( date = '', availability = '100%', alerts_count = 0, title_date = '', alerts = [] )
def server_group_overview(url_key=None, pr=None): try: if url_key: pr = masterdb.PublicReportV2.selectBy(url_key=url_key)[0] elif request.host: pr = masterdb.PublicReportV2.selectBy(hostname=request.host.split(":")[0])[0] url_key = pr.url_key customer = pr.customer if customer.status == 'disabled': raise Exception contact = customer.getMainUser().contact if pr.require_login and "tg-visit" not in request.cookies: url = customer.brand.controlpanel_url if customer.brand else config.CP_BASE_URL return redirect("%s/login?forward_url=%s" % (url.strip("/"), request.url)) local_end_time = contact.toLocalTime(datetime.now()).replace(hour=23, minute=59, second=59) local_start_time = (local_end_time + timedelta(days=-6)).replace(hour=0, minute=0, second=0) end_time = contact.fromLocalTime(local_end_time).replace(tzinfo=None) start_time = contact.fromLocalTime(local_start_time).replace(tzinfo=None) # Get dates for the past week days = [] day = local_end_time for i in range(7): if i == 0: days.append("Today") elif i == 1: days.append("Yesterday") else: days.append(day.strftime("%a - %m/%d")) day += timedelta(days=-1) # Get server group data server_groups = pr.groups.items() server_groups.sort(key=lambda (sg, items): sg.name.lower()) for sg, items in server_groups: sg.detail_link = (url_for('server_group_drilldown', url_key=url_key, server_group_id=sg.id)) # Sorting if pr.sort_order == 'avail_asc': items.sort(key=lambda item: [max(item.getAvailability(start_time, end_time, include_anomalies=pr.include_resources)[0], 0.0), item.formatted_name.lower()]) elif pr.sort_order == 'avail_desc': items.sort(key=lambda item: [-max(item.getAvailability(start_time, end_time, include_anomalies=pr.include_resources)[0], 0.0), item.formatted_name.lower()]) else: items.sort(key=lambda item: item.formatted_name.lower()) for item in items: if item.status != 'active' or (item.isServer() and item.isTemplate()): continue item.active_alerts_count = item.get_events_count(status='confirmed', exclude_anomalies=not pr.include_resources) # Getting detail and cp links if item.isServer(): item.detail_link = "%s?server_id=%s" % (url_for('server_drilldown', url_key=url_key), item.id) item.cp_link = "%s/report/ServerReport?server_id=%s" % (config.CP_BASE_URL, item.id) else: item.detail_link = "%s?compound_service_id=%s" % (url_for('server_drilldown', url_key=url_key), item.id) item.cp_link = "%s/report/CompoundServiceReport?compound_service_id=%s" % (config.CP_BASE_URL, item.id) # Getting stats for each item in each day stats = [] end = end_time for i in range(7): start = end + timedelta(days=-1, seconds=1) alerts = item.get_events( exclude_anomalies=not pr.include_resources, custom_filter=OR(AND(masterdb.Event.q.start_time <= start, masterdb.Event.q.status == 'confirmed'), AND(masterdb.Event.q.start_time >= start, masterdb.Event.q.start_time <= end, IN(masterdb.Event.q.status, ['confirmed', 'resolved']))) ) # Getting status color if alerts: color = "red" if any([alert.severity == "critical" for alert in alerts]) else "orange" else: color = "green" # Getting tooltip info tooltip = '<div class="alert alert-%s"><a href="%s">%s</a></div>' % ("success" if not alerts else "danger", item.cp_link, item.name if pr.hide_fqdn else item.formatted_name) if not alerts: text = 'No outages' log_text = "" else: log_text = "" critical_outages_count = 0 critical_outages_duration = timedelta(seconds=0) warning_outages_count = 0 warning_outages_duration = timedelta(seconds=0) for alert in alerts: et = alert.end_time or min(datetime.now(), end) if alert.severity == "critical": critical_outages_count += 1 if et > alert.start_time: critical_outages_duration += (et - alert.start_time) else: warning_outages_count += 1 if et > alert.start_time: warning_outages_duration += (et - alert.start_time) description = alert.getNewDescription(exclude_agent_heartbeats=True, show_full_fqdn=not pr.hide_fqdn) if isinstance(alert, masterdb.ServerOutage) else alert.description log_text += '<p><i class="glyphicon glyphicon-fire"></i> <a href="%s/outage/Outage?outage_id=%s">%s</a>' % (config.CP_BASE_URL, alert.alert_id, description or alert.alert_label) logs = [log for log in alert.outage_logs if log.public] if logs: log_text += ":<ul>" for log in logs: log_text += "<li>[<span class='local-date'>%s</span>] %s</li>" % (contact.formatLocalTime(log.timestamp), log.message) log_text += "</ul>" log_text += "</p>" log_text += "<span class='hidden contact-timezone'>%s</span>" % contact.getTimezoneObject() critical_outages_duration = masterdb.getApproximateDuration(critical_outages_duration, sig_digits=None, short_labels=True) warning_outages_duration = masterdb.getApproximateDuration(warning_outages_duration, sig_digits=None, short_labels=True) text = "%s critical outage%s (%s)" % (critical_outages_count, 's' if critical_outages_count > 1 else '', critical_outages_duration) text += "<br>%s warnings (%s)" % (warning_outages_count, warning_outages_duration) tooltip += '<p class="text-center"><strong>%s</strong></p>' % text if log_text: tooltip += "<hr/>" + log_text stats.append({"color": color, "tooltip": tooltip}) end += timedelta(days=-1) item.stats = stats # Render template report_body = render_template('overview.html', **locals()) template = pr.template.decode("utf-8") response = template.replace('REPORT_BODY', unicode(report_body)) return response except: app.log("Uncought exception in PublicReport:\n%s" % traceback.format_exc(), "CRITICAL") return redirect("http://www.panopta.com")