예제 #1
0
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")
예제 #2
0
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 = []
        )
예제 #3
0
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")