示例#1
0
def render_graph_content_html(graph_recipe, graph_data_range,
                              graph_render_options):
    output = ""
    try:
        graph_artwork = artwork.compute_graph_artwork(graph_recipe,
                                                      graph_data_range,
                                                      graph_render_options)
        main_graph_html = render_graph_or_error_html(graph_artwork,
                                                     graph_data_range,
                                                     graph_render_options)

        previews = graph_render_options["show_time_range_previews"]
        if graph_recipe['specification'][0] == 'forecast':
            previews = False

        if previews:
            output += "<div class=\"graph_with_timeranges\">"
            output += main_graph_html
            output += render_time_range_selection(graph_recipe,
                                                  graph_render_options)
            output += "</div>"
        else:
            output += main_graph_html

    except livestatus.MKLivestatusNotFoundError:
        output += render_graph_error_html(
            _("Cannot fetch data via Livestatus"), _("Cannot create graph"))

    except Exception as e:
        output += render_graph_error_html(e, _("Cannot create graph"))
    return output
示例#2
0
def render_graph_content_html(graph_recipe, graph_data_range,
                              graph_render_options) -> HTML:
    output = HTML()
    try:
        graph_artwork = artwork.compute_graph_artwork(graph_recipe,
                                                      graph_data_range,
                                                      graph_render_options)
        main_graph_html = render_graph_or_error_html(graph_artwork,
                                                     graph_data_range,
                                                     graph_render_options)

        previews = graph_render_options["show_time_range_previews"]
        if graph_recipe["specification"][0] == "forecast":
            previews = False

        if previews:
            output += html.render_div(
                main_graph_html + render_time_range_selection(
                    graph_recipe, graph_render_options),
                class_="graph_with_timeranges",
            )
        else:
            output += main_graph_html

    except livestatus.MKLivestatusNotFoundError:
        output += render_graph_error_html(
            _("Cannot fetch data via Livestatus"), _("Cannot create graph"))

    except Exception as e:
        output += render_graph_error_html(e, _("Cannot create graph"))
    return output
示例#3
0
def render_time_range_selection(graph_recipe, graph_render_options):
    now = int(time.time())
    output: RenderOutput = "<table class=timeranges>"
    graph_render_options = copy.deepcopy(graph_render_options)
    for timerange_attrs in config.graph_timeranges:
        duration = timerange_attrs["duration"]
        assert isinstance(duration, int)
        graph_render_options.update({
            "size": (20, 4),
            "font_size": 6.0,  # pt
            "onclick": "cmk.graphs.change_graph_timerange(graph, %d)" % duration,
            "fixed_timerange": True,  # Do not follow timerange changes of other graphs
            "title": timerange_attrs["title"],
            "show_legend": False,
            "show_controls": False,
            "preview": True,
            "resizable": False,
            "interaction": False,
        })

        timerange = now - duration, now
        graph_data_range = {
            "time_range": timerange,
            "step": 2 * estimate_graph_step_for_html(timerange, graph_render_options),
        }

        output += "<td title=\"%s\">\n" % (_("Change graph timerange to: %s") %
                                           timerange_attrs["title"])
        graph_artwork = artwork.compute_graph_artwork(graph_recipe, graph_data_range,
                                                      graph_render_options)
        output += render_graph_html(graph_artwork, graph_data_range, graph_render_options)
        output += "\n</td>"
        output += "</tr><tr>"
    output += "</table>"
    return output
