1.1 The chart Command & Multi-Dimensional Aggregations

Key Takeaways

  • The chart command is a transforming command that produces a two-dimensional statistical matrix (cross-tabulation pivot table) designed specifically for chart visualizations.
  • Syntax allows either `chart <eval-function> over <row-field> by <column-field>` or `chart <eval-function> by <row-field>, <column-field>`, where the first field forms rows (X-axis) and the second forms column series (legend).
  • The chart command is strictly constrained to a maximum of two split-by dimensions, unlike stats which accepts an unlimited number of by-clause fields.
  • All standard statistical aggregation functions (such as count, dc, sum, avg, min, max, perc<X>, stdev) and inline eval expressions are supported within chart.
  • Transforming commands discard raw event data (`_raw`) and shift the Splunk Web search results view from the Events tab to the Statistics and Visualizations tabs.
Last updated: August 2026

1.1 The chart Command & Multi-Dimensional Aggregations

In Splunk Search Processing Language (SPL), transforming commands are the foundation of all reporting, metric summaries, and dashboard visualizations. Among these, the chart command is specifically engineered to convert raw event streams into two-dimensional cross-tabulation tables (matrix pivot tables). For the Splunk Core Certified Power User exam, you must master the mechanics of the chart command, its exact syntax variants, how it aggregates multi-dimensional datasets, how it compares to stats, and how its output data structures map directly into graphical visualizations.


1. Architectural Foundations of Transforming Commands

To understand chart, you must first understand what makes a command "transforming" in the Splunk pipeline architecture.

Splunk documents six command types — distributable streaming, centralized streaming, transforming, generating, orchestrating, and dataset processing. Three of them matter most here:

  1. Streaming Commands: Operate on each event as it is returned by the search (e.g., eval, where, rex). They do not change the underlying tabular structure of the event stream. Distributable streaming commands can run on the indexers; centralized streaming commands run only on the search head.
  2. Generating Commands: Return or generate results without an input pipe (e.g., search as the first command, tstats, inputlookup).
  3. Transforming Commands: Order the results into a data table, converting event streams into statistical output (e.g., chart, timechart, stats, top, rare, contingency).
+-------------------------------------------------------------------------------------+
|                        The Transforming Pipeline Barrier                            |
+-------------------------------------------------------------------------------------+
| Raw Event Stream (Indexers)                                                         |
|  - Contains _raw, _time, host, source, sourcetype, indexed/extracted fields         |
|  - Displayed on the "Events" Tab in Splunk Web                                      |
+-------------------------------------------------------------------------------------+
                                           |
                                           v
                          [ | chart count over host by status ]
                                           |
                                           v
+-------------------------------------------------------------------------------------+
| Statistical Summary Table (Search Head)                                             |
|  - Raw events and non-aggregated fields are discarded                               |
|  - Output populates the "Statistics" Tab and unlocks the "Visualizations" Tab       |
|  - Creates a 2D matrix formatted for column, bar, line, area, and pie charts        |
+-------------------------------------------------------------------------------------+

Critical Behaviors of Transforming Commands:

  • Destruction of Raw Event State: Once a transforming command executes, individual event fields and the _raw text are no longer accessible to downstream SPL commands, unless explicitly preserved in the aggregation.
  • Search Head Reduction Barrier: In a distributed deployment, indexers perform local streaming pre-aggregations (the Map phase) and send intermediate accumulators over the network to the Search Head. The Search Head merges these accumulators into the final matrix (the Reduce phase).
  • UI View State Transition: Executing chart shifts the Splunk Search & Reporting interface from the Events tab to the Statistics tab and allows immediate rendering in the Visualizations tab.

2. The 2-Dimensional Data Structure: chart vs. stats

The fundamental conceptual difference between chart and stats lies in the shape of the output data table.

  • stats produces a "Tall" (Flat) Table: Every combination of by clause fields produces a new row. The stats command supports an arbitrary, unlimited number of by fields (by host, status, method, uri_path).
  • chart produces a "Wide" (2-Dimensional Matrix) Table: The first split-by field establishes the table rows (X-axis categories), while the second split-by field pivots horizontally to form individual column headers (data series/legend). The chart command supports a maximum of two split-by dimensions.

Visual Comparison: stats vs. chart Data Shapes

Consider web access logs containing servers (web01, web02) and HTTP status codes (200, 404, 500):

+-------------------------------------------------------------------------------------+
| `stats count by host, status`                | `chart count over host by status`    |
| (Flat / Tall Table - 1 row per unique tuple) | (2D Matrix Table - Row x Column Grid)|
+----------------------------------------------+--------------------------------------+
| host        status       count               | host        200        404       500 |
| web01       200          1500                | web01       1500       45        12  |
| web01       404          45                  | web02       1800       23        5   |
| web01       500          12                  +--------------------------------------+
| web02       200          1800                | Rows: host (X-axis categories)       |
| web02       404          23                  | Columns: status values (Data Series) |
| web02       500          5                   | Values: count metric                 |
+----------------------------------------------+--------------------------------------+

