-
Notifications
You must be signed in to change notification settings - Fork 14.3k
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
feat: db connection analytics #13346
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,6 @@ | |
from flask_appbuilder.security.sqla.models import User | ||
from marshmallow import ValidationError | ||
|
||
from superset import app | ||
from superset.commands.base import BaseCommand | ||
from superset.dao.exceptions import DAOCreateFailedError | ||
from superset.databases.commands.exceptions import ( | ||
|
@@ -33,11 +32,9 @@ | |
) | ||
from superset.databases.commands.test_connection import TestConnectionDatabaseCommand | ||
from superset.databases.dao import DatabaseDAO | ||
from superset.extensions import db, security_manager | ||
from superset.extensions import db, event_logger, security_manager | ||
|
||
logger = logging.getLogger(__name__) | ||
config = app.config | ||
stats_logger = config["STATS_LOGGER"] | ||
|
||
|
||
class CreateDatabaseCommand(BaseCommand): | ||
|
@@ -54,10 +51,12 @@ def run(self) -> Model: | |
try: | ||
TestConnectionDatabaseCommand(self._actor, self._properties).run() | ||
except Exception: | ||
db.session.rollback() | ||
stats_logger.incr( | ||
f"db_connection_failed.{database.db_engine_spec.__name__}" | ||
) | ||
with event_logger.log_context( | ||
action="db_connection_failed", | ||
engine=database.db_engine_spec.__name__, | ||
): | ||
db.session.rollback() | ||
|
||
raise DatabaseConnectionFailedError() | ||
|
||
# adding a new database we always want to force refresh schema list | ||
|
@@ -69,8 +68,9 @@ def run(self) -> Model: | |
security_manager.add_permission_view_menu("database_access", database.perm) | ||
db.session.commit() | ||
except DAOCreateFailedError as ex: | ||
logger.exception(ex.exception) | ||
raise DatabaseCreateFailedError() | ||
with event_logger.log_context(action=f"db_creation_failed.{ex.exception}"): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @hughhhh I saw this earlier today, that we're currently logging the entire exception. Can we change this on line 71 and 72 to log just the class? I originally thought since we were already logging it, it would be fine to pass to the event logger, but I think we should actually clean this up as well. |
||
logger.exception(ex.exception) | ||
raise DatabaseCreateFailedError() | ||
return database | ||
|
||
def validate(self) -> None: | ||
|
@@ -90,4 +90,6 @@ def validate(self) -> None: | |
if exceptions: | ||
exception = DatabaseInvalidError() | ||
exception.add_list(exceptions) | ||
raise exception | ||
|
||
with event_logger.log_context(action="db_connection_failed"): | ||
raise exception |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to just use
log
in places like this. The main difference betweenlog
andlog_context
is that the former, in addition to being a context manager, logs the duration automatically, together with some dashboard/chart metadata that is irrelevant here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true... it also logs the user_id and referrer, so maybe it's still useful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to either 1) refactor
log
to do some of the magic inlog_context
maybe add a bool flagenrich_with_request_context=False
, or 2) can we just call the context manager with thewith
block? Would that just work? or 3) refactorlog_context
to NOT be be context manager and create a new one saylog_context_manager
(or better name) that's used only when we want duration / with blockThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One problem is that adding the flag
enrich_with_request_context
would be a breaking change (our event logger, for example, would have to be updated).I think the best way here is:
AbstractEventLogger
calledlog_with_context
, that does all the job thatlog_context
does but is a function, not a context manager. The method callslog
at the end, with all the extracted context.AbstractEventLogger.log_context
to uselog_with_context
for the enrichment, removing the shared code between them.log_with_context
. Since it delegates the actual logging tolog
it will work with all existing event loggers, and is not a breaking change..Eventually I think we should have the event logger itself be a context manager by implementing
__enter__
and__exit__
methods, so we could call:Since we can do this by adding methods to
AbstractEventLogger
it would also not be a breaking change.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick clarification that
enrich_with_request_context
would be false by default to protect backwards compatibity. But maybe function composition is better than a parameter here, I'm ok with with either pattern.There's a need to really clarify/improve the method in
AbstractEventLogger
with good/clear names here between functions we can call, content manager(s) and decorator(s)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we're merging this branch into @hughhhh's feature branch rather than master, @betodealmeida said that he could do the log_context refactor in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm working on the refactor right now.
@mistercrunch you're right, I forgot that
log
takes a**kwargs
that would swallow the new argument.