Skip to content

Commit

Permalink
BugSnag 🐛 (#157)
Browse files Browse the repository at this point in the history
* Added BugSnag error reporting, initial pass

* Add BugnSnag to docs + some error handling

* Delete test_operators_twitter.py
  • Loading branch information
battleoverflow authored Oct 4, 2023
1 parent 77c47a6 commit 1eae088
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 120 deletions.
4 changes: 4 additions & 0 deletions config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ credentials:
key: MY_API_KEY
ssl: False

error_reporting:
- name: bugsnag
api_key: API_KEY

sources:
# This section defines each of the input sources for ThreatIngestor.
# Define as many as you want. ThreatIngestor maintains a "state" for each of
Expand Down
13 changes: 13 additions & 0 deletions docs/extras.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ Extras

There are a few extra tools included alongside ThreatIngestor, that didn't quite make sense as sources or operators.

BugSnag
-------

BugSnag monitoring is a valuable tool to have when running in daemon mode. Adding it is extremely simple and the only requirement is to have an API key.

Here's an example to include in your ``config.yml``:

.. code-block:: yaml
error_reporting:
- name: bugsnag
api_key: API_KEY
Quick Webapp
------------

Expand Down
65 changes: 0 additions & 65 deletions tests/test_operators_twitter.py

This file was deleted.

48 changes: 47 additions & 1 deletion threatingestor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,30 @@
logger.info("Notifiers is not installed.")
notifiers = None

try:
import bugsnag
bugsnag_imported = True
except ImportError:
logger.info("BugSnag is not installed.")
bugsnag_imported = False

import threatingestor.config
import threatingestor.state
import threatingestor.exceptions
import threatingestor.whitelist

BUGSNAG_ACTIVE = False

def bugsnag_notification(msg=None, metadata=None) -> None:
"""
Monitor your code with BugSnag
You can include a additional information with the `metadata` paramater.
"""

if bugsnag_imported:
bugsnag.notify(Exception(msg), metadata={"ThreatIngestor" : metadata})

class Ingestor:
"""ThreatIngestor main work logic.
Expand All @@ -35,6 +54,7 @@ def __init__(self, config_file):

# Configure logging with optional notifiers.
logger.configure(**self.config.logging())

try:
logger.level("NOTIFY", no=35, color="<yellow>", icon="\U0001F514")
except TypeError:
Expand All @@ -61,13 +81,28 @@ def __init__(self, config_file):
logger.exception("Couldn't initialize statsd client; bad config?")
sys.exit(1)

# Configure BugSnag
if bugsnag_imported:
for service in self.config.error_reporting():
if service['name'] == "bugsnag":
if service['api_key']:
bugsnag.configure(api_key=service['api_key'])
logger.debug("BugSnag configured")
BUGSNAG_ACTIVE = True

break

# Load state DB.
try:
logger.debug(f"Opening state database '{self.config.state_path()}'")
self.statedb = threatingestor.state.State(self.config.state_path())
except (OSError, IOError, threatingestor.exceptions.IngestorError):
# Error loading state DB.
logger.exception("Error reading state database")

if BUGSNAG_ACTIVE:
bugsnag_notification("Error reading state database")

sys.exit(1)

# Instantiate plugins.
Expand All @@ -84,8 +119,11 @@ def __init__(self, config_file):
self.whitelist = threatingestor.whitelist.Whitelist(self.config.whitelists())

except (TypeError, ConnectionError, threatingestor.exceptions.PluginError):
logger.warning("Twitter config format has recently changed. See https://github.com/InQuest/ThreatIngestor/releases/tag/v1.0.0b5")
logger.exception("Error initializing plugins")

if BUGSNAG_ACTIVE:
bugsnag_notification("Error initializing plugins")

sys.exit(1)

def _is_whitelisted(self, artifact) -> bool:
Expand Down Expand Up @@ -122,6 +160,10 @@ def run_once(self):
except Exception:
self.statsd.incr(f'error.source.{source}')
logger.exception(f"Unknown error in source '{source}'")

if BUGSNAG_ACTIVE:
bugsnag_notification(f"Unknown error in source '{source}'")

continue

# Save the source state.
Expand All @@ -144,6 +186,10 @@ def run_once(self):
except Exception:
self.statsd.incr(f'error.operator.{operator}')
logger.exception(f"Unknown error in operator '{operator}'")

if BUGSNAG_ACTIVE:
bugsnag_notification(f"Unknown error in operator '{operator}'")

continue

# Record stats and update the summary.
Expand Down
5 changes: 5 additions & 0 deletions threatingestor/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ def logging(self):
return self.config.get('logging', {})


def error_reporting(self):
"""Returns error_reporting config dictionary."""
return self.config['error_reporting']


def credentials(self, credential_name):
"""Return a dictionary with the specified credentials."""
for credential in self.config['credentials']:
Expand Down
54 changes: 0 additions & 54 deletions threatingestor/operators/twitter.py

This file was deleted.

0 comments on commit 1eae088

Please sign in to comment.