Why does this matter for visualizations? Charting engines (such as Highcharts in Splunk Classic XML and Apache ECharts in Splunk Dashboard Studio) expect distinct data series to exist as separate columns. A clustered column chart displaying HTTP status codes per host requires status 200, 404, and 500 as separate data series columns, which chart creates automatically.


3. Syntax Rules: over and by Clauses

The chart command supports two equivalent syntax conventions for two-dimensional aggregations, as well as a one-dimensional format.

Syntax Form 1: Explicit over and by

... | chart <statistical-function>(<field>) [as <alias>] over <row-field> by <column-field>
  • <row-field>: The field following over forms the rows (X-axis categories).
  • <column-field>: The field following by forms the column headers (data series/legend).
index=web sourcetype=access_combined
| chart count over host by status

Syntax Form 2: Comma-Separated by

... | chart <statistical-function>(<field>) [as <alias>] by <row-field>, <column-field>

When two fields are specified after by separated by a comma:

  • The first field is automatically treated as the row field (over).
  • The second field is automatically treated as the column series field (by).
index=web sourcetype=access_combined
| chart avg(response_time) as avg_latency by uri_path, method

In this example, uri_path defines the rows, and distinct method values (GET, POST, DELETE) become the column headers.

Syntax Form 3: 1-Dimensional Aggregation (Single Split-By Field)

When only a single split-by field is provided, chart creates a single-series table:

index=web sourcetype=access_combined
| chart sum(bytes) as total_bytes by host

Here, each row is a host, and a single metric column total_bytes is produced. This is ideal for simple single-series bar charts, column charts, or pie charts.

The Strict Two-Field Limit Rule

[!IMPORTANT] Crucial Exam Rule: The documented chart syntax offers exactly two shapes — BY <row-split> <column-split> or OVER <row-split> [BY <column-split>]. Either way you get at most two split dimensions, and once over is used the by clause accepts exactly one field. An expression such as chart count over host by status, method or chart count by host, status, method fails to parse. If your use case requires three or more grouping dimensions, you must use stats.

4. Statistical Aggregation Functions in chart

The chart command supports the complete suite of Splunk statistical functions. These functions operate on event fields to compute counts, averages, sums, variance, or percentiles.

Function CategoryFunction SyntaxDescriptionExample
CountingcountTotal number of events matching criteriachart count over host by status
count(<field>)Number of events where <field> is not nullchart count(clientip) by host
distinct_count(<field>) or dc(<field>)Count of unique values of <field>chart dc(clientip) as unique_users over host by status
Central Tendencyavg(<field>) or mean(<field>)Arithmetic mean of numeric fieldchart avg(bytes) as avg_bytes over host by method
median(<field>)50th percentile / middle valuechart median(response_time) by uri_path, host
mode(<field>)Most frequently occurring valuechart mode(status) by host
Extrema & Sumssum(<field>)Arithmetic sum of numeric valueschart sum(bytes) as total_volume by host, sourcetype
min(<field>), max(<field>)Minimum and maximum valueschart min(resp_time), max(resp_time) over host by method
range(<field>)Difference between max(<field>) and min(<field>)chart range(response_time) by host
Dispersionstdev(<field>), stdevp(<field>)Sample / population standard deviationchart stdev(duration) by app_tier, host
var(<field>), varp(<field>)Sample / population variancechart var(bytes) by host
Percentilesperc<X>(<field>)Approximate Xth percentile (e.g., perc95, perc99)chart perc95(response_time) as p95 over uri_path by host
exactperc<X>(<field>)Exact Xth percentile (more resource intensive)chart exactperc95(response_time) by host

Renaming Aggregations with the as Clause

Always assign clear, human-readable aliases to aggregation metrics using the as keyword. The alias must appear immediately after the aggregation function and before any over or by clauses:

`-- Correct syntax for field aliasing`
index=web
| chart avg(response_time) as avg_resp_ms, perc95(response_time) as p95_resp_ms over uri_path by status
`-- INCORRECT syntax (will generate a syntax error)`
index=web
| chart avg(response_time) over uri_path by status as avg_resp_ms   <-- SYNTAX ERROR!

5. Inline eval() Expressions Within chart

Power Users frequently need to perform conditional aggregation or arithmetic calculation inside transforming commands without creating intermediate fields with standalone eval stages. Splunk allows embedding eval() expressions directly inside chart aggregation functions.

1. Conditional Counting with count(eval(...))

Instead of filtering out non-matching events before the chart command, you can compute distinct counts based on arbitrary boolean conditions:

index=web
| chart count(eval(status>=200 AND status<300)) as success_count,
        count(eval(status>=400 AND status<500)) as client_err_count,
        count(eval(status>=500)) as server_err_count
        over host by method

2. Embedded Arithmetic Transformations with eval(...)

You can wrap an aggregation function in an eval() expression to transform units directly:

