From 1a024e60a796bb11936ea1d29c2c70e4160f53f1 Mon Sep 17 00:00:00 2001
From: Thomas Bechtold <tbechtold@suse.com>
Date: Mon, 11 Mar 2019 11:20:19 +0100
Subject: [PATCH] Don't fail if sqlalchemy driver fails to initialize

Given that the driver is initialized during the service
startup (eg. like Keystone, Nova, ...) a osprofiler driver failure has
a huge impact on the service (when the driver fails, the whole service
is not usable).
We want to avoid that and just log error/exceptions but keep the
services running.

Change-Id: I5688f10364884a74b7eb44c0c8bda15730ccd424
Closes-Bug: 1819433
---
 osprofiler/drivers/sqlalchemy_driver.py | 58 ++++++++++++++-----------
 1 file changed, 32 insertions(+), 26 deletions(-)

diff --git a/osprofiler/drivers/sqlalchemy_driver.py b/osprofiler/drivers/sqlalchemy_driver.py
index c16a3ac..06f3746 100644
--- a/osprofiler/drivers/sqlalchemy_driver.py
+++ b/osprofiler/drivers/sqlalchemy_driver.py
@@ -34,34 +34,40 @@ class SQLAlchemyDriver(base.Driver):
             from sqlalchemy import Table, MetaData, Column
             from sqlalchemy import String, JSON, Integer
         except ImportError:
-            raise exc.CommandError(
-                "To use this command, you should install 'SQLAlchemy'")
+            LOG.exception("To use this command, install 'SQLAlchemy'")
+        else:
+            self._metadata = MetaData()
+            self._data_table = Table(
+                "data", self._metadata,
+                Column("id", Integer, primary_key=True),
+                # timestamp - date/time of the trace point
+                Column("timestamp", String(26), index=True),
+                # base_id - uuid common for all notifications related to
+                # one trace
+                Column("base_id", String(255), index=True),
+                # parent_id - uuid of parent element in trace
+                Column("parent_id", String(255), index=True),
+                # trace_id - uuid of current element in trace
+                Column("trace_id", String(255), index=True),
+                Column("project", String(255), index=True),
+                Column("host", String(255), index=True),
+                Column("service", String(255), index=True),
+                # name - trace point name
+                Column("name", String(255), index=True),
+                Column("data", JSON)
+            )
 
-        self._engine = create_engine(connection_str)
-        self._conn = self._engine.connect()
-        self._metadata = MetaData()
-        self._data_table = Table(
-            "data", self._metadata,
-            Column("id", Integer, primary_key=True),
-            # timestamp - date/time of the trace point
-            Column("timestamp", String(26), index=True),
-            # base_id - uuid common for all notifications related to one trace
-            Column("base_id", String(255), index=True),
-            # parent_id - uuid of parent element in trace
-            Column("parent_id", String(255), index=True),
-            # trace_id - uuid of current element in trace
-            Column("trace_id", String(255), index=True),
-            Column("project", String(255), index=True),
-            Column("host", String(255), index=True),
-            Column("service", String(255), index=True),
-            # name - trace point name
-            Column("name", String(255), index=True),
-            Column("data", JSON)
-        )
+        # we don't want to kill any service that does use osprofiler
+        try:
+            self._engine = create_engine(connection_str)
+            self._conn = self._engine.connect()
 
-        # FIXME(toabctl): Not the best idea to create the table on every
-        # startup when using the sqlalchemy driver...
-        self._metadata.create_all(self._engine, checkfirst=True)
+            # FIXME(toabctl): Not the best idea to create the table on every
+            # startup when using the sqlalchemy driver...
+            self._metadata.create_all(self._engine, checkfirst=True)
+        except Exception:
+            LOG.exception("Failed to create engine/connection and setup "
+                          "intial database tables")
 
     @classmethod
     def get_name(cls):
-- 
2.21.0