> ## Documentation Index
> Fetch the complete documentation index at: https://docs-xcor.paloaltonetworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Display data in a table

> Create and customize tables of data from query results for Palo Alto Networks Cortex XCOR dashboards.

<Note>
  [Classic dashboards](/observe/dashboards/classic-dashboards) have their own panels
  and methods of configuring them. For details about panels in classic dashboards,
  see [Classic dashboard panels](/observe/dashboards/classic-dashboards/classic-panels).
</Note>

A *table* panel in Palo Alto Networks Cortex XCOR organizes and displays the data
returned by one or more [queries](/investigate/querying) as a table with sortable
columns. For a metrics query, each row is one series, with a column for each of the
series' labels and a column for its value. A table can combine the results of
several queries into one row per series.

To create a table chart or learn more about the configuration options common
to all panels, see [Panels](/observe/dashboards/panels).

## Table chart queries

Table charts use one or more
[queries](/observe/dashboards/panels#change-a-panels-query) to retrieve data to
visualize. Table charts use the following query **Options** to refine the
displayed information, depending on your **Datasource**:

<Tabs>
  <Tab title="Metrics (Prometheus)" id="queries-metrics">
    * **Query type**: In the collapsible **Options** at the bottom of the **Query**
      tab, select the [PromQL query](/investigate/querying/promql#basic-querying) type:

      * **Instant**: Query for the latest value in the time range.
      * **Range**: Query for values across the time range. When you select **Range**,
        also set **Reduce values in time range to** to choose how Cortex XCOR
        reduces each series to a single value:

        * **Avg**: The series' mean value, excluding null values.
        * **First**: The series' first value.
        * **First \***: The series' first numeric value.
        * **Last**: The series' last value.
        * **Last \***: The series' last numeric value.
        * **Min**: The series' minimum value.
        * **Max**: The series' maximum value.
        * **Total**: The total of all values in the series.

    * **Min step**: The minimum step for the PromQL query. This option appears when
      **Query type** is **Range**.

    - **Truncation strategy**: Truncation strategy to apply to the query. This modifies
      the raw query. Cortex XCOR selects the best strategy for fit when
      possible, and displays `Auto` as the selected strategy.

      Available strategies are:

      * `Auto`
      * `Off`
      * `Avg`
      * `Min`
      * `Max`

      Changing your truncation strategy adds truncation information as additional bands
      or bars on your chart and details into the legend.
  </Tab>

  <Tab title="Logs" id="queries-logs">
    For logs, enter a valid query.
  </Tab>
</Tabs>

### Query example

The following example creates a table with multiple label values:

```text theme={null}
sum by (instance, environment) (METRIC_NAME)
```

Replace *`METRIC_NAME`* with the name of any metric with labels.

### Combine multiple queries

When a table has more than one query, Cortex XCOR joins the results into a single
table. Rows from different queries merge into one row when they have the same label
set, and each query adds its own value column. For example, three queries that each
aggregate `by (container)` produce one row per container, with one value column per
query.

A table combines its queries when all of the following are true:

* The table's **Time series format** is **Default**. The other formats don't merge
  rows across queries. See [Modify a table's data format](#modify-a-tables-data-format).
* Every query returns the same labels, for example, by aggregating each one with
  `sum by (container)`. Rows merge only when every label matches, so a query that
  returns an extra label produces separate rows for its series.
* Each query has an **Alias**. The alias becomes the header of that query's value
  column. Without aliases, the value columns are named `Value`, `Value (2)`,
  `Value (3)`, and so on.

Each value column holds the latest value for an **Instant** query, or the reduced
value for a **Range** query, as set by the query's **Query type** option.

In the panel's JSON representation, omit the `transform` field from the table's
`spec`, and set `alias` on each query. The `transform` field is deprecated. It
selects one of the legacy formats, which don't merge queries. For a complete example, see
[Table that combines multiple queries](#table-that-combines-multiple-queries).

## Use a table's tooltip

Cortex XCOR truncates the display of table values that exceed a column's width. To
view the complete value, hold the pointer over the truncated value in the table.

## Export a table as CSV

You can export a table's values as a CSV file.

1. In the panel, click the <Icon icon="ellipsis-vertical" /> icon.
2. Select **Export CSV**.

## Configure a table

You can configure a table by
[modifying its <Icon icon="settings" /> **Settings**](/observe/dashboards/panels#edit-a-panel).

Cortex XCOR doesn't fully support directly editing a panel's JSON
representation. To configure a panel, edit it and modify individual fields. Use the JSON
representation only for managing your configuration as code with tools such as
[Chronoctl](/tooling/chronoctl) and [Terraform](/tooling/infrastructure/terraform).

### Modify a table's data format

The **Data Format** section in a table's **Settings** tab defines how the table
interprets the panel's query results for tabular display.

To define the table's data format, select a **Time series format**.

* **Default** displays the query results as returned, with one row per series, a
  column for each label, and a value column for each query. Rows from multiple
  queries merge when their labels match. Use this format for new tables. See
  [Combine multiple queries](#combine-multiple-queries).
* **Series To Rows** displays each series as a row in the table. You must also select
  which **Calculations** to apply to the series and display in the table. If the
  series contains labels, you can also toggle **Label-based columns**, which adds
  a column for each series' label when enabled.
* **Series To Columns** displays each series as a column in the table. Each row
  in the table represents one data point in the series with the timestamp indicated
  in the **Time** column.
* **Raw** displays the timestamp and value for each data point of a selected series.

**Series To Rows**, **Series To Columns**, and **Raw** are legacy formats. They
reshape raw time series in the browser instead of displaying the query results
directly, and they don't merge rows across queries. In the panel's JSON
representation, these formats set the table's `transform` field, and **Default**
omits it.

Changing the format resets the table's sorting and the settings in its
**Table columns** tab.

### Modify a table's sorting

The **Sorting** section in a table's **Settings** tab controls the table's sorting
order.

* **Sort by**: Determines the column used to sort the table.
* **Sort order**: Determines whether to display the table's contents in its **Default**
  original data order, or to sort it in **Ascending** or **Descending** order.
  Cortex XCOR disables this field until you select a **Sort by** column.

To add multiple sorting criteria:

1. Set a **Sort by** column.
2. Click **+** (**Add sort**) to add a sorting criteria.

To remove a sorting criteria, click **<Icon icon="trash" alt="Delete icon" /> Delete**
on the row of the criteria you want to remove.

In the expanded panel view, click a column header to sort by that column. Each click
toggles between ascending and descending order.

### Modify a table's units

The **Unit and formatting** section in a table's **Settings** tab controls how
Cortex XCOR interprets the units of data in the table.

* **Unit**: Defines the unit used to render the Y-axis. This has the most significant
  effect when you enable Abbreviate. Defaults to `Decimal`.
  * **Decimal**: Base 10 values. Cortex XCOR renders a value of
    `1000000` as `1M`.
  * **Bytes**: As decimal multiple-byte units. Cortex XCOR renders a
    value of `1000000` as `1MB`.
  * **Time**: Determines the [unit of time](/overview/concepts/time-units)
    that Cortex XCOR uses to interpret a numeric value.
  * **Percent**: Interprets the value as a percentile, representing 0% to 100% in a
    range of either 0.0 to 1.0 (**Percent (0.0-1.0)**) or 0 and 100
    (**Percent (0-100)**).

    For example, Cortex XCOR renders a value of `1.0` in **Percent
    (0.0-1.0)** as `100%`, and in **Percent (0-100)** as `1%`.
* **Decimals**: Defines how many decimal places Cortex XCOR renders for
  values.
  **Default** renders decimal places only if necessary and rounds to the nearest
  value. Numeric values from `0` to `4` render the corresponding number of decimal
  places.
* **Abbreviate**: Toggles whether to abbreviate units on the Y-axis. For example, if
  enabled, Cortex XCOR renders a value of `100000000` as `100M`. You can
  toggle this setting only if you set the **Unit** to `Decimal` or `Bytes`; `Time`
  units are always abbreviated and `Percent` values don't require the toggle.
  Defaults to `true`.

To discard your changes and restore the panel's settings to their defaults, click
**Reset all settings to defaults**.

### Configure a table's thresholds

The **Thresholds** section in a table chart's **Settings** tab defines values where
Cortex XCOR renders each threshold range. You can set a single threshold
to differentiate, or multiple thresholds to indicate severity level. For example,
you might want a warning value in orange, and a critical value in red.

To create a new threshold:

1. Edit a table panel.
2. Click the **Settings** tab.
3. In the **Thresholds** section, click the <Icon icon="plus" /> plus icon.
4. Enter a value in the **When value is >=** text box.
5. Use the color box to select a color for the threshold.
6. Optional: Click the caret (**>**) to expand a row and update the **Message** field.
7. Click the <Icon icon="plus" /> plus icon to add more threshold levels.
8. When finished, click **Apply**.

After applying the changes, the table updates with the selected color highlighting
the violated threshold.

To delete a threshold value, click the caret (**>**) to expand the threshold definition,
and then click
**<Icon icon="trash" alt="Delete icon" /> Delete threshold**.

### Configure a table's columns

The **Table columns** tab in a table's **Edit panel** interface controls whether
to display certain columns in the table and lets you edit their headings. The
tab lists each table column in a separate row.

* **Visibility**: Toggles whether to display the column.
* **Name**: Displays the column's original name.
* **Display Name**: Defines the name used in the column's header.
* **Order**: Use the arrows to reorder the table.

Expand a column row to set its **Type** and column-specific formatting. Choose
**Number**, **String**, or **Time**. Set **Type** to **Number** when a column stores
numeric text so the table sorts and formats values numerically instead of sorting
lexically by string.

## Table examples

The following examples are [JSON formatted](/observe/dashboards/panels/json-representation)
dashboard code. Modify the variables in these examples for your tenant and applications.

### Table that combines multiple queries

This table compares CPU usage with CPU requests for each container in a Kubernetes
namespace. Each query aggregates `by (container)`, so the table merges the three
results into one row per container. Each query's `alias` names its value column, and
the `columnOverrides` entries rename the `container` label column and format the
ratio as a percentage. The queries use a
[dashboard variable](/observe/dashboards/customization/dashboard-variables) named
`namespace`.

```json Table that combines multiple queries expandable theme={null}
{
  "kind": "Panel",
  "spec": {
    "display": {
      "name": "CPU quota by container"
    },
    "plugin": {
      "kind": "Table",
      "spec": {
        "columnOverrides": [
          {
            "value": "container",
            "properties": {
              "displayName": "Container"
            }
          },
          {
            "value": "CPU requests %",
            "properties": {
              "format": {
                "kind": "Number",
                "unit": {
                  "kind": "PercentDecimal"
                }
              }
            }
          }
        ],
        "column_order": ["container", "CPU usage", "CPU requests", "CPU requests %"]
      }
    },
    "queries": [
      {
        "kind": "DataQuery",
        "spec": {
          "alias": "CPU usage",
          "plugin": {
            "kind": "PrometheusTimeSeriesQuery",
            "spec": {
              "query": "sum by (container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", container!=\"\"}[5m]))"
            }
          }
        }
      },
      {
        "kind": "DataQuery",
        "spec": {
          "alias": "CPU requests",
          "plugin": {
            "kind": "PrometheusTimeSeriesQuery",
            "spec": {
              "query": "sum by (container) (kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"})"
            }
          }
        }
      },
      {
        "kind": "DataQuery",
        "spec": {
          "alias": "CPU requests %",
          "plugin": {
            "kind": "PrometheusTimeSeriesQuery",
            "spec": {
              "query": "sum by (container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", container!=\"\"}[5m])) / sum by (container) (kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"})"
            }
          }
        }
      }
    ]
  }
}
```

### Table with severity by color

This table lists items sorted by severity, and applies color to the **Severity**
column based on the resulting value:

```json Table with colored severity expandable theme={null}
{
  "kind": "Panel",
  "spec": {
    "display": {
      "name": "Table by category",
      "description": ""
    },
    "plugin": {
      "kind": "Table",
      "spec": {
        "columnOverrides": [
          {
            "properties": {
              "displayName": "Category A",
              "format": {
                "kind": "Number",
                "thresholds": {
                  "base": {
                    "color": "#2A75CF"
                  }
                }
              }
            },
            "value": "sent_by_gmail"
          },
          {
            "properties": {
              "displayName": "Category B"
            },
            "value": "sent_by_exchange"
          },
          {
            "properties": {
              "displayName": "Category C"
            },
            "value": "sent_by_channel_c"
          },
          {
            "properties": {
              "displayName": "Resource ID",
              "format": {
                "kind": "String",
                "overrides": []
              }
            },
            "value": "account_id"
          },
          {
            "properties": {
              "displayName": "Category C"
            },
            "value": "sent_by_ticket"
          }
        ],
        "sort": [],
        "thresholds": {
          "base": {
            "color": "#2A75CF"
          }
        }
      }
    },
    "queries": [
      {
        "kind": "DataQuery",
        "spec": {
          "alias": "Category A",
          "plugin": {
            "kind": "LogsDataQuery",
            "spec": {
              "query": "#\"query 1\": \"@tags:MailRenderingJob* $NotificationId $AccountId \\\"sent by Gmail, response code is\\\"\"\n#\"query 2\": \"@tags:MailRenderingJob* $NotificationId $AccountId \\\"Using Exchange Connector\\\"\"\n#\"query 3\": \"@tags:MailRenderingJob* $NotificationId $AccountId -\\\"sent by Gmail, response code is\\\" -\\\"Using Exchange Connector\\\"\"\nservice=\"classic\"\ntags: \"MailRenderingJob\"\n\"$AccountId\"\n| summarize sent_by_gmail = countif(message: \"sent by Gmail\"), sent_by_exchange = countif(message: \"Using Exchange Connector\"), sent_by_ticket = countif(NOT  (\"Using Exchange Connector\" OR \"sent by Gmail, response code is\")) by account_id ",
              "reducer": "Sum",
              "series_name": {
                "name_pattern": "Category A",
                "type": "Labels"
              }
            }
          }
        }
      }
    ],
    "formulas": [],
    "links": []
  }
}
```

### Table with additional columns

This table overrides the default columns and adds additional columns:

```json Additional columns expandable theme={null}
{
  "kind": "Panel",
  "spec": {
    "display": {
      "name": "Table by delivery status",
      "description": ""
    },
    "plugin": {
      "kind": "Table",
      "spec": {
        "columnOverrides": [
          {
            "properties": {
              "displayName": "DATA.ENVELOPE.TARGET",
              "width": 540.5
            },
            "value": "data.envelope.recipient"
          },
          {
            "properties": {
              "displayName": "DATA.STATUS.CODE",
              "format": {
                "kind": "String",
                "overrides": [
                  {
                    "matcher": {
                      "type": "ByName"
                    },
                    "properties": {
                      "background_color": "#7edb76"
                    },
                    "value": "250"
                  },
                  {
                    "matcher": {
                      "type": "ByRegex"
                    },
                    "properties": {
                      "background_color": "#fadfc2"
                    },
                    "value": "4.*"
                  },
                  {
                    "matcher": {
                      "type": "ByRegex"
                    },
                    "properties": {
                      "background_color": "#f34949"
                    },
                    "value": "5.*"
                  }
                ]
              }
            },
            "value": "data.delivery_code"
          },
          {
            "properties": {
              "displayName": "DATA.SUMMARY.LABEL"
            },
            "value": "data.summary.customer"
          },
          {
            "properties": {
              "displayName": "LOGS"
            },
            "value": "count_"
          }
        ],
        "unit": {
          "abbreviate": true,
          "kind": "Decimal"
        }
      }
    },
    "queries": [
      {
        "kind": "DataQuery",
        "spec": {
          "plugin": {
            "kind": "LogsDataQuery",
            "spec": {
              "query": "#\"query\": \"service:example-service @data.summary.customer:* @email_id:* -@data.envelope.recipient:mailarchive *:$MessageId.value $AccountId\"\nservice=\"example-service\"\ndata.summary.customer EXISTS\nemail_id EXISTS\nNOT data.envelope.recipient: \"mailarchive\"\nmessage_id =~ \"$MessageId\"\naccount_id =~ \"$AccountId\"\n| summarize by data.delivery_code,data.envelope.recipient,data.summary.customer ",
              "reducer": "Last"
            }
          }
        }
      }
    ],
    "formulas": [],
    "links": []
  }
}
```

### Table with custom columns and color coding based on result

This table adds custom columns and adds color to one of the columns based on the
query result:

```json Custom columns and color coding expandable theme={null}
{
  "kind": "Panel",
  "spec": {
    "display": {
      "name": "Table with status codes",
      "description": ""
    },
    "plugin": {
      "kind": "Table",
      "spec": {
        "columnOverrides": [
          {
            "properties": {
              "format": {
                "kind": "String",
                "overrides": [
                  {
                    "matcher": {
                      "type": "ByRegex"
                    },
                    "properties": {
                      "background_color": "#fadfc2"
                    },
                    "value": "4.*"
                  },
                  {
                    "matcher": {
                      "type": "ByRegex"
                    },
                    "properties": {
                      "background_color": "#f34949"
                    },
                    "value": "5.*"
                  }
                ]
              }
            },
            "value": "data.delivery_code"
          },
          {
            "properties": {
              "displayName": "Source"
            },
            "value": "data.envelope.sender"
          }
        ],
        "unit": {
          "abbreviate": true,
          "kind": "Decimal"
        }
      }
    },
    "queries": [
      {
        "kind": "DataQuery",
        "spec": {
          "plugin": {
            "kind": "LogsDataQuery",
            "spec": {
              "query": "# \"query\": \"service:example-service @data.envelope.recipient:*example.com -@data.remote.mx:mailarchive -@data.envelope.sender:*.example.com $AccountId @data.mailfrom_account_id:* @message_id:*username@example.com> @test.service:out status:(warn OR error)\"\nservice = \"example-service\"\ndata.envelope.recipient: \"example.com\"\nNOT data.remote.mx = \"mailarchive\"\nNOT data.envelope.sender: \"example.com\"\naccount_id =~ \"$AccountId\"\ndata.mailfrom_account_id EXISTS\nmessage_id =~ \"username@example.com|username@example-staging.com\"\ntest.service: \"out\"\nseverity =~ \"ERROR|WARN\"\n| summarize by data.envelope.sender,data.delivery_code,data.response.text,data.summary.customer",
              "reducer": "Last"
            }
          }
        }
      }
    ],
    "formulas": [],
    "links": []
  }
}
```


## Related topics

- [Create lookup tables for log data](/control/shaping/shape-logs/lookup-logs.md)
- [Review aggregation rules](/control/shaping/shape-metrics/reduce-cardinality/aggregation-rules.md)
- [Visualize proportional data with pie charts](/observe/dashboards/panels/pie-chart.md)
- [Visualize data using dashboards](/observe/dashboards.md)
- [Analyze live traffic traces](/investigate/analyze/trace-analyzer.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.