示例#4
0
def _answer_graph_image_request() -> None:
    try:
        host_name = request.var("host")
        if not host_name:
            raise MKGeneralException(_("Missing mandatory \"host\" parameter"))

        service_description = request.var("service", "_HOST_")

        site = request.var("site")
        # FIXME: We should really enforce site here. But it seems that the notification context
        # has no idea about the site of the host. This could be optimized later.
        #if not site:
        #    raise MKGeneralException("Missing mandatory \"site\" parameter")
        try:
            row = get_graph_data_from_livestatus(site, host_name, service_description)
        except livestatus.MKLivestatusNotFoundError:
            if config.debug:
                raise
            raise Exception(
                _("Cannot render graph: host %s, service %s not found.") %
                (host_name, service_description))

        site = row["site"]

        # Always use 25h graph in notifications
        end_time = time.time()
        start_time = end_time - (25 * 3600)

        graph_render_options = graph_image_render_options()

        graph_identification = (
            "template",
            {
                "site": site,
                "host_name": host_name,
                "service_description": service_description,
                "graph_index": None,  # all graphs
            })

        graph_data_range = graph_image_data_range(graph_render_options, start_time, end_time)
        graph_recipes = graph_identification_types.create_graph_recipes(
            graph_identification, destination=html_render.GraphDestinations.notification)
        num_graphs = request.get_integer_input("num_graphs") or len(graph_recipes)

        graphs = []
        for graph_recipe in graph_recipes[:num_graphs]:
            graph_artwork = artwork.compute_graph_artwork(graph_recipe, graph_data_range,
                                                          graph_render_options)
            graph_png = render_graph_image(graph_artwork, graph_data_range, graph_render_options)

            graphs.append(base64.b64encode(graph_png).decode("ascii"))

        response.set_data(json.dumps(graphs))

    except Exception as e:
        logger.error("Call to ajax_graph_images.py failed: %s\n%s", e, traceback.format_exc())
        if config.debug:
            raise
示例#5
0
def render_time_range_selection(graph_recipe, graph_render_options) -> HTML:
    now = int(time.time())
    graph_render_options = copy.deepcopy(graph_render_options)
    rows = []
    for timerange_attrs in config.graph_timeranges:
        duration = timerange_attrs["duration"]
        assert isinstance(duration, int)
        graph_render_options.update({
            "size": (20, 4),
            "font_size":
            6.0,  # pt
            "onclick":
            "cmk.graphs.change_graph_timerange(graph, %d)" % duration,
            "fixed_timerange":
            True,  # Do not follow timerange changes of other graphs
            "title":
            timerange_attrs["title"],
            "show_legend":
            False,
            "show_controls":
            False,
            "preview":
            True,
            "resizable":
            False,
            "interaction":
            False,
        })

        timerange = now - duration, now
        graph_data_range = {
            "time_range":
            timerange,
            "step":
            2 * estimate_graph_step_for_html(timerange, graph_render_options),
        }

        graph_artwork = artwork.compute_graph_artwork(graph_recipe,
                                                      graph_data_range,
                                                      graph_render_options)
        rows.append(
            html.render_td(
                render_graph_html(graph_artwork, graph_data_range,
                                  graph_render_options),
                title=_("Change graph timerange to: %s") %
                timerange_attrs["title"],
            ))
    return html.render_table(HTML().join(
        html.render_tr(content) for content in rows),
                             class_="timeranges")
示例#6
0
def host_service_graph_dashlet_cmk(graph_identification,
                                   custom_graph_render_options):
    graph_render_options = default_dashlet_graph_render_options.copy()
    graph_render_options = artwork.add_default_render_options(
        graph_render_options)
    graph_render_options.update(custom_graph_render_options)

    width_var = html.request.get_float_input_mandatory("width", 0.0)
    width = int((width_var / html_size_per_ex))

    height_var = html.request.get_float_input_mandatory("height", 0.0)
    height = int((height_var / html_size_per_ex))

    bounds = _graph_margin_ex(graph_render_options)
    height -= _graph_title_height_ex(graph_render_options)
    height -= bounds.top + bounds.bottom
    width -= bounds.left + bounds.right

    graph_render_options["size"] = (width, height)

    # The timerange is specified in PNP like manner.
    range_secs = {
        "0": 4 * 3600,
        "1": 25 * 3600,
        "2": 7 * 86400,
        "3": 31 * 86400,
        "4": 366 * 86400,
    }

    secs_var = html.request.var("timerange")
    if secs_var not in range_secs:
        secs = 4 * 3600
    else:
        secs = range_secs[secs_var]
    end_time = time.time()
    start_time = end_time - secs
    graph_data_range = {
        "time_range": (start_time, end_time),
    }

    graph_data_range["step"] = estimate_graph_step_for_html(
        graph_data_range["time_range"], graph_render_options)

    try:
        graph_recipes = graph_identification_types.create_graph_recipes(
            graph_identification, destination=GraphDestinations.dashlet)
        if graph_recipes:
            graph_recipe = graph_recipes[0]
        else:
            raise MKGeneralException(_("Failed to calculate a graph recipe."))
    except livestatus.MKLivestatusNotFoundError:
        html.div(_("Cannot render graphs: cannot fetch data via Livestatus"),
                 class_="error")
        return

    # When the legend is enabled, we need to reduce the height by the height of the legend to
    # make the graph fit into the dashlet area.
    if graph_render_options["show_legend"]:
        # TODO FIXME: This graph artwork is calulated twice. Once here and once in render_graphs_from_specification_html()
        graph_artwork = artwork.compute_graph_artwork(graph_recipe,
                                                      graph_data_range,
                                                      graph_render_options)
        if graph_artwork["curves"]:
            legend_height = graph_legend_height_ex(graph_render_options,
                                                   graph_artwork)
            graph_render_options["size"] = (width, height - legend_height)

    html_code = render_graphs_from_definitions([graph_recipe],
                                               graph_data_range,
                                               graph_render_options,
                                               render_async=False)
    html.write(html_code)
