# ClickHouse data source for Grafana
<img alt="Grafana Dashboard Screenshot - Query Analysis" src="https://github.com/grafana/clickhouse-datasource/assets/5509570/d129936e-afac-4002-8963-61c15825c154" width="400" >
<img alt="Grafana Dashboard Screenshot - Data Analysis" src="https://github.com/grafana/clickhouse-datasource/assets/5509570/5911f72b-0a52-4e1e-9cd4-3905ac0623cd" width="400" >
## Version compatibility
Users on `v8.x` of Grafana are encouraged to continue to use `v2.2.0` of the plugin.
Users on `v9.x` and higher of Grafana can use `v3` however it is `beta` and may contain bugs.
The ClickHouse data source plugin allows you to query and visualize ClickHouse
data from within Grafana.
**As of 2.0 this plugin will only support ad hoc filters when using ClickHouse 22.7+**
## Installation
For detailed instructions on how to install the plugin on Grafana Cloud or
locally, please checkout the [Plugin installation docs](https://grafana.com/docs/grafana/latest/plugins/installation/).
## Configuration
### ClickHouse user for the data source
Set up an ClickHouse user account with [readonly](https://clickhouse.com/docs/en/operations/settings/permissions-for-queries#settings_readonly) permission and access to
databases and tables you want to query. Please note that Grafana does not
validate that queries are safe. Queries can contain any SQL statement. For
example, statements like `ALTER TABLE system.users DELETE WHERE name='sadUser'`
and `DROP TABLE sadTable;` would be executed.
To configure a readonly user, follow these steps:
1. Create a `readonly` user profile following the [Creating Users and Roles in ClickHouse](https://clickhouse.com/docs/en/operations/access-rights) guide.
2. Ensure the `readonly` user has enough permission to modify the `max_execution_time` setting required by the underlying [clickhouse-go client](https://github.com/ClickHouse/clickhouse-go/).
3. If you're using a public Clickhouse instance, it's not recommended to set `readonly=2` in the `readonly` profile. Instead, leave `readonly=1` and set the constraint type of `max_execution_time` to [changeable_in_readonly](https://clickhouse.com/docs/en/operations/settings/constraints-on-settings) to allow modification of this setting.
### ClickHouse protocol support
The plugin supports both `HTTP` and `Native` (default) transport protocols. This can be enabled in the configuration via the `protocol` configuration parameter. Both protocols exchange data with ClickHouse using optimized native format.
Note that the default ports for `HTTP/s` and `Native` differ:
- HTTP - 8123
- HTTPS - 8443
- Native - 9000
- Native with TLS - 9440
### Manual configuration
Once the plugin is installed on your Grafana instance, follow [these
instructions](https://grafana.com/docs/grafana/latest/datasources/add-a-data-source/)
to add a new ClickHouse data source, and enter configuration options.
### With a configuration file
It is possible to configure data sources using configuration files with
Grafana’s provisioning system. To read about how it works, including all the
settings that you can set for this data source, refer to [Provisioning Grafana
data sources](https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources).
Here are some provisioning examples for this data source using basic authentication:
```yaml
apiVersion: 1
datasources:
- name: ClickHouse
type: grafana-clickhouse-datasource
jsonData:
defaultDatabase: database
port: 9000
server: localhost
username: username
tlsSkipVerify: false
secureJsonData:
password: password
```
## Building queries
The query editor allows you to query ClickHouse to return time series or
tabular data. Queries can contain macros which simplify syntax and allow for
dynamic parts.
### Time series
Time series visualization options are selectable after adding a `datetime`
field type to your query. This field will be used as the timestamp. You can
select time series visualizations using the visualization options. Grafana
interprets timestamp rows without explicit time zone as UTC. Any column except
`time` is treated as a value column.
#### Multi-line time series
To create multi-line time series, the query must return at least 3 fields in
the following order:
- field 1: `datetime` field with an alias of `time`
- field 2: value to group by
- field 3+: the metric values
For example:
```sql
SELECT log_time AS time, machine_group, avg(disk_free) AS avg_disk_free
FROM mgbench.logs1
GROUP BY machine_group, log_time
ORDER BY log_time
```
### Tables
Table visualizations will always be available for any valid ClickHouse query.
### Visualizing logs with the Logs Panel
To use the Logs panel your query must return a timestamp and string values. To default to the logs visualization in Explore mode, set the timestamp alias to *log_time*.
For example:
```sql
SELECT log_time AS log_time, machine_group, toString(avg(disk_free)) AS avg_disk_free
FROM logs1
GROUP BY machine_group, log_time
ORDER BY log_time
```
To force rendering as logs, in absence of a `log_time` column, set the Format to `Logs` (available from 2.2.0).
### Visualizing traces with the Traces Panel
Ensure your data meets the [requirements of the traces panel](https://grafana.com/docs/grafana/latest/explore/trace-integration/#data-api). This applies if using the visualization or Explore view.
Set the Format to `Trace` when constructing the query (available from 2.2.0).
If using the [Open Telemetry Collector and ClickHouse exporter](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/clickhouseexporter), the following query produces the required column names (these are case sensitive):
```sql
SELECT
TraceId AS traceID,
SpanId AS spanID,
SpanName AS operationName,
ParentSpanId AS parentSpanID,
ServiceName AS serviceName,
Duration / 1000000 AS duration,
Timestamp AS startTime,
arrayMap(key -> map('key', key, 'value', SpanAttributes[key]), mapKeys(SpanAttributes)) AS tags,
arrayMap(key -> map('key', key, 'value', ResourceAttributes[key]), mapKeys(ResourceAttributes)) AS serviceTags
FROM otel.otel_traces
WHERE TraceId = '61d489320c01243966700e172ab37081'
ORDER BY startTime ASC
```
### Macros
To simplify syntax and to allow for dynamic parts, like date range filters, the query can contain macros.
Here is an example of a query with a macro that will use Grafana's time filter:
```sql
SELECT date_time, data_stuff
FROM test_data
WHERE $__timeFilter(date_time)
```
| Macro | Description | Output example |
|----------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|
| *$__timeFilter(columnName)* | Replaced by a conditional that filters the data (using the provided column) based on the time range of the panel in seconds | `time >= '1480001790' AND time <= '1482576232' )` |
| *$__dateFilter(columnName)* | Replaced by a conditional that filters the data (using the provided column) based on the date range of the panel | `date >= '2022-10-21' AND date <= '2022-10-23' )` |
| *$__timeFilter_ms(columnName)* | Replaced by a conditional that filters the data (using the provided column) based on the time range of the panel in milliseconds