|
10 | 10 | import random
|
11 | 11 |
|
12 | 12 | import json
|
| 13 | +import struct |
| 14 | +import datetime |
13 | 15 | import socket
|
| 16 | +import msgpack |
14 | 17 | import requests
|
15 | 18 | import requests.exceptions
|
16 | 19 | from six.moves import xrange
|
|
21 | 24 | from .exceptions import InfluxDBClientError
|
22 | 25 | from .exceptions import InfluxDBServerError
|
23 | 26 |
|
| 27 | +def _msgpack_ext_hook(code, data): |
| 28 | + if code == 5: |
| 29 | + (epoch_s, epoch_ns) = struct.unpack(">QI", data) |
| 30 | + time = datetime.datetime.utcfromtimestamp(epoch_s) |
| 31 | + time += datetime.timedelta(microseconds=epoch_ns/1000) |
| 32 | + return time.isoformat() + 'Z' |
| 33 | + return msgpack.ExtType(code, data) |
24 | 34 |
|
25 | 35 | class InfluxDBClient(object):
|
26 | 36 | """InfluxDBClient primary client object to connect InfluxDB.
|
@@ -128,7 +138,7 @@ def __init__(self,
|
128 | 138 |
|
129 | 139 | self._headers = {
|
130 | 140 | 'Content-Type': 'application/json',
|
131 |
| - 'Accept': 'text/plain' |
| 141 | + 'Accept': 'application/x-msgpack' |
132 | 142 | }
|
133 | 143 |
|
134 | 144 | @property
|
@@ -277,13 +287,21 @@ def request(self, url, method='GET', params=None, data=None,
|
277 | 287 | time.sleep((2 ** _try) * random.random() / 100.0)
|
278 | 288 | if not retry:
|
279 | 289 | raise
|
| 290 | + |
| 291 | + def reformat_error(response): |
| 292 | + err = self._parse_msgpack(response) |
| 293 | + if err: |
| 294 | + return json.dumps(err, separators=(',',':')) |
| 295 | + else: |
| 296 | + return response.content |
| 297 | + |
280 | 298 | # if there's not an error, there must have been a successful response
|
281 | 299 | if 500 <= response.status_code < 600:
|
282 |
| - raise InfluxDBServerError(response.content) |
| 300 | + raise InfluxDBServerError(reformat_error(response)) |
283 | 301 | elif response.status_code == expected_response_code:
|
284 | 302 | return response
|
285 | 303 | else:
|
286 |
| - raise InfluxDBClientError(response.content, response.status_code) |
| 304 | + raise InfluxDBClientError(reformat_error(response), response.status_code) |
287 | 305 |
|
288 | 306 | def write(self, data, params=None, expected_response_code=204,
|
289 | 307 | protocol='json'):
|
@@ -342,6 +360,18 @@ def _read_chunked_response(response, raise_errors=True):
|
342 | 360 | _key, []).extend(result[_key])
|
343 | 361 | return ResultSet(result_set, raise_errors=raise_errors)
|
344 | 362 |
|
| 363 | + @staticmethod |
| 364 | + def _parse_msgpack(response): |
| 365 | + """ Returns the decoded response if it is encoded as msgpack, |
| 366 | + otherwise return None |
| 367 | + """ |
| 368 | + headers = response.headers |
| 369 | + if headers and headers["Content-Type"] == "application/x-msgpack": |
| 370 | + return msgpack.unpackb( |
| 371 | + response.content, |
| 372 | + ext_hook=_msgpack_ext_hook, |
| 373 | + raw=False) |
| 374 | + |
345 | 375 | def query(self,
|
346 | 376 | query,
|
347 | 377 | params=None,
|
@@ -434,10 +464,11 @@ def query(self,
|
434 | 464 | expected_response_code=expected_response_code
|
435 | 465 | )
|
436 | 466 |
|
437 |
| - if chunked: |
438 |
| - return self._read_chunked_response(response) |
439 |
| - |
440 |
| - data = response.json() |
| 467 | + data = self._parse_msgpack(response) |
| 468 | + if not data: |
| 469 | + if chunked: |
| 470 | + return self._read_chunked_response(response) |
| 471 | + data = response.json() |
441 | 472 |
|
442 | 473 | results = [
|
443 | 474 | ResultSet(result, raise_errors=raise_errors)
|
|
0 commit comments