influxdata / influxdb-client-python

InfluxDB 2.0 python client
https://influxdb-client.readthedocs.io/en/stable/
MIT License
706 stars 185 forks source link

Exception status is still <class 'influxdb_client.rest.ApiException'> #659

Closed syndrael closed 3 months ago

syndrael commented 3 months ago

Specifications

Code sample to reproduce problem

Sorry but i don't know to "easily" reproduce. Code is very complex.

OK (there are data after Epoch 1714739400): from(bucket: "indicator") |> range(start: 1714739400) KO (there are no data after Epoch 1801139400): from(bucket: "indicator") |> range(start: 1801139400)

All i know is if how you try to query in a range where start is above every records, you get Error 400: But instead of e.status = 400 str(e.status).split("\n") gives this results ['(400)', 'Reason: Bad Request', "HTTP response headers: HTTPHeaderDict({'Content-Type': 'application/json; charset=utf-8', 'Vary': 'Accept-Encoding', 'X-Influxdb-Build': 'OSS', 'X-Influxdb-Version': 'v2.7.6', 'X-Platform-Error-Code': 'invalid', 'Date': 'Sat, 25 May 2024 09:32:30 GMT', 'Transfer-Encoding': 'chunked'})", 'HTTP response body: b\'{"code":"invalid","message":"error in building plan while starting program: cannot query an empty range"}\'', ''] type(e.status) --> <class 'influxdb_client.rest.ApiException'> type(e.body) --> <class 'NoneType'>

It's like body was inside status

Expected behavior

type(e.status) --> int and e.body.. like every e.body.

Actual behavior

type(e.status) --> <class 'influxdb_client.rest.ApiException'> type(e.body) --> <class 'NoneType'>

str(e.status).split("\n") `['(400)', 'Reason: Bad Request', "HTTP response headers: HTTPHeaderDict({'Content-Type': 'application/json; charset=utf-8', 'Vary': 'Accept-Encoding', 'X-Influxdb-Build': 'OSS', 'X-Influxdb-Version': 'v2.7.6', 'X-Platform-Error-Code': 'invalid', 'Date': 'Sat, 25 May 2024 09:32:30 GMT', 'Transfer-Encoding': 'chunked'})", 'HTTP response body: b\'{"code":"invalid","message":"error in building plan while starting program: cannot query an empty range"}\'', '']

Additional info

No response

bednar commented 3 months ago

Hi @syndrael,

Thank you for reaching out. The error message you encountered, error in building plan while starting program: cannot query an empty range, typically indicates that the start time specified in your query is set in the future. This results in an empty range because there's no data to query from a future time point.

To address this and to properly handle similar errors, you can use structured error handling in your code. Below is an example using Python with our client that demonstrates how to handle exceptions gracefully using the ApiException class. This approach ensures you can catch and analyze errors directly related to the API operations:

from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS
from influxdb_client.rest import ApiException

with InfluxDBClient(url="http://localhost:8086", token="my-token", org="my-org", debug=False) as client:

    test1 = Point("pullrequest").tag("key1", "value1").field("status", "value2")
    test2 = Point("pullrequest").tag("key3", "value3").field("status", "value4")

    # Write data using point structure
    write_api = client.write_api(write_options=SYNCHRONOUS)
    write_api.write(bucket="my-bucket", record=[test1, test2])

    # Querying data using Table structure
    query_api = client.query_api()
    try:
        tables = query_api.query('from(bucket:"my-bucket") |> range(start: 1916796352) |> filter(fn: (r) => r._measurement == "pullrequest")')
        for table in tables:
            for record in table.records:
                print(record.values)
    except ApiException as e:
        print(f"Error message: {e.message}")
        print(f"Body: {e.body}")
        print(f"HTTP response status: {e.status}")

This script attempts to execute a query and handles any ApiException that might arise, logging detailed error information. Adjust the range(start: ...) value to a valid timestamp to avoid the specific error you're facing.

Let me know if this helps or if there's anything else you need!

Best Regards

syndrael commented 2 months ago

@bednar Thank you for your answer. You're right. I had to to address this by handling an error. But i don't undertand why an empty answer wouldn't give empty "tables" (in your example). An empty answer forces us to manage exceptions and errors or learn how to manage dates. Wouldn't it be easier to return an empty element? In our case, e.body and e.status don't provide the expected result. e.status is a multi-line character string, unlike the statuses we're used to dealing with. I hope you understand me. Regards.

bednar commented 2 months ago

@bednar Thank you for your answer. You're right. I had to to address this by handling an error. But i don't undertand why an empty answer wouldn't give empty "tables" (in your example). An empty answer forces us to manage exceptions and errors or learn how to manage dates. Wouldn't it be easier to return an empty element? In our case, e.body and e.status don't provide the expected result. e.status is a multi-line character string, unlike the statuses we're used to dealing with. I hope you understand me. Regards.

The error originates from the InfluxDB Server, and the client simply propagates it. This behavior is consistent with how Flux operates. For more details, you can refer to this issue: https://github.com/influxdata/flux/issues/3543.

syndrael commented 2 months ago

@bednar Thank you for this "root" cause. But :-) e.status is a multi-line character string, unlike the statuses we're used to dealing with. e.body and e.status don't provide the expected result. Can't the client correct it ? Regards

bednar commented 2 months ago

The e.status returning 400 is the expected result for a bad request. You can enable debug mode by setting debug=True to view HTTP responses from InfluxDB. If you want to learn how to properly handle exceptions, please refer to this example: https://github.com/influxdata/influxdb-client-python/blob/da7893615eaa1971086b5e7d517bcc283380c2d4/examples/connection_check.py#L25)