index=web
| chart eval(round(sum(bytes)/1024/1024, 2)) as total_mb,
        eval(round(avg(response_time_ms)/1000, 3)) as avg_resp_sec
        over host by status

6. Comprehensive Structural Comparison: chart vs. stats

Attributechart Commandstats Command
Output Structure2-Dimensional Matrix / Cross-Tabulation GridFlat / Tall Table (1 row per unique tuple)
Max Split-By FieldsExactly 2 (over f1 by f2 or by f1, f2)Unlimited (by f1, f2, f3, f4, ...)
Default Limit BehaviorEnforces limit=10 on column split field (groups rest to OTHER)No limits (returns 100% of distinct combinations)
Missing Value HandlingEnforces usenull=t (groups missing values into NULL column)Omits null rows unless explicitly grouped
Primary PurposeDirect input for charts (column, bar, area, pie, line)Data manipulation, subsearches, multi-field rollups
Search Head MemoryAllocates columns for distinct series valuesAllocates rows in standard streaming buffer
Dashboard UsageSingle-panel visual componentsDetailed data tables, event rollups, CSV exports

When to Use stats Instead of chart:

  1. When you need to aggregate across 3 or more categorical fields (e.g., stats sum(bytes) by datacenter, rack, host, process).
  2. When you are processing intermediate data in a complex pipeline that will be followed by eval, where, lookup, or join.
  3. When you need raw tabular exports where each row represents a complete, structured record.

When to Use chart Instead of stats:

  1. When you are feeding data directly into a multi-series chart visualization (e.g., a clustered column chart showing errors by server).
  2. When you want automatic top-N column limiting and grouping of lower-frequency categories into OTHER.
  3. When you want an intuitive matrix display on the Statistics tab without writing complex eval pivot queries.

7. Advanced Pattern: Dynamic Subsearch Filtering with chart

In enterprise environments, you often want to chart metrics for only the top N most active entities (such as top 5 talker IP addresses or top 5 failing endpoints) across all categories. By pairing a subsearch with chart, you can dynamically discover the top entities and filter the outer chart query.

Dynamic Top-5 Client Filtering Example

index=web status=*
  [ search index=web status=*
    | top limit=5 clientip
    | fields clientip ]
| chart count over uri_path by clientip limit=0
+-------------------------------------------------------------------------------------+
| Pipeline Step-by-Step Execution:                                                    |
|                                                                                     |
| 1. Subsearch Executes First:                                                        |
|    `search index=web status=* | top limit=5 clientip | fields clientip`             |
|    Finds the 5 highest-volume clientip values across the dataset.                   |
|    Outputs boolean search filter:                                                   |
|    ( ( clientip="10.0.1.25" ) OR ( clientip="192.168.4.12" ) OR ... )            |
|                                                                                     |
| 2. Outer Search Ingestion:                                                          |
|    Outer search applies the boolean filter to incoming events from disk.            |
|    Only events matching the top 5 IPs are passed down the pipeline.                 |
|                                                                                     |
| 3. Outer `chart` Execution:                                                         |
|    `chart count over uri_path by clientip limit=0`                                 |
|    Renders a pristine 2D grid where the 5 high-volume IPs form the exact 5 columns. |
|    `limit=0` ensures no spurious OTHER columns are generated.                       |
+-------------------------------------------------------------------------------------+

8. Common Exam Traps & Best Practices

  1. The 3-Field Trap:

    • Trap: The exam presents a query like index=firewall | chart sum(bytes) over src_ip by dest_ip, port and asks what the resulting chart looks like.
    • Fact: It will throw a syntax error. chart never accepts more than two split-by fields.
  2. Row vs. Column Inversion:

    • Trap: Confusing over with by. Remember: over <field> sets the rows (X-axis categories), and by <field> sets the columns (legend series). In chart count by host, status, host is the row and status is the column.
  3. Field Alias Positioning:

    • Trap: Placing the as alias at the end of the query (e.g., chart count over host by status as total).
    • Fact: The as keyword must immediately follow the aggregation function: chart count as total over host by status.
  4. Event Loss Misconception:

    • Trap: Expecting to run eval on a field like clientip after running chart count over host by status.
    • Fact: clientip is eliminated at the transforming stage because it was not included in the aggregation or split-by clauses.
Test Your Knowledge

A Splunk administrator executes the following search query: index=web status=* | chart avg(response_time) as avg_resp over host by status How does Splunk structure the resulting output table on the Statistics tab?

A
B
C
D
Test Your Knowledge

A security engineer needs to produce a report showing total data transfer (sum(bytes)) across three dimensions: src_zone, dest_zone, and app_protocol. Which SPL command must be used to generate this aggregation?

A
B
C
D
Test Your Knowledge

Which SPL search correctly calculates the 95th percentile of response times for only HTTP 500-series server error events per host, split by HTTP method, with the metric renamed to p95_server_err_ms?

A
B
C
D