diff --git a/CHANGELOG.md b/CHANGELOG.md index c7d38415..e9879099 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ ## 1.29.0 [unreleased] ### Breaking Changes - 1. [#433](https://github.com/influxdata/influxdb-client-python/pull/433): Rename `InvocableScripts` to `InvokableScripts` +1. [#433](https://github.com/influxdata/influxdb-client-python/pull/433): Rename `InvocableScripts` to `InvokableScripts` + +### Documentation +1. [#434](https://github.com/influxdata/influxdb-client-python/pull/434): How the client uses [logging](https://docs.python.org/3/library/logging.html) ## 1.28.0 [2022-04-19] diff --git a/README.rst b/README.rst index a2074e7f..8f30a6e9 100644 --- a/README.rst +++ b/README.rst @@ -84,6 +84,7 @@ InfluxDB 2.0 client features - `Nanosecond precision`_ - `Delete data`_ - `Handling Errors`_ + - `Logging`_ Installation ------------ @@ -1516,6 +1517,50 @@ Client automatically follows HTTP redirects. The default redirect policy is to f .. marker-asyncio-end +Logging +^^^^^^^ +.. marker-logging-start + +The client uses uses Python's `logging `__ facility for logging the library activity. The following logger categories are exposed: + +- ``influxdb_client.client.influxdb_client`` +- ``influxdb_client.client.influxdb_client_async`` +- ``influxdb_client.client.write_api`` +- ``influxdb_client.client.write_api_async`` +- ``influxdb_client.client.write.retry`` +- ``influxdb_client.client.write.dataframe_serializer`` +- ``influxdb_client.client.util.multiprocessing_helper`` +- ``influxdb_client.client.exceptions`` + +The default logging level is `warning` without configured logger output. You can use the standard logger interface to change the log level and handler: + +.. code-block:: python + + import logging + import sys + + from influxdb_client import InfluxDBClient + + with InfluxDBClient(url="http://localhost:8086", token="my-token", org="my-org") as client: + for _, logger in client.conf.loggers.items(): + logger.setLevel(logging.DEBUG) + logger.addHandler(logging.StreamHandler(sys.stdout)) + +Debugging +""""""""" + +For debug purpose you can enable verbose logging of HTTP requests and set the ``debug`` level to all client's logger categories by: + +.. code-block:: python + + client = InfluxDBClient(url="http://localhost:8086", token="my-token", debug=True) + +.. note:: + + Both HTTP request headers and body will be logged to standard output. + +.. marker-logging-end + Local tests ----------- diff --git a/docs/usage.rst b/docs/usage.rst index 162ad5e8..3d6f2ab6 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -58,15 +58,12 @@ How to use Asyncio :start-after: marker-asyncio-start :end-before: marker-asyncio-end -Debugging -^^^^^^^^^ +Logging +^^^^^^^ -For debug purpose you can enable verbose logging of http requests. -Both request header and body will be logged to standard output. - -.. code-block:: python - - _client = InfluxDBClient(url="http://localhost:8086", token="my-token", debug=True, org="my-org") +.. include:: ../README.rst + :start-after: marker-logging-start + :end-before: marker-logging-end Examples ^^^^^^^^ diff --git a/influxdb_client/_async/rest.py b/influxdb_client/_async/rest.py index 49bd54e7..0430d872 100644 --- a/influxdb_client/_async/rest.py +++ b/influxdb_client/_async/rest.py @@ -10,7 +10,6 @@ import io import json -import logging import re import ssl @@ -22,8 +21,6 @@ from influxdb_client.rest import ApiException from influxdb_client.rest import _UTF_8_encoding -logger = logging.getLogger(__name__) - async def _on_request_start(session, trace_config_ctx, params): print(f">>> Request: '{params.method} {params.url}'") @@ -229,9 +226,6 @@ async def request(self, method, url, query_params=None, headers=None, data = await r.read() r = RESTResponseAsync(r, data) - # log response body - logger.debug("response body: %s", r.data) - if not 200 <= r.status <= 299: raise ApiException(http_resp=r) diff --git a/influxdb_client/_sync/rest.py b/influxdb_client/_sync/rest.py index 68da8328..3f9aff5d 100644 --- a/influxdb_client/_sync/rest.py +++ b/influxdb_client/_sync/rest.py @@ -14,7 +14,6 @@ import io import json -import logging import re import ssl @@ -30,9 +29,6 @@ raise ImportError('OpenAPI Python client requires urllib3.') -logger = logging.getLogger(__name__) - - class RESTResponse(io.IOBase): """NOTE: This class is auto generated by OpenAPI Generator. @@ -247,9 +243,6 @@ def request(self, method, url, query_params=None, headers=None, if six.PY3: r.data = r.data.decode('utf8') - # log response body - logger.debug("response body: %s", r.data) - if not 200 <= r.status <= 299: raise ApiException(http_resp=r) diff --git a/influxdb_client/client/_base.py b/influxdb_client/client/_base.py index 4130d04e..e0218272 100644 --- a/influxdb_client/client/_base.py +++ b/influxdb_client/client/_base.py @@ -5,6 +5,7 @@ import codecs import configparser import csv +import logging import os from datetime import datetime, timedelta from typing import Iterator, List, Generator, Any, Union, Iterable, AsyncGenerator @@ -29,11 +30,22 @@ except ModuleNotFoundError: _HAS_DATACLASS = False +LOGGERS_NAMES = [ + 'influxdb_client.client.influxdb_client', + 'influxdb_client.client.influxdb_client_async', + 'influxdb_client.client.write_api', + 'influxdb_client.client.write_api_async', + 'influxdb_client.client.write.retry', + 'influxdb_client.client.write.dataframe_serializer', + 'influxdb_client.client.util.multiprocessing_helper', + 'influxdb_client.client.exceptions' +] + # noinspection PyMethodMayBeStatic class _BaseClient(object): def __init__(self, url, token, debug=None, timeout=10_000, enable_gzip=False, org: str = None, - default_tags: dict = None, **kwargs) -> None: + default_tags: dict = None, http_client_logger: str = None, **kwargs) -> None: self.url = url self.token = token self.org = org @@ -46,13 +58,17 @@ def __init__(self, url, token, debug=None, timeout=10_000, enable_gzip=False, or else: self.conf.host = self.url self.conf.enable_gzip = enable_gzip - self.conf.debug = debug self.conf.verify_ssl = kwargs.get('verify_ssl', True) self.conf.ssl_ca_cert = kwargs.get('ssl_ca_cert', None) self.conf.proxy = kwargs.get('proxy', None) self.conf.proxy_headers = kwargs.get('proxy_headers', None) self.conf.connection_pool_maxsize = kwargs.get('connection_pool_maxsize', self.conf.connection_pool_maxsize) self.conf.timeout = timeout + # logging + self.conf.loggers["http_client_logger"] = logging.getLogger(http_client_logger) + for client_logger in LOGGERS_NAMES: + self.conf.loggers[client_logger] = logging.getLogger(client_logger) + self.conf.debug = debug auth_token = self.token self.auth_header_name = "Authorization" diff --git a/influxdb_client/client/exceptions.py b/influxdb_client/client/exceptions.py index 5278d8d8..48681add 100644 --- a/influxdb_client/client/exceptions.py +++ b/influxdb_client/client/exceptions.py @@ -4,7 +4,7 @@ from urllib3 import HTTPResponse -logger = logging.getLogger(__name__) +logger = logging.getLogger('influxdb_client.client.exceptions') class InfluxDBError(Exception): diff --git a/influxdb_client/client/influxdb_client.py b/influxdb_client/client/influxdb_client.py index 82d5eefd..e3cce1b5 100644 --- a/influxdb_client/client/influxdb_client.py +++ b/influxdb_client/client/influxdb_client.py @@ -53,7 +53,7 @@ def __init__(self, url, token, debug=None, timeout=10_000, enable_gzip=False, or :key list[str] profilers: list of enabled Flux profilers """ super().__init__(url=url, token=token, debug=debug, timeout=timeout, enable_gzip=enable_gzip, org=org, - default_tags=default_tags, **kwargs) + default_tags=default_tags, http_client_logger="urllib3", **kwargs) from .._sync.api_client import ApiClient self.api_client = ApiClient(configuration=self.conf, header_name=self.auth_header_name, diff --git a/influxdb_client/client/influxdb_client_async.py b/influxdb_client/client/influxdb_client_async.py index fd35ade0..07c53875 100644 --- a/influxdb_client/client/influxdb_client_async.py +++ b/influxdb_client/client/influxdb_client_async.py @@ -10,7 +10,7 @@ from influxdb_client.client.write_api import PointSettings from influxdb_client.client.write_api_async import WriteApiAsync -logger = logging.getLogger('influxdb_client.client.influxdb_client') +logger = logging.getLogger('influxdb_client.client.influxdb_client_async') class InfluxDBClientAsync(_BaseClient): @@ -46,7 +46,8 @@ def __init__(self, url, token, org: str = None, debug=None, timeout=10_000, enab ``aiohttp-retry``. :class:`~aiohttp.ClientSession` by default. :key list[str] profilers: list of enabled Flux profilers """ - super().__init__(url=url, token=token, org=org, debug=debug, timeout=timeout, enable_gzip=enable_gzip, **kwargs) + super().__init__(url=url, token=token, org=org, debug=debug, timeout=timeout, enable_gzip=enable_gzip, + http_client_logger="aiohttp.client", **kwargs) # compatibility with Python 3.6 if sys.version_info[:2] >= (3, 7): diff --git a/influxdb_client/client/util/multiprocessing_helper.py b/influxdb_client/client/util/multiprocessing_helper.py index 025a9368..41530a23 100644 --- a/influxdb_client/client/util/multiprocessing_helper.py +++ b/influxdb_client/client/util/multiprocessing_helper.py @@ -10,7 +10,7 @@ from influxdb_client import InfluxDBClient, WriteOptions from influxdb_client.client.exceptions import InfluxDBError -logger = logging.getLogger(__name__) +logger = logging.getLogger('influxdb_client.client.util.multiprocessing_helper') def _success_callback(conf: (str, str, str), data: str): diff --git a/influxdb_client/client/write/dataframe_serializer.py b/influxdb_client/client/write/dataframe_serializer.py index 95ad09b0..3e55104d 100644 --- a/influxdb_client/client/write/dataframe_serializer.py +++ b/influxdb_client/client/write/dataframe_serializer.py @@ -11,7 +11,7 @@ from influxdb_client import WritePrecision from influxdb_client.client.write.point import _ESCAPE_KEY, _ESCAPE_STRING, _ESCAPE_MEASUREMENT, DEFAULT_WRITE_PRECISION -logger = logging.getLogger(__name__) +logger = logging.getLogger('influxdb_client.client.write.dataframe_serializer') def _itertuples(data_frame): diff --git a/influxdb_client/client/write/retry.py b/influxdb_client/client/write/retry.py index 50fdaa46..2c4b359e 100644 --- a/influxdb_client/client/write/retry.py +++ b/influxdb_client/client/write/retry.py @@ -11,7 +11,7 @@ from influxdb_client.client.exceptions import InfluxDBError -logger = logging.getLogger(__name__) +logger = logging.getLogger('influxdb_client.client.write.retry') class WritesRetry(Retry): diff --git a/influxdb_client/client/write_api.py b/influxdb_client/client/write_api.py index c1b13391..5c78bf23 100644 --- a/influxdb_client/client/write_api.py +++ b/influxdb_client/client/write_api.py @@ -23,7 +23,7 @@ from influxdb_client.client.write.retry import WritesRetry from influxdb_client.rest import _UTF_8_encoding -logger = logging.getLogger(__name__) +logger = logging.getLogger('influxdb_client.client.write_api') if _HAS_DATACLASS: diff --git a/influxdb_client/client/write_api_async.py b/influxdb_client/client/write_api_async.py index 50381016..b312c77b 100644 --- a/influxdb_client/client/write_api_async.py +++ b/influxdb_client/client/write_api_async.py @@ -9,7 +9,7 @@ from influxdb_client.client.write.point import DEFAULT_WRITE_PRECISION from influxdb_client.client.write_api import PointSettings -logger = logging.getLogger('influxdb_client.client.influxdb_client') +logger = logging.getLogger('influxdb_client.client.write_api_async') if _HAS_DATACLASS: from dataclasses import dataclass diff --git a/influxdb_client/configuration.py b/influxdb_client/configuration.py index fcb3c667..d7e31e38 100644 --- a/influxdb_client/configuration.py +++ b/influxdb_client/configuration.py @@ -70,9 +70,7 @@ def __init__(self): self.password = "" # Logging Settings - self.logger = {} - self.logger["package_logger"] = logging.getLogger("influxdb_client") - self.logger["urllib3_logger"] = logging.getLogger("urllib3") + self.loggers = {} # Log format self.logger_format = '%(asctime)s %(levelname)s %(message)s' # Log stream handler @@ -145,7 +143,7 @@ def logger_file(self, value): # then add file handler and remove stream handler. self.logger_file_handler = logging.FileHandler(self.__logger_file) self.logger_file_handler.setFormatter(self.logger_formatter) - for _, logger in six.iteritems(self.logger): + for _, logger in six.iteritems(self.loggers): logger.addHandler(self.logger_file_handler) @property @@ -167,14 +165,14 @@ def debug(self, value): self.__debug = value if self.__debug: # if debug status is True, turn on debug logging - for _, logger in six.iteritems(self.logger): + for _, logger in six.iteritems(self.loggers): logger.setLevel(logging.DEBUG) # turn on httplib debug httplib.HTTPConnection.debuglevel = 1 else: # if debug status is False, turn off debug logging, # setting log level to default `logging.WARNING` - for _, logger in six.iteritems(self.logger): + for _, logger in six.iteritems(self.loggers): logger.setLevel(logging.WARNING) # turn off httplib debug httplib.HTTPConnection.debuglevel = 0