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

feat: add statsd metrics for notifications #20158

Merged
merged 5 commits into from
May 26, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 2 additions & 0 deletions superset/reports/notifications/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from superset.reports.notifications.base import BaseNotification
from superset.reports.notifications.exceptions import NotificationError
from superset.utils.core import send_email_smtp
from superset.utils.decorators import statsd_gauge
from superset.utils.urls import modify_url_query

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -149,6 +150,7 @@ def _get_subject(self) -> str:
def _get_to(self) -> str:
return json.loads(self._recipient.recipient_config_json)["target"]

@statsd_gauge("email.send")
def send(self) -> None:
subject = self._get_subject()
content = self._get_content()
Expand Down
2 changes: 2 additions & 0 deletions superset/reports/notifications/slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from superset.models.reports import ReportRecipientType
from superset.reports.notifications.base import BaseNotification
from superset.reports.notifications.exceptions import NotificationError
from superset.utils.decorators import statsd_gauge
from superset.utils.urls import modify_url_query

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -147,6 +148,7 @@ def _get_inline_files(self) -> Sequence[Union[str, IOBase, bytes]]:
return []

@backoff.on_exception(backoff.expo, SlackApiError, factor=10, base=2, max_tries=5)
@statsd_gauge("slack.send")
def send(self) -> None:
files = self._get_inline_files()
title = self._content.name
Expand Down
23 changes: 22 additions & 1 deletion superset/utils/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import time
from contextlib import contextmanager
from functools import wraps
from typing import Any, Callable, Dict, Iterator, TYPE_CHECKING, Union
from typing import Any, Callable, Dict, Iterator, Optional, TYPE_CHECKING, Union

from flask import current_app, Response

Expand All @@ -32,6 +32,27 @@
from superset.stats_logger import BaseStatsLogger


def statsd_gauge(metric_prefix: Optional[str] = None) -> Callable[..., Any]:
def decorate(f: Callable[..., Any]) -> Callable[..., Any]:
"""
Handle sending statsd gauge metric from any method or function
"""

def wrapped(*args: Any, **kwargs: Any) -> Any:
metric_prefix_ = metric_prefix or f.__name__
try:
result = f(*args, **kwargs)
current_app.config["STATS_LOGGER"].gauge(f"{metric_prefix_}.ok", 1)
Copy link
Member

Choose a reason for hiding this comment

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

Does this allow for the end user to set a custom prefix?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, when creating a custom statsd logger class

return result
except Exception as ex:
current_app.config["STATS_LOGGER"].gauge(f"{metric_prefix_}.error", 1)
raise ex

return wrapped

return decorate


@contextmanager
def stats_timing(stats_key: str, stats_logger: BaseStatsLogger) -> Iterator[float]:
"""Provide a transactional scope around a series of operations."""
Expand Down