diff --git a/packages/common/demo.js b/packages/common/demo.js
index 7bcc0a5bfb43eab441b50dbefb408e73139ea39c..1d75c31780f35f164fd31910e33dc97e6bb001a6 100644
--- a/packages/common/demo.js
+++ b/packages/common/demo.js
@@ -1,4 +1,13 @@
 import './vpu-mini-spinner.js';
 import './vpu-spinner.js';
 import './vpu-icon.js';
-import './vpu-button.js';
\ No newline at end of file
+import './vpu-button.js';
+import {init, captureMessage, captureException} from './errorreport';
+
+// error reporting
+init({debug: false, release: 'vpu-common@0.1'});
+captureMessage("test error message");
+captureException(new Error('another error'));
+setTimeout(() => {
+    throw new Error("an error");
+});
diff --git a/packages/common/env.js b/packages/common/env.js
index 02d9d232f57b51c688aa5b728befac4420836f46..0fc3eead53af1526415ff9290cf49026a11aea3f 100644
--- a/packages/common/env.js
+++ b/packages/common/env.js
@@ -8,6 +8,7 @@ switch(environment) {
             apiBaseUrl: 'https://mw-dev.tugraz.at',
             apiUrlPrefix: '',
             keyCloakClientId: 'auth-dev-mw-frontend',
+            sentryDSN: 'http://0405d811e8d746cca2e70f6eff764570@129.27.166.25:9000/2',
         };
 
         break;
@@ -35,4 +36,4 @@ switch(environment) {
 }
 
 
-export default config;
+export default config;
\ No newline at end of file
diff --git a/packages/common/errorreport.js b/packages/common/errorreport.js
new file mode 100644
index 0000000000000000000000000000000000000000..d174079323b096344b2b9389062933bc978bea24
--- /dev/null
+++ b/packages/common/errorreport.js
@@ -0,0 +1,65 @@
+import * as Sentry from '@sentry/browser';
+import env from './env.js';
+import environment from 'consts:environment';
+
+/**
+ * Initializes error reporting.
+ * 
+ * If a sentry DSN is set we will use sentry, if not we will log to the console.
+ * 
+ * @param {Boolean} [options.debug=false] Enable debug output
+ * @param {String} [options.release] The project release
+ */
+export function init(options) {
+  let defaults = {
+    debug: false,
+  };
+  let actual = Object.assign({}, defaults, options);
+
+  let sentryOptions = {debug: actual.debug, environment: environment};
+
+  if (actual.release) {
+    sentryOptions['release'] = actual.release;
+  }
+
+  if (!env.sentryDSN) {
+    if (options.debug)
+      console.log("No sentry DSN set, sentry disabled");
+
+    // In case we don't have a sentry config, we still use sentry, but print
+    // all events into the console don't send them to the server.
+    // XXX: Dummy DSN needed to make init() work.
+    sentryOptions['dsn'] = 'http://12345@dummy.dummy/42';
+    sentryOptions['beforeSend'] = (event, hint) => {
+      console.error('ERR-REPORT:', hint.originalException || hint.syntheticException);
+      return null;
+    };
+  } else {
+    sentryOptions['dsn'] = env.sentryDSN;
+  }
+
+  Sentry.init(sentryOptions);
+}
+
+/**
+ * Log an exception
+ *
+ * @param {*} exception
+ */
+export function captureException(exception) {
+  Sentry.captureException(exception);
+}
+
+/**
+ * Log a message, returns an internal ID
+ *
+ * @param {String} message The message to log
+ * @param {String} [level=error] The loglevel (error, warning, info, debug)
+ */
+export function captureMessage(message, level) {
+  if (!level)
+    level = 'error';
+  if (!['error', 'warning', 'info', 'debug'].includes(level))
+    throw new Error('Invalid log level');
+  Sentry.captureMessage(message, level);
+}
\ No newline at end of file
diff --git a/packages/common/package.json b/packages/common/package.json
index b9b5bf40fb360268c4e1b823ca5ed32d9b6fb376..e69e99d115be452ecfa4e2b6a65241e4d3b86f9e 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -29,9 +29,10 @@
     "watch": "rollup -c --watch"
   },
   "dependencies": {
+    "@sentry/browser": "^5.6.3",
+    "bulma": "^0.7.5",
     "i18next": "^17.0.11",
     "lit-element": "^2.2.1",
-    "material-design-icons-svg": "^3.0.0",
-    "bulma": "^0.7.5"
+    "material-design-icons-svg": "^3.0.0"
   }
 }