示例#1
0
def estimate_graph_step_for_html(time_range, graph_render_options):
    graph_render_options = artwork.add_default_render_options(
        graph_render_options)
    width_in_ex = graph_render_options["size"][1]
    steps_per_ex = html_size_per_ex * 4
    number_of_steps = width_in_ex * steps_per_ex
    return int((time_range[1] - time_range[0]) / number_of_steps)
示例#2
0
def graph_image_render_options(api_request: Optional[dict[str, Any]] = None) -> GraphRenderOptions:
    # Set image rendering defaults
    graph_render_options = {
        "font_size": 8.0,  # pt
        "resizable": False,
        "show_controls": False,
        "title_format": ("add_title_infos", ["add_service_description"]),
        "interaction": False,
        "size": (80, 30),  # ex
        # Specific for PDF rendering.
        "color_gradient": 20.0,
        "show_title": True,
        "border_width": 0.05,
    }

    # Populate missing keys
    graph_render_options = artwork.add_default_render_options(
        graph_render_options, render_unthemed=True
    )

    # Enforce settings optionally setable via request
    if api_request and api_request.get("render_options"):
        graph_render_options.update(api_request["render_options"])

    return graph_render_options
示例#3
0
def render_graph_container_html(graph_recipe, graph_data_range,
                                graph_render_options):
    graph_render_options = artwork.add_default_render_options(
        graph_render_options)

    # Estimate size of graph. This will not be the exact size of the graph, because
    # this does calculate the size of the canvas area and does not take e.g. the legend
    # into account. We would need the graph_artwork to calculate that, but this is something
    # we don't have in this early stage.
    size = graph_render_options["size"]
    graph_width = size[0] * html_size_per_ex
    graph_height = size[1] * html_size_per_ex

    content = html.render_div("", class_="title") \
            + html.render_div("",
                class_="content",
                style="width:%dpx;height:%dpx" % (graph_width, graph_height))

    output = html.render_div(html.render_div(content, class_=["graph", "loading_graph"]),
                             class_="graph_load_container") \

    output += html.render_javascript(
        "cmk.graphs.load_graph_content(%s, %s, %s)" % (
            json.dumps(graph_recipe),
            json.dumps(graph_data_range),
            json.dumps(graph_render_options),
        ))

    if "cmk.graphs.register_delayed_graph_listener" not in html.final_javascript_code:
        html.final_javascript("cmk.graphs.register_delayed_graph_listener()")

    return output
示例#4
0
def _show_graph_html_content(graph_artwork, graph_data_range,
                             graph_render_options) -> None:
    """Render the HTML code of a graph without its container

    That is a canvas object for drawing the actual graph and also legend, buttons, resize handle,
    etc.
    """
    graph_render_options = artwork.add_default_render_options(
        graph_render_options)

    html.open_div(
        class_=[
            "graph", "preview" if graph_render_options["preview"] else None
        ],
        style="font-size: %.1fpt;%s" %
        (graph_render_options["font_size"],
         _graph_padding_styles(graph_render_options)),
    )

    if graph_render_options["show_controls"]:
        _show_graph_add_to_icon_for_popup(graph_artwork, graph_data_range,
                                          graph_render_options)

    v_axis_label = graph_artwork["vertical_axis"]["axis_label"]
    if v_axis_label:
        html.div(v_axis_label, class_="v_axis_label")

    # Add the floating elements
    if graph_render_options[
            "show_graph_time"] and not graph_render_options["preview"]:
        html.div(
            graph_artwork["time_axis"]["title"] or "",
            css=[
                "time", "inline"
                if graph_render_options["show_title"] == "inline" else None
            ],
        )

    if graph_render_options["show_controls"] and graph_render_options[
            "resizable"]:
        html.img(src=theme.url("images/resize_graph.png"), class_="resize")

    _show_html_graph_title(graph_artwork, graph_render_options)
    _show_graph_canvas(graph_render_options)

    # Note: due to "omit_zero_metrics" the graph might not have any curves
    if _graph_legend_enabled(graph_render_options, graph_artwork):
        _show_graph_legend(graph_artwork, graph_render_options)

    model_params_repr = graph_artwork["definition"].get("model_params_repr")
    model_params_display = (graph_artwork["definition"].get(
        "model_params", {}).get("display_model_parametrization"))
    if model_params_repr and model_params_display:
        html.open_div(align="center")
        html.h2(_("Forecast Parametrization"))
        html.write_html(model_params_repr)
        html.close_div()

    html.close_div()
示例#5
0
def render_graph_html(graph_artwork, graph_data_range, graph_render_options):
    graph_render_options = artwork.add_default_render_options(graph_render_options)

    html_code = render_graph_html_content(graph_artwork, graph_data_range, graph_render_options)

    return html.render_javascript(
        'cmk.graphs.create_graph(%s, %s, %s, %s);' %
        (json.dumps("%s" % html_code), json.dumps(graph_artwork), json.dumps(graph_render_options),
         json.dumps(graph_ajax_context(graph_artwork, graph_data_range, graph_render_options))))
示例#6
0
def render_graph_html_content(graph_artwork, graph_data_range,
                              graph_render_options):
    graph_render_options = artwork.add_default_render_options(
        graph_render_options)

    css = " preview" if graph_render_options["preview"] else ""
    output: RenderOutput = '<div class="graph%s" style="font-size: %.1fpt;%s">' % (
        css, graph_render_options["font_size"],
        _graph_padding_styles(graph_render_options))

    if graph_render_options["show_controls"]:
        output += render_graph_add_to_icon_for_popup(graph_artwork,
                                                     graph_data_range,
                                                     graph_render_options)

    v_axis_label = graph_artwork["vertical_axis"]["axis_label"]
    if v_axis_label:
        output += '<div class=v_axis_label>%s</div>' % v_axis_label

    # Add the floating elements
    if graph_render_options[
            "show_graph_time"] and not graph_render_options["preview"]:
        output += html.render_div(
            graph_artwork["time_axis"]["title"] or "",
            css=[
                "time", "inline"
                if graph_render_options["show_title"] == "inline" else None
            ])

    if graph_render_options["show_controls"] and graph_render_options[
            "resizable"]:
        output += '<img class=resize src="%s">' % html.theme_url(
            "images/resize_graph.png")

    output += render_html_graph_title(graph_artwork, graph_render_options)
    output += render_graph_canvas(graph_render_options)

    # Note: due to "omit_zero_metrics" the graph might not have any curves
    if show_graph_legend(graph_render_options, graph_artwork):
        output += render_graph_legend(graph_artwork, graph_render_options)

    model_params_repr = graph_artwork["definition"].get("model_params_repr")
    model_params_display = graph_artwork["definition"].get(
        'model_params', {}).get("display_model_parametrization")
    if model_params_repr and model_params_display:
        output += "<div align='center'><h2>Forecast Parametrization</h2>%s</div>" % model_params_repr

    output += '</div>'
    return output
示例#7
0
def render_graph_html(graph_artwork, graph_data_range,
                      graph_render_options) -> HTML:
    graph_render_options = artwork.add_default_render_options(
        graph_render_options)

    with output_funnel.plugged():
        _show_graph_html_content(graph_artwork, graph_data_range,
                                 graph_render_options)
        html_code = HTML(output_funnel.drain())

    return html.render_javascript(
        'cmk.graphs.create_graph(%s, %s, %s, %s);' %
        (json.dumps(html_code), json.dumps(graph_artwork),
         json.dumps(graph_render_options),
         json.dumps(
             graph_ajax_context(graph_artwork, graph_data_range,
                                graph_render_options))))
示例#8
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)
示例#9
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)