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)
Hi @Ts_P,
I would recommend cloning the repository first and following the quick start rather than just downloading the migrate script.
Hope that helps!
Hi @Ts_P
I ping the internal team that owns this ... lets see if they come back with something.
Its pretty new.
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 ) 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.
thanks a lot @miguel-sanchez I will test it and let you know
$ ./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 ?
no you can run without uv using standard the python toolchain.
@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
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 !
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
@tommyers-elastic , @miguel-sanchez, @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.
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!