From fbcd738e806ba4378f9290e5b79db8a1c4fccc57 Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Fri, 14 Sep 2018 10:31:48 +0200
Subject: [PATCH] Add sentry integration

JIRA INFRA-525 #action In Progress
---
 app/commands.py            | 11 +++++++++++
 app/extensions.py          |  2 ++
 app/factory.py             | 13 +++++++++++--
 app/settings.py            | 10 ++++++++++
 requirements-to-freeze.txt |  1 +
 requirements.txt           |  1 +
 6 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/app/commands.py b/app/commands.py
index fd1c33f..678ebaa 100644
--- a/app/commands.py
+++ b/app/commands.py
@@ -14,6 +14,9 @@ import redis
 import rq
 import sqlalchemy as sa
 from flask import current_app
+from rq.contrib.sentry import register_sentry
+from raven import Client
+from raven.transport.http import HTTPTransport
 from .extensions import db, ldap_manager
 from .defaults import defaults
 from .tasks import TaskWorker
@@ -103,4 +106,12 @@ def register_cli(app):
         redis_connection = redis.from_url(redis_url)
         with rq.Connection(redis_connection):
             worker = TaskWorker(current_app.config["QUEUES"])
+            if current_app.config["SENTRY_DSN"]:
+                client = Client(
+                    current_app.config["SENTRY_DSN"],
+                    transport=HTTPTransport,
+                    environment=current_app.config["CSENTRY_ENVIRONMENT"],
+                    release=current_app.config["CSENTRY_RELEASE"],
+                )
+                register_sentry(client, worker)
             worker.work()
diff --git a/app/extensions.py b/app/extensions.py
index e8e7bc1..8e18dce 100644
--- a/app/extensions.py
+++ b/app/extensions.py
@@ -21,6 +21,7 @@ from flask_debugtoolbar import DebugToolbarExtension
 from flask_redis import FlaskRedis
 from flask_session import Session
 from flask_caching import Cache
+from raven.contrib.flask import Sentry
 
 
 convention = {
@@ -43,3 +44,4 @@ toolbar = DebugToolbarExtension()
 session_redis_store = FlaskRedis(config_prefix="SESSION_REDIS")
 fsession = Session()
 cache = Cache()
+sentry = Sentry()
diff --git a/app/factory.py b/app/factory.py
index 0eda82d..f311666 100644
--- a/app/factory.py
+++ b/app/factory.py
@@ -9,6 +9,7 @@ Create the WSGI application.
 :license: BSD 2-Clause, see LICENSE for more details.
 
 """
+import logging
 import sqlalchemy as sa
 import rq_dashboard
 from flask import Flask
@@ -26,6 +27,7 @@ from .extensions import (
     session_redis_store,
     fsession,
     cache,
+    sentry,
 )
 from .admin.views import (
     AdminModelView,
@@ -58,9 +60,15 @@ def create_app(config=None):
     app.jinja_env.filters["datetimeformat"] = utils.format_datetime
     app.jinja_env.filters["toyaml"] = utils.pretty_yaml
 
-    if not app.debug:
-        import logging
+    if app.config["SENTRY_DSN"]:
+        # CSENTRY_ENVIRONMENT can be overwritten in the local settings
+        # We can't define SENTRY_ENVIRONMENT before loading them
+        app.config["SENTRY_ENVIRONMENT"] = app.config["CSENTRY_ENVIRONMENT"]
+        sentry.init_app(
+            app, dsn=app.config["SENTRY_DSN"], logging=True, level=logging.ERROR
+        )
 
+    if not app.debug:
         # Send ERROR via mail
         from logging.handlers import SMTPHandler
 
@@ -107,6 +115,7 @@ def create_app(config=None):
         for key, value in app.config.items()
         if key
         not in (
+            "SENTRY_DSN",
             "SECRET_KEY",
             "LDAP_BIND_USER_PASSWORD",
             "MAIL_CREDENTIALS",
diff --git a/app/settings.py b/app/settings.py
index 8ff1de0..5e6eb49 100644
--- a/app/settings.py
+++ b/app/settings.py
@@ -10,6 +10,8 @@ This module implements the app default settings.
 
 """
 import os
+import raven
+from pathlib import Path
 from datetime import timedelta
 
 SQLALCHEMY_DATABASE_URI = "postgresql://ics:icspwd@postgres/csentry_db"
@@ -68,6 +70,7 @@ TEMPORARY_ICS_ID = "ZZ"
 MAC_OUI = "02:42:42"
 
 DOCUMENTATION_URL = "http://ics-infrastructure.pages.esss.lu.se/csentry/index.html"
+# Shall be set to staging|production|development
 CSENTRY_ENVIRONMENT = "staging"
 
 AWX_URL = "https://torn.tn.esss.lu.se"
@@ -85,3 +88,10 @@ VM_MEMORY_CHOICES = [2, 4, 8, 16, 32, 128]
 VM_DEFAULT_DNS = "172.16.6.21"
 VIOC_CORES_CHOICES = [1, 3, 6]
 VIOC_MEMORY_CHOICES = [2, 4, 8]
+
+# Sentry integration
+CSENTRY_RELEASE = raven.fetch_git_sha(Path(__file__).parents[1])
+# Leave to empty string to disable sentry integration
+SENTRY_DSN = ""
+SENTRY_USER_ATTRS = ["username"]
+SENTRY_CONFIG = {"release": CSENTRY_RELEASE}
diff --git a/requirements-to-freeze.txt b/requirements-to-freeze.txt
index 735bbf4..5fea95b 100644
--- a/requirements-to-freeze.txt
+++ b/requirements-to-freeze.txt
@@ -20,6 +20,7 @@ qrcode
 uwsgi
 whitenoise
 ansible-tower-cli
+raven
 rq
 rq-dashboard
 sqlalchemy-citext
diff --git a/requirements.txt b/requirements.txt
index ac291bb..87512fb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -33,6 +33,7 @@ python-dateutil==2.7.3
 python-editor==1.0.3
 PyYAML==3.13
 qrcode==6.0
+raven==6.9.0
 redis==2.10.6
 requests==2.19.1
 rq==0.12.0
-- 
GitLab