# Grafana to Elastic stack migration

**URL:** <https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604>\
**Category:** Elastic Observability\
**Created:** [July 6, 2026, 12:13pm UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604 "2026-07-06T12:13:18Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ts\_P](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ts_p/32/147683_2.png) [@Ts\_P](https://discuss.elastic.co/u/Ts_P)\
**Post date:** [July 6, 2026, 12:13pm UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/1 "2026-07-06T12:13:18Z")

</div>

I wanna migrate from Grafana to Elastic stack .  
I found this repository and few articles.  
Can I download the binary files directly **obs-migrate**?(for windows 11 x64)

> **[GitHub - elastic/observability-migration-platform: source-agnostic tooling for migrating...](https://github.com/elastic/observability-migration-platform)**
>
> source-agnostic tooling for migrating observability assets

---

<div class="post-metadata">

**Author:** ![carly.richmond](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/carly.richmond/32/104935_2.png) [@carly.richmond](https://discuss.elastic.co/u/carly.richmond)\
**Post date:** [July 6, 2026, 4:10pm UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/2 "2026-07-06T16:10:02Z")

</div>

Hi @Ts_P,

I would recommend cloning the repository first and following the [quick start](https://github.com/elastic/observability-migration-platform#quick-start) rather than just downloading the migrate script.

Hope that helps!

---

<div class="post-metadata">

**Author:** ![stephenb](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/stephenb/32/40856_2.png) [@stephenb](https://discuss.elastic.co/u/stephenb)\
**Post date:** [July 6, 2026, 4:54pm UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/3 "2026-07-06T16:54:48Z")

</div>

Hi @Ts_P

I ping the internal team that owns this ... lets see if they come back with something.

Its pretty new.

---

<div class="post-metadata">

**Author:** ![miguel-sanchez](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/miguel-sanchez/32/142564_2.png) [@miguel-sanchez](https://discuss.elastic.co/u/miguel-sanchez)\
**Post date:** [July 7, 2026, 10:59am UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/4 "2026-07-07T10:59:31Z")

</div>

Hi @Ts_P ,

I'm part of the team working on the Observability Migration Platform. There is no packaged binary today; the tool is a Python CLI, not a standalone installer. Simpler distribution via PyPI/uvx is on our roadmap, but not available yet.

The supported path is cloning the repo and following the Quick Start.

We haven't validated Windows 11 x64 and we are still in technical preview. The CLI itself is plain Python with no deliberate OS-specific logic, so it may work on Windows, but we can't guarantee it yet.

We'll be happy to assist if you run into any complications, please reach out or open a GitHub issue ( [Issues · elastic/observability-migration-platform · GitHub](https://github.com/elastic/observability-migration-platform/issues) ) with your OS, Python version, and the output of obs-migrate doctor, and we'll provide guidance or use the feedback to improve the tool.

Thanks for your interest in the tool, don't hesitate to reach back out if you encounter anything along the way.

---

<div class="post-metadata">

**Author:** ![Ts\_P](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ts_p/32/147683_2.png) [@Ts\_P](https://discuss.elastic.co/u/Ts_P)\
**Post date:** [July 7, 2026, 11:15am UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/5 "2026-07-07T11:15:29Z")

</div>

thanks a lot @miguel-sanchez I will test it and let you know

---

<div class="post-metadata">

**Author:** ![Ts\_P](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ts_p/32/147683_2.png) [@Ts\_P](https://discuss.elastic.co/u/Ts_P)\
**Post date:** [July 7, 2026, 1:26pm UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/6 "2026-07-07T13:26:49Z")

</div>

@miguel-sanchez

$ ./obs-migrate.exe doctor  
obs-migrate doctor  
pinned kb-dashboard tool version: 0.4.1  
uv on PATH: no  
kb-dashboard-cli: available (installed)  
kb-dashboard-lint: available (installed)

is the "uv on PATH" missing critical ?

---

<div class="post-metadata">

**Author:** ![tommyers-elastic](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/tommyers-elastic/32/107559_2.png) [@tommyers-elastic](https://discuss.elastic.co/u/tommyers-elastic)\
**Post date:** [July 7, 2026, 1:52pm UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/7 "2026-07-07T13:52:26Z")

</div>

no you can run without `uv` using standard the python toolchain.

---

<div class="post-metadata">

**Author:** ![Ts\_P](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ts_p/32/147683_2.png) [@Ts\_P](https://discuss.elastic.co/u/Ts_P)\
**Post date:** [July 9, 2026, 3:45pm UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/8 "2026-07-09T15:45:35Z")

</div>

@tommyers-elastic I quickly tested the dashboard against dashboard json from Grafana .  
It went well . I even ingested it manually in Kibana.  
I saw in the logs these messages.

Is this expected because it is an early version of that tool or because I run it on windows 11.

`NOT FEASIBLE (20 panels):`  
`[OpenTelemetry Collector] Spans: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_receiver_accepted_spans${suffix}{receiver=~"$receiver",job="$job"}[$_ra`  
`[OpenTelemetry Collector] Metric Points: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_receiver_accepted_metric_points${suffix}{receiver=~"$receiver",job="$job`  
`[OpenTelemetry Collector] Log Records: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_receiver_accepted_log_records${suffix}{receiver=~"$receiver",job="$job"}`  
`[OpenTelemetry Collector] Spans: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_processor_accepted_spans${suffix}{processor=~"$processor",job="$job"}[$`  
`[OpenTelemetry Collector] Metric Points: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_processor_accepted_metric_points${suffix}{processor=~"$processor",job="$`  
`[OpenTelemetry Collector] Log Records: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_processor_accepted_log_records${suffix}{processor=~"$processor",job="$jo`  
`[OpenTelemetry Collector] Batch Metrics 1: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_processor_batch_batch_send_size_count{processor=~"$processor",job="$job"`  
`[OpenTelemetry Collector] Batch Metrics 2: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_processor_batch_batch_size_trigger_send${suffix}{processor=~"$processor"`  
`[OpenTelemetry Collector] Spans: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_exporter_sent_spans${suffix}{exporter=~"$exporter",job="$job"}[$rate_i`  
`[OpenTelemetry Collector] Metric Points: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_exporter_sent_metric_points${suffix}{exporter=~"$exporter",job="$job"}[$`  
`[OpenTelemetry Collector] Log Records: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: sum(${metric:value}(otelcol_exporter_sent_log_records${suffix}{exporter=~"$exporter",job="$job"}[$`  
`[OpenTelemetry Collector] Exporter Queue Size: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: max(otelcol_exporter_queue_size{exporter=~"$exporter",job="$job"}) by (exporter $grouping)`  
`[OpenTelemetry Collector] Exporter Queue Capacity: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: min(otelcol_exporter_queue_capacity{exporter=~"$exporter",job="$job"}) by (exporter $grouping)`  
`[OpenTelemetry Collector] Exporter Queue Usage: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: max(`  
`otelcol_exporter_queue_size{`  
`exporter=~"$exporter", job="$job"`  
`}`  
`) by (expo`  
`[OpenTelemetry Collector] Total RSS Memory: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: max(otelcol_process_memory_rss{job="$job"}) by (job $grouping)`  
`[OpenTelemetry Collector] Total Runtime Sys Memory: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: max(otelcol_process_runtime_total_sys_memory_bytes{job="$job"}) by (job $grouping)`  
`[OpenTelemetry Collector] Total Runtime Heap Memory: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: max(otelcol_process_runtime_heap_alloc_bytes{job="$job"}) by (job $grouping)`  
`[OpenTelemetry Collector] CPU Usage: BY/WITHOUT clause contains Grafana template variable ($grouping); grouping dimension is unknown at migration time and requires manual redesign`  
`PromQL: max(rate(otelcol_process_cpu_seconds${suffix}{job="$job"}[$__rate_interval])*100) by (job $grouping)`  
`[OpenTelemetry Collector] RPC server responses by GRPC status code (receivers): AST parse failed (unknown function with name 'label_metric'), using regex fragment parser`  
`PromQL: sum by(rpc_grpc_status_code) (${metric:value}(otelcol_rpc_server_responses_per_rpc_count{}[$__rate_i`  
`[OpenTelemetry Collector] RPC client responses by GRPC status code (exporters): AST parse failed (unknown function with name 'label_metric'), using regex fragment parser`  
`PromQL: sum by(rpc_grpc_status_code) (${metric:value}(otelcol_rpc_client_responses_per_rpc_count{}[$__rate_i`

---

<div class="post-metadata">

**Author:** ![tommyers-elastic](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/tommyers-elastic/32/107559_2.png) [@tommyers-elastic](https://discuss.elastic.co/u/tommyers-elastic)\
**Post date:** [July 9, 2026, 4:18pm UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/9 "2026-07-09T16:18:26Z")

</div>

thanks for the detail! some of this is expected (i.e. we don't currently support it) e.g. late binding variables. but some are potentially bugs e.g. `[OpenTelemetry Collector] RPC client responses by GRPC status code (exporters): AST parse failed (unknown function with name 'label_metric'), using regex fragment parser`

we'll look into it !

---

<div class="post-metadata">

**Author:** ![Ts\_P](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ts_p/32/147683_2.png) [@Ts\_P](https://discuss.elastic.co/u/Ts_P)\
**Post date:** [July 10, 2026, 8:15am UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/10 "2026-07-10T08:15:29Z")

</div>

awesome thanks a lot.  
I have tested with another sample dashboard json from grafana.

NOT FEASIBLE (4 panels):  
`[Kubewarden] 90th percentile evaluation latency: histogram_quantile target field type could not be determined; cannot safely translate to ES|QL PERCENTILE() (verify the base metric is a histogram or exponential_histogram field on the target index)`  
`PromQL: histogram_quantile(.90, sum(rate(kubewarden_policy_evaluation_latency_milliseconds_bucket[$__interva`  
`[Kubewarden] policy accepted request percentage: PromQL arithmetic with divergent filters/groupings cannot be translated safely yet`  
`PromQL: sum(kubewarden_policy_evaluations_total{accepted="true",mutated="false", policy_name="$policy_name"`  
`[Kubewarden] policy request rejection percentage: PromQL arithmetic with divergent filters/groupings cannot be translated safely yet`  
`PromQL: sum(kubewarden_policy_evaluations_total{accepted="false", policy_name="$policy_name" })*100/sum(kube`  
`[Kubewarden] policy mutation request percentage: PromQL arithmetic with divergent filters/groupings cannot be translated safely yet`  
`PromQL: sum(kubewarden_policy_evaluations_total{mutated="true", policy_name="$policy_name" })*100/sum(kubewa`

---

<div class="post-metadata">

**Author:** ![Ts\_P](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ts_p/32/147683_2.png) [@Ts\_P](https://discuss.elastic.co/u/Ts_P)\
**Post date:** [July 16, 2026, 12:01pm UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/11 "2026-07-16T12:01:03Z")

</div>

@tommyers-elastic , @**[miguel-sanchez](https://discuss.elastic.co/u/miguel-sanchez), @[carly.richmond](https://discuss.elastic.co/u/carly.richmond)**

I tested the Grafana to Kibana dashboard migration tool on another dashboard: **Kubernetes / Compute Resources / Pod (from Suse Rancher - Grafana )**.

The migration was successful, and it generated an **NDJSON** file that imports correctly into Kibana (a few panels were flagged with warnings).

Our goal is **not** to migrate Prometheus data or modify the Prometheus configuration to send metrics to Elasticsearch. We already ingest our OpenTelemetry Kubernetes metrics into Elasticsearch and would like to reuse that existing data.  
I read this one  
`PromQL support is not limited to metrics ingested through Prometheus remote write. All TSDS are supported, including metrics ingested through OpenTelemetry Protocol (OTLP), and the bulk API.`

My question is:

- Is it feasible to take the migrated dashboard and simply update its queries so they point to our existing OpenTelemetry metrics in Elasticsearch?
- We already have Kubernetes metric data available, and Kibana includes managed dashboards such as **[OTEL] [Metrics Kubernetes] Cluster Overview**. Can we reuse the same data views and field mappings for the migrated dashboard?
- Or is it generally more practical to recreate the dashboard manually in Kibana instead of adapting the migrated one?

Has anyone had experience migrating Grafana dashboards to Kibana **without migrating the underlying data** , but instead reusing existing OpenTelemetry data already stored in Elasticsearch?

I'd appreciate any recommendations or lessons learned.

---

<div class="post-metadata">

**Author:** ![tommyers-elastic](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/tommyers-elastic/32/107559_2.png) [@tommyers-elastic](https://discuss.elastic.co/u/tommyers-elastic)\
**Post date:** [July 27, 2026, 3:28pm UTC](https://discuss.elastic.co/t/grafana-to-elastic-stack-migration/387604/12 "2026-07-27T15:28:18Z")

</div>

The OOTB dashboards you mention are designed to work with the default OTel K8s operator. The mappings are handled by bundled Kibana dynamic mappings for OTel logs and metrics, so everything should work without any manual input.

On this question:

> Is it feasible to take the migrated dashboard and simply update its queries so they point to our existing OpenTelemetry metrics in Elasticsearch?

We have recently added options to the migration tool which will help to do this conversation during migration itself. There are a couple of useful options: `--field-profile=otel` will translate labels which should help keep filter options working. For cases where this isn't sufficient, we have added `--metric-map-file` which allows you to add custom field name mappings; this should allow you to define the field names you need to translate once, and use them in bulk migrations.

These options will be available in the next release, which is coming soon!
