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)
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
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
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()
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))))
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
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))))
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)
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)