question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using multiple DSNs, choosing based on the logger

See original GitHub issue

I’m looking to upgrade from raven-python[flask] to sentry-sdk[flask]. We previous had two DSNs for our backend: one for errors and one to log performance issues (e.g. slow requests / high DB query count).

We were previously able to configure this via:

from raven.contrib.flask import Sentry
from raven.handlers.logging import SentryHandler

performance_logger = logging.getLogger("benchling.performance")
performance_logger.setLevel(logging.WARNING)
sentry = Sentry(logging=True, level=logging.WARNING)

def init_sentry(app):
    sentry.init_app(app, dsn=app.config["SENTRY_DSN_SERVER"])
    performance_handler = SentryHandler(dsn=app.config["SENTRY_DSN_BACKEND_PERFORMANCE"])
    performance_logger.addHandler(performance_handler)

With the new architecture, this seems hard to do since the DSN is configured once via sentry_sdk.init where the LoggingIntegration simply listens to the root logger. I was able to hack around this by monkey-patching the logging_integration’s handler as follows:

import logging

import sentry_sdk
from sentry_sdk.client import Client
from sentry_sdk.hub import Hub
from sentry_sdk.integrations.celery import CeleryIntegration
from sentry_sdk.integrations.flask import FlaskIntegration
from sentry_sdk.integrations.logging import LoggingIntegration


def register_clients_for_loggers(logger_name_to_client):
    """Monkeypatch LoggingIntegration's EventHandler to override the Client based on the record's logger"""
    hub = Hub.current
    logging_integration = hub.get_integration(LoggingIntegration)
    if not logging_integration:
        return
    handler = logging_integration._handler
    old_emit = handler.emit

    def new_emit(record):
        new_client = logger_name_to_client.get(record.name)
        previous_client = hub.client
        should_bind = new_client is not None
        try:
            if should_bind:
                hub.bind_client(new_client)
            old_emit(record)
        finally:
            if should_bind:
                hub.bind_client(previous_client)

    handler.emit = new_emit

def init_sentry(app):
    sentry_sdk.init(
        dsn=app.config["SENTRY_DSN_SERVER"],
        release=app.config["SENTRY_RELEASE"],
        environment=app.config["SENTRY_ENVIRONMENT"],
        integrations=[
            LoggingIntegration(
                level=logging.WARNING,  # Capture info and above as breadcrumbs
                event_level=logging.WARNING,  # Send warnings and errors as events
            ),
            CeleryIntegration(),
            FlaskIntegration(),
        ],
    )

    performance_logger = logging.getLogger("benchling.performance")
    performance_logger.setLevel(logging.WARNING)

    perf_client = Client(
        dsn=app.config["SENTRY_DSN_BACKEND_PERFORMANCE"],
        release=app.config["SENTRY_RELEASE"],
        environment=app.config["SENTRY_ENVIRONMENT"],
    )
    register_clients_for_loggers({performance_logger.name: perf_client})

Two questions:

  1. Does this approach seem reasonable, or is there a better way to handle this?
  2. If there isn’t a better way, would it be possible to have sentry_sdk.init let you specify this mapping?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:22 (10 by maintainers)

github_iconTop GitHub Comments

3reactions
kiddtencommented, Oct 27, 2020

What is the easiest way to use multiple dsn nowadays? I do not need to configure somehow, I just need 2 dns supported simultaneously.

2reactions
untitakercommented, Apr 17, 2019

btw sorry @saifelse for the lack of response. Passing a function as a transport is only used for testing purposes. I think your approach is fine. Something we could improve is to put a TransportMultiplexer class into the SDK which forwards the event to all transports, and then each transport decides by itself if it wants to send.

Read more comments on GitHub >

github_iconTop Results From Across the Web

DNS and Domain Logging: A Bird's Eye View - DomainTools
Discover everything you need to know about log collection. In the first blog of this five-part series, we'll give an industry overview on ......
Read more >
Logback to log different messages to two files - Stack Overflow
You can have as many loggers as you wish. But, it's better you have one for each package that you need to log...
Read more >
DNS Logging and Diagnostics - Microsoft Learn
Enhanced DNS logging and diagnostics in Windows Server 2012 R2 and later includes DNS Audit events and DNS Analytic events. DNS audit logs...
Read more >
Logger in Java - Java Logging Example - DigitalOcean
We can add multiple handlers to a java logger and whenever we log any message, every handler will process it accordingly. There are...
Read more >
Choosing a routing policy - Amazon Route 53
You can use failover routing to create records in a private hosted zone. Geolocation routing policy – Use when you want to route...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found