示例#7
0
def render_ajax_graph(context):
    graph_data_range = context["data_range"]
    graph_render_options = context["render_options"]
    graph_recipe = context["definition"]

    start_time_var = html.request.var("start_time")
    end_time_var = html.request.var("end_time")
    step_var = html.request.var("step")
    if start_time_var is not None and end_time_var is not None and step_var is not None:
        start_time = float(start_time_var)
        end_time = float(end_time_var)
        step = float(step_var)
    else:
        start_time, end_time = graph_data_range["time_range"]
        step = graph_data_range["step"]

    size = graph_render_options["size"]

    resize_x_var = html.request.var("resize_x")
    resize_y_var = html.request.var("resize_y")

    if resize_x_var is not None and resize_y_var is not None:
        render_opt_x, render_opt_y = context["render_options"]["size"]
        size_x = max(min_resize_width,
                     float(resize_x_var) / html_size_per_ex + render_opt_x)
        size_y = max(min_resize_height,
                     float(resize_y_var) / html_size_per_ex + render_opt_y)
        config.user.save_file("graph_size", (size_x, size_y))
        size = (size_x, size_y)

    range_from_var = html.request.var("range_from")
    range_to_var = html.request.var("range_to")
    if range_from_var is not None and range_to_var is not None:
        vertical_range: Optional[Tuple[float, float]] = (float(range_from_var),
                                                         float(range_to_var))
    else:
        vertical_range = None

    if html.request.has_var("pin"):
        artwork.save_graph_pin()

    if html.request.has_var("consolidation_function"):
        graph_recipe["consolidation_function"] = html.request.var(
            "consolidation_function")

    graph_render_options["size"] = size
    graph_data_range["time_range"] = (start_time, end_time)
    graph_data_range["vertical_range"] = vertical_range
    graph_data_range["step"] = step

    # Persist the current data range for the graph editor
    if graph_render_options["editing"]:
        save_user_graph_data_range(graph_data_range)

    graph_artwork = artwork.compute_graph_artwork(graph_recipe,
                                                  graph_data_range,
                                                  graph_render_options)
    html_code = render_graph_html_content(graph_artwork, graph_data_range,
                                          graph_render_options)

    return {
        "html": html_code,
        "graph": graph_artwork,
        "context": {
            "graph_id": context["graph_id"],
            "definition": graph_recipe,
            "data_range": graph_data_range,
            "render_options": graph_render_options,
        }
    }
