Render
render
Specifies a visualization type for the query results. When present, the frontend renders the results using the specified chart type instead of the default table grid.
Spec
... | render <chart_type> [with (<property> = <value> [, ...])]Parameters
chart_type - The visualization type (see Chart Types below).
property - Optional rendering properties.Return Value
The same data as the input, annotated with visualization metadata.Chart Settings
Use Chart settings in the query page's visualization tab or the dashboard chart editor to choose a chart type, axes, units, line styles, palette, and named series colors. Controls update the render clause; query edits update the controls. Reset removes an explicit setting so the default applies. Unknown or inapplicable saved properties are preserved until explicitly removed.
The chart settings reference lists every supported property, its type, default, allowed values, and applicable chart types. It is generated from the same catalog used by the editor and query completion. In the query editor, completion after render, with (, and property assignment offers chart types, settings, and values. Invalid known settings produce warnings without rejecting otherwise valid queries.
Logarithmic axes
Set yScale = "log" on line, time, or vertical bar charts. A numeric x axis supports xScale = "log" on line charts and horizontal bars. Category axes and a timechart's datetime x axis cannot use a logarithmic scale. The existing "logarithmic" spelling remains supported.
minX, maxX, minY, maxY, xUnit, and yUnit follow visual axes. Logarithmic bounds must be positive; a minimum must be less than its maximum. Invalid bounds are ignored with a warning. Nonpositive or nonfinite points are omitted from logarithmic plotting, with an omitted-point count; lines leave gaps. Original result rows and exports retain their values.
range x from 1 to 10 step 1
| extend value = pow(10.0, x)
| project value, x
| render barchart with (yScale = "log", minY = 1)Colors
palette is an ordered, repeating array of hex colors. seriesColors maps exact legend labels to hex colors and takes precedence over the palette. For pie charts, keys match category labels. Colors accept #RGB and #RRGGBB. Omitted settings retain the existing automatic palette. Saved overrides remain available when a series temporarily disappears.
Arrays and objects use dynamic(...) containing literal JSON; expressions are not evaluated inside it. Duplicate object keys are rejected. Use a quoted string for text, a boolean for switches, and a number for numeric settings.
range x from 1 to 10 step 1
| extend value = x * 100
| render linechart with (
yScale = "log",
fill = false,
tension = 0.25,
palette = dynamic(["#1565c0", "#ef6c00"]),
seriesColors = dynamic({"value": "#ef6c00"})
)Grouped line and bar series use labels such as (host: api), with multiple dimensions joined as (host: api), (region: us-east). The editor lists labels from preview results and permits entering labels for currently absent series.
Thresholds and conditional colors
Use Chart settings → Thresholds → Add threshold on time, line, bar, and stat charts. Choose Above or Below, a numeric value, and a color. Leave Series empty to apply a rule to all series, or enter an exact legend label (a column name for stat cards). For an acceptable range, add a below rule for the lower limit and an above rule for the upper limit. Later matching rules take priority; the arrow buttons change their order. Values equal to the threshold retain their normal color unless another rule matches.
range x from 0 to 100 step 1
| extend value = x
| render linechart with (
thresholds = dynamic([
{"value": 60, "direction": "above", "color": "#ed6c02"},
{"value": 80, "direction": "above", "color": "#d32f2f"},
{"value": 20, "direction": "below", "color": "#d32f2f"}
]),
showThresholds = true
)Time and line strokes and markers change color at the numeric axis threshold, including crossings between samples. Area fills retain the series color. On stacked lines, thresholds follow the plotted cumulative height. Bars and stat values are colored using their individual numeric values. Missing and nonfinite values never match. Thresholds use the original data units, before display formatting; timespan axes use milliseconds and percentunit values use fractions (for example, 0.8 for 80%).
Dashed guides show thresholds inside the visible numeric axis range and follow horizontal bar orientation. Set showThresholds = false to hide guides while retaining colors. Rules for absent or hidden series do not draw guides. Thresholds do not expand the axis range. Sampling is disabled for charts with thresholds so brief excursions are preserved. Rules save with the existing chart settings and take precedence over palette and series color overrides where they match.
Preview and persistence
Chart controls immediately redraw existing results when the data query, account, and variable bindings are unchanged. Compatible visualization changes resolve axes from the local output schema. Controls update the render query as you edit, while query validation continues in the background. Opening a dashboard editor and saving presentation changes also reuse the loaded rows. Dashboard previews execute changed data queries; the query page asks you to execute when its displayed results no longer match.
Kusto tiles save settings in their query. Simple tiles expose the same applicable controls for their existing chart choices, persist an optional renderOptions object, and display a copyable equivalent render clause. The Simple tile title stays authoritative. Existing tiles without settings retain their previous behavior.
Units
| Unit ID | Category | Formatting |
|---|---|---|
"bytes" | Data size | Binary auto-scale: B, KB, MB, GB, TB (÷1024) |
"decbytes" | Data size | Decimal auto-scale: B, KB, MB, GB, TB (÷1000) |
"bytesps" | Data rate | Binary auto-scale + /s suffix |
"bits" | Bits | Decimal auto-scale: b, Kb, Mb, Gb |
"celsius" | Temperature | Append °C |
"fahrenheit" | Temperature | Append °F |
"kelvin" | Temperature | Append K |
"seconds" | Duration | Auto-scale to human-readable duration |
"milliseconds" | Duration | Auto-scale to human-readable duration |
"microseconds" | Duration | Auto-scale to human-readable duration |
"percent" | Percent | Values 0–100 shown with % |
"percentunit" | Percent | Values 0–1 multiplied by 100, shown with % |
"none" | Number | SI suffixes for large numbers (K, M, G, T) |
When a column has a timespan type, numeric ticks are formatted as durations unless an explicit unit overrides the format. A timechart's datetime x-axis labels adapt to the visible range.
Chart Types
timechart
Time series visualization. The x-axis is the first datetime column. Each numeric column draws a separate line at each timestamp; if there are no numeric columns, each timespan column becomes a value series instead. Remaining columns become grouping keys. A single value column grouped by host keeps labels such as (host: api); multiple value columns use labels such as p50 (host: api) and p90 (host: api). These labels also identify series in color overrides and threshold rules.
Project the value columns you want to plot. Convert a numeric grouping key with tostring() when it should identify a group rather than a value series.
datatable(timestamp:datetime, host:string, cpu:float64, cpu_fraction:float64, temp:float64, location:string, bytes:int64, service:string, cpu_percent:float64, memory:float64)[now(), "host-a", 0.42, 0.42, 21.5, "lab", 1024, "api", 42.0, 0.68]
| where timestamp > ago(1h)
| summarize avg(cpu) by bin(timestamp, 1m)
| render timechartPlot multiple percentile values for every time bucket:
datatable(timestamp:datetime, duration:real)[
datetime(2026-01-01T00:00:00Z), 10.0,
datetime(2026-01-01T00:00:10Z), 20.0,
datetime(2026-01-01T00:01:00Z), 30.0,
datetime(2026-01-01T00:01:10Z), 50.0
]
| summarize (p50, p90) = percentiles(duration, 50, 90) by timestamp = bin(timestamp, 1m)
| order by timestamp asc
| render timechart with (fill = false)linechart
Line chart. The x-axis is the first numeric (or timespan) column and the y-axis is the next numeric column; every other column becomes a series key.
range x from 0 to 100 step 1
| extend y = sin(x * pi() / 50)
| render linechartbarchart
Bar chart for comparing values across categories. The value is the first numeric (int, uint, or float) column and the category label is the first non-numeric column, in any order; when every column is numeric the first two are used positionally.
datatable(timestamp:datetime, statusCode:int64, method:string)[now(), 200, "GET"]
| where timestamp > ago(1d)
| summarize count() by statusCode
| render barchartpiechart
Pie chart showing proportional distribution. The value is the first numeric (int, uint, or float) column and the slice label is the first non-numeric column, in any order.
datatable(timestamp:datetime, statusCode:int64, method:string)[now(), 200, "GET"]
| where timestamp > ago(1h)
| summarize count() by method
| render piechartmap2d
2D geographic map visualization. Requires latitude and longitude columns of type float64. See Map Chart Options for optional columns.
datatable(latitude:float64, longitude:float64, name:string)[40.7, -74.0, "New York"]
| project latitude, longitude, label = name
| render map2dUse Chart settings → Labels to adjust label size, colors, outline width, and offset above individual markers. Cluster counts stay centered. Label settings apply to cluster mode, not heatmaps.
Heatmaps use geographic density by default. HeatmapRadiusMeters sets the smoothing radius on the ground (default 1000 m), with a smooth kernel that reaches zero at that distance. Maximum weight (HeatmapMaxWeight) accepts "auto" (default) or a positive number. Auto uses the largest valid input weight from the full query result, before combining points. A fixed value lets multiple queries or dashboards share a scale. The radius and scale remain fixed when panning, zooming, or resizing; the legend shows the resolved maximum and radius.
The numeric weight column accepts any finite positive value (default 1); geographic mode preserves values above 1. Zero and negative weights do not contribute. Missing or nonfinite coordinates, coordinates outside Web Mercator's latitude range (approximately ±85.0511°), and nonfinite weights are skipped. Longitudes wrap across the date line. An isolated point reaches the top of the scale at the maximum weight. Overlapping points add density and may saturate even when their individual weights are below the maximum. Each point contributes its weight over its geographic kernel; latitude does not change its total mass. Small hotspots naturally become less visible when their area is smaller than a screen pixel: coarse pixels average density over ground area, rather than summing counts into hotter colors.
For an absolute physical density scale, Advanced → Density override (HeatmapMaxDensity) accepts a positive maximum in weighted events/km². It overrides the maximum weight setting; leave it unset for Auto or Fixed maximum weight.
Return a color column containing #RGB or #RRGGBB to give each category its own hue. Density controls opacity; overlapping category colors mix in proportion to their density, independently of row order. Missing or invalid colors use the default density gradient. Geographic heatmaps share one layer across all categories and generate tiles in a background worker. For dense inputs, points of the same color are combined into weighted spherical centroids in fixed geographic bins measuring 1/32 of the smoothing radius. This preserves total weight and introduces a small spatial approximation that is independent of zoom.
datatable(latitude:float64, longitude:float64, weight:float64, color:string)[
35.110, -80.789, 800, '#2563eb',
35.112, -80.790, 600, '#dc2626'
]
| render map2d with (MapType = 'heatmap', HeatmapRadiusMeters = 500, HeatmapMaxWeight = 'auto')Saved queries with explicit Radius or BlurRadius settings retain the legacy pixel heatmap, including its original 0–1 weight clamp. Set HeatmapMode = 'geographic' to migrate those queries; their pixel controls are ignored in geographic mode. HeatmapMode = 'pixels' explicitly selects the legacy renderer. Use Chart settings → Appearance to edit these settings in queries and dashboards. For a shared fixed scale, use HeatmapMaxWeight = 1000 instead of 'auto'.
Cama
| project latitude = todouble(xcoord), longitude = todouble(ycoord), label = address
| render map2d with (LabelFontSize = 18, LabelColor = "#202020", LabelOutlineColor = "#ffffff", LabelOutlineWidth = 3, LabelOffset = 20)gantt
Gantt chart for scheduling and timeline visualization. Requires name, start, and end columns. Optionally supports color and group columns.
datatable(name:string, start:datetime, end:datetime, group:string)["Deploy", now(), now() + 1d, "Release"]
| project name, start, end, group
| render gantttrace
Distributed trace visualization for viewing spans in a trace tree. Requires timestamp (datetime), traceid, parentid, and spanid (string) columns, plus an end or duration column. See Trace Chart Options for column detection.
datatable(timestamp:datetime, traceid:string, parentid:string, spanid:string, operationName:string, duration_ms:int64)[now(), "abc123", "", "span-1", "GET /", 3]
| where traceid == "abc123"
| project timestamp, traceid, parentid, spanid, operationName, duration
| render tracestat
Statistical card display showing key metrics. Shows one card per column of the first row. Requires at least one column.
datatable(timestamp:datetime, host:string, cpu:float64, memory:float64)[now(), "host-a", 0.42, 0.68]
| where timestamp > ago(5m)
| summarize avg(cpu), avg(memory), count()
| render stattable
Default table grid display. This is the default when no render operator is specified.
datatable(message:string)["example log"]
| take 100
| render table