-1

I am trying to backfill Prometheus metrics data from files using a Docker container. My setup was working fine until I reinstalled Docker. Now, I am encountering the following error:

An error occurred: Command '['docker', 'exec', 'prometheus', '/bin/sh', '-c', 'promtool tsdb create-blocks-from openmetrics /etc/prometheus/data/openmetrics_prometheus_1720519200.txt /prometheus']' returned non-zero exit status 1.
stderr: getting min and max timestamp: next: data does not end with # EOF

I am running a script to backfill Prometheus metrics data from JSON files, converting them to OpenMetrics format, and appending # EOF to the end of each file. Here is the relevant part of my script:

import os
import subprocess
import json

def change_to_openmetrics(data, output_file_path):
    with open(output_file_path, "a") as output_file:
        for result in data["result"]:
            metric_name = result["metric"]["__name__"]
            labels = ",".join(
                [
                    f'{key}="{value}"'
                    for key, value in result["metric"].items()
                    if key != "__name__"
                ]
            )
            for value in result["values"]:
                timestamp = int(value[0])
                metric_value = float(value[1])
                output_file.write(
                    f"{metric_name}{{{labels}}} {metric_value} {timestamp}\n"
                )
    with open(output_file_path, "a") as output_file:
        output_file.write("# EOF\n")

def backfill_prometheus(folder_path):
    try:
        prometheus_container_name = "prometheus"
        files_found = False

        result = subprocess.run(
            [
                "docker",
                "ps",
                "--filter",
                f"name=^{prometheus_container_name}$",
                "--format",
                "{{.Names}}",
            ],
            capture_output=True,
            text=True,
        )
        if prometheus_container_name not in result.stdout.strip().split("\n"):
            print("Prometheus container is not running.")
            return

        if os.path.exists("./prometheus/data"):
            for f in os.listdir("./prometheus/data"):
                file_to_delete = os.path.join("./prometheus/data", f)
                if os.path.isfile(file_to_delete):
                    os.remove(file_to_delete)
                else:
                    print(f"Skipping non-file item: {file_to_delete}")

        for filename in os.listdir(folder_path):
            if not filename.endswith(".txt") and not filename.startswith("prometheus"):
                continue

            files_found = True
            file_path = os.path.join(folder_path, filename)
            openmetrics_filename = f"openmetrics_{filename}"
            openmetrics_file_path = os.path.join("./prometheus/data", openmetrics_filename)

            with open(file_path, "r") as file:
                for line in file:
                    try:
                        prometheus_data = json.loads(line.strip())
                        change_to_openmetrics(prometheus_data, openmetrics_file_path)
                    except json.JSONDecodeError:
                        print(f"Skipping line in file {filename} as it is not valid JSON.")

            with open(openmetrics_file_path, "a") as output_file:
                output_file.write("# EOF\n")

            cmd = (
                f"docker exec prometheus /bin/sh -c "
                f"'promtool tsdb create-blocks-from openmetrics /etc/prometheus/data/{openmetrics_filename} /prometheus'"
            )
            print(f"Running command: {cmd}")

            result = subprocess.run(
                [
                    "docker",
                    "exec",
                    "prometheus",
                    "/bin/sh",
                    "-c",
                    f"promtool tsdb create-blocks-from openmetrics /etc/prometheus/data/{openmetrics_filename} /prometheus",
                ],
                capture_output=True,
                text=True,
            )

            print("stdout:", result.stdout)
            print("stderr:", result.stderr)

            if result.returncode != 0:
                raise subprocess.CalledProcessError(result.returncode, result.args, output=result.stdout, stderr=result.stderr)

            print(f"Backfilled data from file: {filename}")

        if not files_found:
            print("No Prometheus data files found in the folder.")
        else:
            print("Backfilling complete for all files in the folder.")

    except subprocess.CalledProcessError as e:
        print(f"An error occurred: {e}")
        print("stdout:", e.output)
        print("stderr:", e.stderr)

# Example usage
# backfill_prometheus('/path/to/your/folder')

I tried runnig the command in terminal and its working succesfully, so the issue is not with the file.

2
  • Just to be clear: are you saying that result of docker exec prometheus /bin/sh -c promtool tsdb create-blocks-from openmetrics /etc/prometheus/data/openmetrics_prometheus_1720519200.txt /prometheus differ depending from how you start it?
    – markalex
    Commented Jul 9 at 14:23
  • Yaa basicall. It was working fine before. I don't know whats the reason now. I tried backfilling with a file of a smaller size using script, and it worked once, bit when I use a larger file, again it doesnt work. But it works in terminal. The command I ran on terminal is docker exec prometheus /bin/sh -c "promtool tsdb create-blocks-from openmetrics /etc/prometheus/data/openmetrics_prometheus_1720519200.txt /prometheus". Commented Jul 9 at 14:47

0

Browse other questions tagged or ask your own question.