示例#8
0
def host_service_graph_dashlet_cmk(
    graph_identification: GraphIdentifier,
    custom_graph_render_options,
):
    graph_render_options = {**default_dashlet_graph_render_options}
    graph_render_options = artwork.add_default_render_options(
        graph_render_options)
    graph_render_options.update(custom_graph_render_options)

    width_var = request.get_float_input_mandatory("width", 0.0)
    width = int((width_var / html_size_per_ex))

    height_var = request.get_float_input_mandatory("height", 0.0)
    height = int((height_var / html_size_per_ex))

    bounds = _graph_margin_ex(graph_render_options)
    height -= _graph_title_height_ex(graph_render_options)
    height -= bounds.top + bounds.bottom
    width -= bounds.left + bounds.right

    graph_render_options["size"] = (width, height)

    timerange = json.loads(request.get_str_input_mandatory("timerange"))

    if isinstance(timerange, list):
        end_time = timerange[1]
        start_time = timerange[0]
    else:
        end_time = time.time()
        start_time = end_time - float(timerange)

    graph_data_range = {
        "time_range": (start_time, end_time),
    }

    graph_data_range["step"] = estimate_graph_step_for_html(
        graph_data_range["time_range"], graph_render_options)

    graph_recipes = resolve_graph_recipe_with_error_handling(
        graph_identification,
        destination=GraphDestinations.dashlet,
    )
    if not isinstance(graph_recipes, list):
        return graph_recipes  # This is to html.write the exception
    if graph_recipes:
        graph_recipe = graph_recipes[0]
    else:
        raise MKGeneralException(_("Failed to calculate a graph recipe."))

    # When the legend is enabled, we need to reduce the height by the height of the legend to
    # make the graph fit into the dashlet area.
    if graph_render_options["show_legend"]:
        # TODO FIXME: This graph artwork is calulated twice. Once here and once in render_graphs_from_specification_html()
        graph_artwork = artwork.compute_graph_artwork(graph_recipe,
                                                      graph_data_range,
                                                      graph_render_options)
        if graph_artwork["curves"]:
            legend_height = graph_legend_height_ex(graph_render_options,
                                                   graph_artwork)
            graph_render_options["size"] = (width, height - legend_height)

    html_code = render_graphs_from_definitions([graph_recipe],
                                               graph_data_range,
                                               graph_render_options,
                                               render_async=False)
    html.write_html(html_code)
示例#9
0
def render_ajax_graph(context):
    graph_data_range = context["data_range"]
    graph_render_options = context["render_options"]
    graph_recipe = context["definition"]

    if html.request.has_var("start_time"):
        start_time = float(html.request.var("start_time"))
        end_time = float(html.request.var("end_time"))
        step = float(html.request.var("step"))
    else:
        start_time, end_time = graph_data_range["time_range"]
        step = graph_data_range["step"]

    if html.request.has_var("resize_x"):  # then has always also resize_y
        size_x = max(
            min_resize_width,
            float(html.request.var("resize_x")) / html_size_per_ex +
            context["render_options"]["size"][0])
        size_y = max(
            min_resize_height,
            float(html.request.var("resize_y")) / html_size_per_ex +
            context["render_options"]["size"][1])
        size = size_x, size_y
        config.user.save_file("graph_size", size)
    else:
        size = context["render_options"]["size"]

    if html.request.has_var("range_from"):
        range_from = float(html.request.var("range_from"))
        range_to = float(html.request.var("range_to"))
        vertical_range = (range_from, range_to)
    else:
        vertical_range = None

    if html.request.has_var("pin"):
        artwork.save_graph_pin()

    if html.request.has_var("consolidation_function"):
        graph_recipe["consolidation_function"] = html.request.var(
            "consolidation_function")

    graph_render_options["size"] = size
    graph_data_range["time_range"] = (start_time, end_time)
    graph_data_range["vertical_range"] = vertical_range
    graph_data_range["step"] = step

    # Persist the current data range for the graph editor
    if graph_render_options["editing"]:
        save_user_graph_data_range(graph_data_range)

    graph_artwork = artwork.compute_graph_artwork(graph_recipe,
                                                  graph_data_range,
                                                  graph_render_options)
    html_code = render_graph_html_content(graph_artwork, graph_data_range,
                                          graph_render_options)

    return {
        "html": html_code,
        "graph": graph_artwork,
        "context": {
            "graph_id": context["graph_id"],
            "definition": graph_recipe,
            "data_range": graph_data_range,
            "render_options": graph_render_options,
        }
    }