Skip to content
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

Convenient handling of DBMS notifications #1059

Merged
merged 7 commits into from May 15, 2024

Conversation

robsdedude
Copy link
Member

@robsdedude robsdedude commented May 8, 2024

This PR introduces support for a more convenient way of consuming notifications received from the DBMS server.

This feature is still in PREVIEW.
It might be changed without following the deprecation policy.

Logging

A new sub-logger neo4j.notifications is introduced.
Every notification received will be logged through this logger.
The log-level is determined by the notification's severity.

If logging is not configured explicitly, warnings are logged to stderr.
This means that, by default, warnings like deprecations received from the DBMS will appear on stderr.

Warnings

A new driver-level configuration warn_notification_severity is introduced.
It can be used to configure from which notification severity level upward the driver should emit a warning (i.e., call warnings.warn).

By default (None), it will be set to OFF (never emitting warnings on notifications), unless Python runs in development mode or the environment variable PYTHONNEO4JDEBUG is set, in which case the driver will emit a
warning on every notification.

Usage

This functionality if mainly meant for developing and debugging.
Therefore, no emphasis is put on efficiency.
However, it's impact is capt to a minimum when disabled.
It's assumed that in productions environments this feature is either disabled explicitly

neo4j.GraphDatabase.driver(
    ...,
    warn_notification_severity=neo4j.NotificationMinimumSeverity.OFF,
    ...,
)

or default behavior (see above) is used by not running Python in development mode.

Example

# example.py
import neo4j


URL = "neo4j://localhost:7687"
AUTH = ("neo4j", "pass")
DB = "neo4j"


with neo4j.GraphDatabase.driver(
    URL,
    auth=AUTH,
    warn_notification_severity=neo4j.NotificationMinimumSeverity.INFORMATION,
) as driver:
    driver.execute_query(
        "MERGE (:Test {name: 'foo'})",
        database_=DB,
    )
    driver.execute_query(
        "MATCH (n:Test {name: 'baz'}), (m:Test1 {name: 'bar'}) "
        "RETURN n, m",
        database_=DB,
        routing_="r",
    )

On an empty database, this leads to the following output:

$ python example.py
/path/to/example.py:10: PreviewWarning: notification warnings are a preview feature. It might be changed without following the deprecation policy. See also https://github.com/neo4j/neo4j-python-driver/wiki/preview-features.
  with neo4j.GraphDatabase.driver(
/path/to/example.py:19: Neo4jWarning: {severity: INFORMATION} {code: Neo.ClientNotification.Statement.CartesianProduct} {category: PERFORMANCE} {title: This query builds a cartesian product between disconnected patterns.} {description: If a part of a query contains multiple disconnected patterns, this will build a cartesian product between all those parts. This may produce a large amount of data and slow down query processing. While occasionally intended, it may often be possible to reformulate the query that avoids the use of this cross product, perhaps by adding a relationship between the different parts or by using OPTIONAL MATCH (identifier is: (m))} {position: line: 1, column: 1, offset: 0} for query:
MATCH (n:Test {name: 'baz'}), (m:Test1 {name: 'bar'}) RETURN n, m
^
  driver.execute_query(
Received notification from DBMS server: {severity: WARNING} {code: Neo.ClientNotification.Statement.UnknownLabelWarning} {category: UNRECOGNIZED} {title: The provided label is not in the database.} {description: One of the labels in your query is not available in the database, make sure you didn't misspell it or that the label is available when you run this statement in your application (the missing label name is: Test1)} {position: line: 1, column: 34, offset: 33} for query: "MATCH (n:Test {name: 'baz'}), (m:Test1 {name: 'bar'}) RETURN n, m"
/path/to/example.py:19: Neo4jWarning: {severity: WARNING} {code: Neo.ClientNotification.Statement.UnknownLabelWarning} {category: UNRECOGNIZED} {title: The provided label is not in the database.} {description: One of the labels in your query is not available in the database, make sure you didn't misspell it or that the label is available when you run this statement in your application (the missing label name is: Test1)} {position: line: 1, column: 34, offset: 33} for query:
MATCH (n:Test {name: 'baz'}), (m:Test1 {name: 'bar'}) RETURN n, m
                                 ^
  driver.execute_query(

src/neo4j/_async/work/result.py Outdated Show resolved Hide resolved
src/neo4j/_async/work/result.py Show resolved Hide resolved
@robsdedude robsdedude marked this pull request as ready for review May 13, 2024 10:35
Copy link
Contributor

@bigmontz bigmontz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📓

@robsdedude robsdedude merged commit 9b47011 into neo4j:5.0 May 15, 2024
20 checks passed
@robsdedude robsdedude deleted the native-warnings branch May 15, 2024 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants