Skip to content

Commit

Permalink
Add non blocking event reporting feature (#170)
Browse files Browse the repository at this point in the history
* Add non blocking event reporting feature

* chore: minor text update

* chore: update changelog

---------

Co-authored-by: Pangratios Cosma <[email protected]>
  • Loading branch information
Kelvin4664 and subzero10 authored Jun 1, 2024
1 parent c5634eb commit 9c788e2
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ CHANGELOG](http://keepachangelog.com/) for how to update this file. This project
adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
- Feat: honeybadger.event() for sending events to Honeybadger Insights

## [0.19.1] - 2024-04-07

Expand Down
21 changes: 14 additions & 7 deletions honeybadger/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@

logger = logging.getLogger(__name__)


def send_notice(config, payload):
notice_id = payload.get("error", {}).get("token", None)
request_object = request.Request(url="{}/v1/notices/".format(config.endpoint),
data=b(json.dumps(payload, cls=StringReprJSONEncoder)))
def _make_http_request(path, config, payload):

if not config.api_key:
logger.error("Honeybadger API key missing from configuration: cannot report errors.")
return


request_object = request.Request(url=config.endpoint + path,
data=b(json.dumps(payload, cls=StringReprJSONEncoder)))
request_object.add_header('X-Api-Key', config.api_key)
request_object.add_header('Content-Type', 'application/json')
request_object.add_header('Accept', 'application/json')
Expand All @@ -32,9 +30,18 @@ def send_request():

if config.force_sync:
send_request()

else:
t = threading.Thread(target=send_request)
t.start()


def send_notice(config, payload):
notice_id = payload.get("error", {}).get("token", None)
path = '/v1/notices/'
_make_http_request(path, config, payload)
return notice_id


def send_event(config, payload):
path = '/v1/events/'
return _make_http_request(path, config, payload)
36 changes: 36 additions & 0 deletions honeybadger/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import sys
import logging
import copy
import time

from honeybadger.plugins import default_plugin_manager
import honeybadger.connection as connection
Expand All @@ -25,6 +26,12 @@ def _send_notice(self, exception, exc_traceback=None, context=None, fingerprint=
return fake_connection.send_notice(self.config, payload)
else:
return connection.send_notice(self.config, payload)

def _send_event(self, payload):
if self.config.is_dev() and not self.config.force_report_data:
return fake_connection.send_event(self.config, payload)
else:
return connection.send_event(self.config, payload)

def _get_context(self):
return getattr(self.thread_local, 'context', {})
Expand Down Expand Up @@ -55,6 +62,35 @@ def notify(self, exception=None, error_class=None, error_message=None, context={
merged_context.update(context)

return self._send_notice(exception, context=merged_context, fingerprint=fingerprint)


def event(self, event_type=None, data=None, **kwargs):
"""
Send an event to Honeybadger
Events logged with this method will appear in Honeybadger Insights.
"""
# If the first argument is a string, treat it as event_type
if isinstance(event_type, str):
payload = data.copy() if data else {}
payload['event_type'] = event_type
# If the first argument is a dictionary, merge it with kwargs
elif isinstance(event_type, dict):
payload = event_type.copy()
payload.update(kwargs)
# Raise an error if event_type is not provided correctly
else:
raise ValueError("The first argument must be either a string or a dictionary")

# Ensure 'event_type' is in payload
if 'event_type' not in payload:
raise ValueError("An event_type must be provided")

# Add a timestamp to the payload if not provided
if 'ts' not in payload:
payload['ts'] = time.time()

return self._send_event(payload)


def configure(self, **kwargs):
self.config.set_config_from_dict(kwargs)
Expand Down
5 changes: 5 additions & 0 deletions honeybadger/fake_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ def send_notice(config, payload):
logger.info('Development mode is enabled; this error will be reported if it occurs after you deploy your app.')
logger.debug('The config used is {} with payload {}'.format(config, payload))
return notice_id

def send_event(config, payload):
logger.info('Development mode is enabled; this event will be reported if it occurs after you deploy your app.')
logger.debug('The config used is {} with payload {}'.format(config, payload))
return True

0 comments on commit 9c788e2

Please sign in to comment.