Skip to content

Refactor Logging Hierarchy in neo4j-python-driver #997

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ See also https://github.com/neo4j/neo4j-python-driver/wiki for a full changelog.

## NEXT RELEASE
- No breaking or major changes.
- Implemented a hierarchical logger structure to improve log source
identification and traceability.
Introduced child loggers:
- `neo4j.io`: For socket and bolt protocol related logging.
- `neo4j.pool`: For logs pertaining to connection pooling and routing.
- `neo4j.auth_management`: For logging inside the provided AuthManager
implementations.


## Version 5.15
Expand Down
27 changes: 24 additions & 3 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2080,9 +2080,30 @@ following code:
Logging
*******

The driver offers logging for debugging purposes. It is not recommended to
enable logging for anything other than debugging. For instance, if the driver is
not able to connect to the database server or if undesired behavior is observed.
The driver offers logging for debugging purposes.
It is not recommended to enable logging for anything other than debugging.
For instance, if the driver is not able to connect to the database server or if
undesired behavior is observed.

This includes messages logged on ``WARNING`` level or higher.
They are logged to help understand what is going on *inside* the driver.
All relevant information is passed through return values, raised exceptions,
warnings, etc.
The logs are not the right place to look for actionable information.

The driver supports hierarchical logging.
This means you can selectively configure all of the driver's logging or only
parts of it.
Currently available:

* ``neo4j``: The root logger for the driver.
High-level code (e.g., Session, Transaction, Driver, etc.) logs here.

* ``neo4j.io``: Logs network activity and bolt protocol messages, handshakes,
etc.
* ``neo4j.pool``: Logs connection pool activity (including routing).
* ``neo4j.auth_management``: Logger for provided :class:`.AuthManager`
implementations.

There are different ways of enabling logging as listed below.

Expand Down
8 changes: 6 additions & 2 deletions src/neo4j/_async/auth_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from ..exceptions import Neo4jError


log = getLogger("neo4j")
log = getLogger("neo4j.auth_management")


class AsyncStaticAuthManager(AsyncAuthManager):
Expand Down Expand Up @@ -67,7 +67,11 @@ def __init__(
self._lock = AsyncLock()

async def _refresh_auth(self):
self._current_auth = await self._provider()
try:
self._current_auth = await self._provider()
except BaseException as e:
log.error("[ ] _: <AUTH MANAGER> provider failed: %r", e)
raise
if self._current_auth is None:
raise TypeError(
"Auth provider function passed to expiration_based "
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_async/io/_bolt.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@


# Set up logger
log = getLogger("neo4j")
log = getLogger("neo4j.io")


class ServerStateManagerBase(abc.ABC):
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_async/io/_bolt3.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
)


log = getLogger("neo4j")
log = getLogger("neo4j.io")


class BoltStates(Enum):
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_async/io/_bolt4.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
)


log = getLogger("neo4j")
log = getLogger("neo4j.io")


class AsyncBolt4x0(AsyncBolt):
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_async/io/_bolt5.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
)


log = getLogger("neo4j")
log = getLogger("neo4j.io")


class AsyncBolt5x0(AsyncBolt):
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_async/io/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
)


log = logging.getLogger("neo4j")
log = logging.getLogger("neo4j.io")


class AsyncInbox:
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_async/io/_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@


# Set up logger
log = getLogger("neo4j")
log = getLogger("neo4j.pool")


@dataclass
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_async/work/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
_P = te.ParamSpec("_P")


log = getLogger("neo4j")
log = getLogger("neo4j.pool")


class AsyncSession(AsyncWorkspace):
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_async_compat/network/_bolt_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
from ..._sync.io import Bolt


log = logging.getLogger("neo4j")
log = logging.getLogger("neo4j.io")


def _sanitize_deadline(deadline):
Expand Down
4 changes: 2 additions & 2 deletions src/neo4j/_async_compat/network/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from ... import addressing


log = logging.getLogger("neo4j")
log = logging.getLogger("neo4j.io")


def _resolved_addresses_from_info(info, host_name):
Expand Down Expand Up @@ -142,7 +142,7 @@ def resolve_address(address, family=0, resolver=None):
yield address
return

addressing.log.debug("[#0000] _: <RESOLVE> in: %s", address)
log.debug("[#0000] _: <RESOLVE> in: %s", address)
if resolver:
for address in map(addressing.Address, resolver(address)):
log.debug("[#0000] _: <RESOLVE> custom resolver out: %s",
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from .addressing import Address


log = getLogger("neo4j")
log = getLogger("neo4j.pool")


class OrderedSet(MutableSet):
Expand Down
8 changes: 6 additions & 2 deletions src/neo4j/_sync/auth_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from ..exceptions import Neo4jError


log = getLogger("neo4j")
log = getLogger("neo4j.auth_management")


class StaticAuthManager(AuthManager):
Expand Down Expand Up @@ -67,7 +67,11 @@ def __init__(
self._lock = Lock()

def _refresh_auth(self):
self._current_auth = self._provider()
try:
self._current_auth = self._provider()
except BaseException as e:
log.error("[ ] _: <AUTH MANAGER> provider failed: %r", e)
raise
if self._current_auth is None:
raise TypeError(
"Auth provider function passed to expiration_based "
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_sync/io/_bolt.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@


# Set up logger
log = getLogger("neo4j")
log = getLogger("neo4j.io")


class ServerStateManagerBase(abc.ABC):
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_sync/io/_bolt3.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
)


log = getLogger("neo4j")
log = getLogger("neo4j.io")


class BoltStates(Enum):
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_sync/io/_bolt4.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
)


log = getLogger("neo4j")
log = getLogger("neo4j.io")


class Bolt4x0(Bolt):
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_sync/io/_bolt5.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
)


log = getLogger("neo4j")
log = getLogger("neo4j.io")


class Bolt5x0(Bolt):
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_sync/io/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
)


log = logging.getLogger("neo4j")
log = logging.getLogger("neo4j.io")


class Inbox:
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_sync/io/_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@


# Set up logger
log = getLogger("neo4j")
log = getLogger("neo4j.pool")


@dataclass
Expand Down
2 changes: 1 addition & 1 deletion src/neo4j/_sync/work/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
_P = te.ParamSpec("_P")


log = getLogger("neo4j")
log = getLogger("neo4j.pool")


class Session(Workspace):
Expand Down
4 changes: 0 additions & 4 deletions src/neo4j/addressing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

from __future__ import annotations

import logging
import typing as t
from socket import (
AddressFamily,
Expand All @@ -30,9 +29,6 @@
import typing_extensions as te


log = logging.getLogger("neo4j")


_T = t.TypeVar("_T")


Expand Down