influxdata / influxdb-python

Python client for InfluxDB
MIT License
1.7k stars 521 forks source link

Suggestion: run queries copy/pasted from grafana/influx dash #924

Open SGStino opened 2 years ago

SGStino commented 2 years ago

Mainly, can we somehow get this extern (snooped from chrome's dev tools):

{
  "extern": {
    "type": "File",
    "package": null,
    "imports": null,
    "body": [
      {
        "type": "OptionStatement",
        "assignment": {
          "type": "VariableAssignment",
          "id": {
            "type": "Identifier",
            "name": "v"
          },
          "init": {
            "type": "ObjectExpression",
            "properties": [
              {
                "type": "Property",
                "key": {
                  "type": "Identifier",
                  "name": "timeRangeStart"
                },
                "value": {
                  "type": "DateTimeLiteral",
                  "value": "2022-10-06T19:53:24.520584"
                }
              },
              {
                "type": "Property",
                "key": {
                  "type": "Identifier",
                  "name": "timeRangeStop"
                },
                "value": {
                  "type": "DateTimeLiteral",
                  "value": "2022-10-07T19:53:24.520584"
                }
              },
              {
                "type": "Property",
                "key": {
                  "type": "Identifier",
                  "name": "windowPeriod"
                },
                "value": {
                  "type": "DurationLiteral",
                  "values": [
                    {
                      "magnitude": 864000,
                      "unit": "ms"
                    }
                  ]
                }
              }
            ]
          }
        }
      }
    ]
  },

I'm guessing the Query() object needs to be created with an extern set like this, however, I am getting json serialization errors.

from influxdb_client import Query
query = Query(**create_request(query1, start, stop))
api._query_api.post_query(org=org, query=query, async_req=False, _preload_content=False)

where create_request is:

def create_request(query, start, stop, max_samples = 100):
  window = (stop - start) / max_samples
  window = int(window.total_seconds() * 1000)

  start = start.isoformat()
  stop = stop.isoformat()

  return {
    "query": query,
    "extern": {
      "type": "File",
      "package": None,
      "imports": None,
      "body": [
        {
          "type": "OptionStatement",
          "assignment": {
            "type": "VariableAssignment",
            "id": {
              "type": "Identifier",
              "name": "v"
            },
            "init": {
              "type": "ObjectExpression",
              "properties": [
                {
                  "type": "Property",
                  "key": {
                    "type": "Identifier",
                    "name": "timeRangeStart"
                  },
                  "value": {
                    "type": "DateTimeLiteral",
                    "value": start
                  }
                },
                {
                  "type": "Property",
                  "key": {
                    "type": "Identifier",
                    "name": "timeRangeStop"
                  },
                  "value": {
                    "type": "DateTimeLiteral",
                    "value": stop
                  }
                },
                {
                  "type": "Property",
                  "key": {
                    "type": "Identifier",
                    "name": "windowPeriod"
                  },
                  "value": {
                    "type": "DurationLiteral",
                    "values": [
                      {
                        "magnitude": window,
                        "unit": "ms"
                      }
                    ]
                  }
                }
              ]
            }
          }
        }
      ]
    },
    "dialect": {
      "annotations": [
        "group",
        "datatype",
        "default"
      ]
    }
  }

But i cant seem to find the json it sends to the server to get this error:

HTTP response headers: HTTPHeaderDict({'Content-Type': 'application/json; charset=utf-8', 'Date': 'Fri, 07 Oct 2022 17:54:54 GMT', 'Vary': 'Accept-Encoding', 'X-Influxdb-Build': 'OSS', 'X-Influxdb-Version': 'v2.4.0', 'X-Platform-Error-Code': 'invalid', 'Transfer-Encoding': 'chunked'})
HTTP response body: b'{"code":"invalid","message":"compilation failed: extern json parse error: premature end of input at line 1 column 750"}'
SGStino commented 2 years ago

Turns out, ...

    "imports": None,
    "package": None,

are really required, or it gives json errors.

So, the minimal implementation for this is:

from influxdb_client import Query, InfluxDBClient
client = InfluxDBClient(url="https://influx.local/", token="....", org=org)
api = client.query_api()

query = Query(**create_request(query2, start, stop))
response = api._query_api.post_query(org=org, query=query,
                                        async_req=False, _preload_content=False, _return_http_data_only=False)

api._to_tables(response, query_options=api._get_query_options())