Преглед изворни кода

Merge pull request #2013 from porter-dev/nico/improve-cohere-sentry-integration

Improve cohere sentry integration
Nicolas Frati пре 4 година
родитељ
комит
a8da89876d

+ 4 - 4
.github/workflows/production.yaml

@@ -22,7 +22,7 @@ jobs:
       - name: Install kubectl
         uses: azure/setup-kubectl@v2.0
         with:
-          version: 'v1.19.15'
+          version: "v1.19.15"
       - name: Log in to gcloud CLI
         run: gcloud auth configure-docker
       - name: Checkout
@@ -38,7 +38,7 @@ jobs:
           FEEDBACK_ENDPOINT=${{secrets.FEEDBACK_ENDPOINT}}
           IS_HOSTED=true
           ENABLE_COHERE=true
-          COHERE_KEY=${{secrets.COHERE_KEY}}
+          COHERE_API_KEY=${{secrets.COHERE_KEY}}
           INTERCOM_APP_ID=${{secrets.INTERCOM_APP_ID}}
           INTERCOM_SRC=${{secrets.INTERCOM_SRC}}
           SEGMENT_WRITE_KEY=${{secrets.SEGMENT_WRITE_KEY}}
@@ -78,7 +78,7 @@ jobs:
       - name: Install kubectl
         uses: azure/setup-kubectl@v2.0
         with:
-          version: 'v1.19.15'
+          version: "v1.19.15"
       - name: Log in to gcloud CLI
         run: gcloud auth configure-docker
       - name: Checkout
@@ -93,4 +93,4 @@ jobs:
         run: |
           aws eks --region ${{ secrets.AWS_REGION }} update-kubeconfig --name production-2
             
-          kubectl rollout restart deployment/provisioner
+          kubectl rollout restart deployment/provisioner

+ 4 - 3
.github/workflows/staging.yaml

@@ -22,7 +22,7 @@ jobs:
       - name: Install kubectl
         uses: azure/setup-kubectl@v2.0
         with:
-          version: 'v1.19.15'
+          version: "v1.19.15"
       - name: Log in to gcloud CLI
         run: gcloud auth configure-docker
       - name: Checkout
@@ -36,7 +36,8 @@ jobs:
           DISCORD_CID=${{secrets.DISCORD_CID}}
           FEEDBACK_ENDPOINT=${{secrets.FEEDBACK_ENDPOINT}}
           IS_HOSTED=true
-          COHERE_KEY=${{secrets.COHERE_KEY}}
+          ENABLE_COHERE=true
+          COHERE_API_KEY=${{secrets.COHERE_KEY}}
           INTERCOM_APP_ID=${{secrets.INTERCOM_APP_ID}}
           INTERCOM_SRC=${{secrets.INTERCOM_SRC}}
           SEGMENT_WRITE_KEY=${{secrets.SEGMENT_WRITE_KEY}}
@@ -76,7 +77,7 @@ jobs:
       - name: Install kubectl
         uses: azure/setup-kubectl@v2.0
         with:
-          version: 'v1.19.15'
+          version: "v1.19.15"
       - name: Log in to gcloud CLI
         run: gcloud auth configure-docker
       - name: Checkout

+ 123 - 176
dashboard/src/hosted.index.html

@@ -1,186 +1,133 @@
 <!DOCTYPE html>
 <html lang="en">
-  <head>
-    <title>Porter | Dashboard</title>
 
-    <script>
-      !(function () {
-        var e = (window.Cohere = window.Cohere || []);
-        if (e.invoked) console.error("Tried to load Cohere twice");
-        else {
-          (e.invoked = !0),
-            (e.snippet = "0.2"),
-            (e.methods = [
-              "init",
-              "identify",
-              "stop",
-              "showCode",
-              "getSessionUrl",
-              "makeCall",
-              "addCallStatusListener",
-              "removeCallStatusListener",
-              "widget",
-            ]),
-            e.methods.forEach(function (o) {
-              e[o] = function () {
-                var t = Array.prototype.slice.call(arguments);
-                t.unshift(o), e.push(t);
-              };
-            });
-          var o = document.createElement("script");
-          (o.type = "text/javascript"),
-            (o.async = !0),
-            (o.src = "https://static.cohere.so/main.js"),
-            (o.crossOrigin = "anonymous");
-          var t = document.getElementsByTagName("script")[0];
-          t.parentNode.insertBefore(o, t);
-        }
-      })();
-      window.Cohere.init("<%= htmlWebpackPlugin.options.cohereKey %>");
-    </script>
+<head>
+  <title>Porter | Dashboard</title>
 
-    <script>
-      window.intercomSettings = {
-        app_id: "<%= htmlWebpackPlugin.options.intercomAppId %>",
-        custom_launcher_selector: "#intercom_help",
-      };
-    </script>
+  <script>
+    window.intercomSettings = {
+      app_id: "<%= htmlWebpackPlugin.options.intercomAppId %>",
+      custom_launcher_selector: "#intercom_help",
+    };
+  </script>
 
-    <script>
-      // We pre-filled your app ID in the widget URL: 'https://widget.intercom.io/widget/gq56g49i'
-      (function () {
-        var w = window;
-        var ic = w.Intercom;
-        if (typeof ic === "function") {
-          ic("reattach_activator");
-          ic("update", w.intercomSettings);
+  <script>
+    // We pre-filled your app ID in the widget URL: 'https://widget.intercom.io/widget/gq56g49i'
+    (function () {
+      var w = window;
+      var ic = w.Intercom;
+      if (typeof ic === "function") {
+        ic("reattach_activator");
+        ic("update", w.intercomSettings);
+      } else {
+        var d = document;
+        var i = function () {
+          i.c(arguments);
+        };
+        i.q = [];
+        i.c = function (args) {
+          i.q.push(args);
+        };
+        w.Intercom = i;
+        var l = function () {
+          var s = d.createElement("script");
+          s.type = "text/javascript";
+          s.async = true;
+          s.src = "<%= htmlWebpackPlugin.options.intercomSrc %>";
+          var x = d.getElementsByTagName("script")[0];
+          x.parentNode.insertBefore(s, x);
+        };
+        if (document.readyState === "complete") {
+          l();
+        } else if (w.attachEvent) {
+          w.attachEvent("onload", l);
         } else {
-          var d = document;
-          var i = function () {
-            i.c(arguments);
-          };
-          i.q = [];
-          i.c = function (args) {
-            i.q.push(args);
-          };
-          w.Intercom = i;
-          var l = function () {
-            var s = d.createElement("script");
-            s.type = "text/javascript";
-            s.async = true;
-            s.src = "<%= htmlWebpackPlugin.options.intercomSrc %>";
-            var x = d.getElementsByTagName("script")[0];
-            x.parentNode.insertBefore(s, x);
-          };
-          if (document.readyState === "complete") {
-            l();
-          } else if (w.attachEvent) {
-            w.attachEvent("onload", l);
-          } else {
-            w.addEventListener("load", l, false);
-          }
+          w.addEventListener("load", l, false);
         }
-      })();
-    </script>
+      }
+    })();
+  </script>
 
-    <script>
-      !(function () {
-        var analytics = (window.analytics = window.analytics || []);
-        if (!analytics.initialize)
-          if (analytics.invoked)
-            window.console &&
-              console.error &&
-              console.error("Segment snippet included twice.");
-          else {
-            analytics.invoked = !0;
-            analytics.methods = [
-              "trackSubmit",
-              "trackClick",
-              "trackLink",
-              "trackForm",
-              "pageview",
-              "identify",
-              "reset",
-              "group",
-              "track",
-              "ready",
-              "alias",
-              "debug",
-              "page",
-              "once",
-              "off",
-              "on",
-              "addSourceMiddleware",
-              "addIntegrationMiddleware",
-              "setAnonymousId",
-              "addDestinationMiddleware",
-            ];
-            analytics.factory = function (e) {
-              return function () {
-                var t = Array.prototype.slice.call(arguments);
-                t.unshift(e);
-                analytics.push(t);
-                return analytics;
-              };
-            };
-            for (var e = 0; e < analytics.methods.length; e++) {
-              var key = analytics.methods[e];
-              analytics[key] = analytics.factory(key);
-            }
-            analytics.load = function (key, e) {
-              var t = document.createElement("script");
-              t.type = "text/javascript";
-              t.async = !0;
-              t.src =
-                "https://cdn.segment.com/analytics.js/v1/" +
-                key +
-                "/analytics.min.js";
-              var n = document.getElementsByTagName("script")[0];
-              n.parentNode.insertBefore(t, n);
-              analytics._loadOptions = e;
+  <script>
+    !(function () {
+      var analytics = (window.analytics = window.analytics || []);
+      if (!analytics.initialize)
+        if (analytics.invoked)
+          window.console &&
+            console.error &&
+            console.error("Segment snippet included twice.");
+        else {
+          analytics.invoked = !0;
+          analytics.methods = [
+            "trackSubmit",
+            "trackClick",
+            "trackLink",
+            "trackForm",
+            "pageview",
+            "identify",
+            "reset",
+            "group",
+            "track",
+            "ready",
+            "alias",
+            "debug",
+            "page",
+            "once",
+            "off",
+            "on",
+            "addSourceMiddleware",
+            "addIntegrationMiddleware",
+            "setAnonymousId",
+            "addDestinationMiddleware",
+          ];
+          analytics.factory = function (e) {
+            return function () {
+              var t = Array.prototype.slice.call(arguments);
+              t.unshift(e);
+              analytics.push(t);
+              return analytics;
             };
-            analytics._writeKey = "<%= htmlWebpackPlugin.options.segmentWriteKey %>";
-            analytics.SNIPPET_VERSION = "4.13.2";
-            analytics.load("<%= htmlWebpackPlugin.options.segmentKey %>");
-            analytics.page();
+          };
+          for (var e = 0; e < analytics.methods.length; e++) {
+            var key = analytics.methods[e];
+            analytics[key] = analytics.factory(key);
           }
-      })();
-    </script>
-    <link rel="icon" href="https://i.ibb.co/HnSk02f/ptr.png" />
-    <meta
-      name="description"
-      content="Kubernetes powered PaaS that runs in your own cloud."
-    />
-    <meta property="og:title" content="Porter" />
-    <meta
-      property="og:image"
-      content="https://i.ibb.co/52g2g7C/porter-wide.png"
-    />
-    <meta
-      property="og:description"
-      content="Kubernetes powered PaaS that runs in your own cloud."
-    />
-    <meta property="og:url" content="https://porter.run" />
-    <link
-      href="https://fonts.googleapis.com/css?family=Work+Sans:400,500,600"
-      rel="stylesheet"
-    />
-    <link
-      href="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.css"
-      rel="stylesheet"
-    />
-    <link
-      href="https://fonts.googleapis.com/icon?family=Material+Icons|Material+Icons+Outlined|Material+Icons+Round"
-      rel="stylesheet"
-    />
-    <!-- Coding languages icons -->
-    <link
-      rel="stylesheet"
-      href="https://cdn.jsdelivr.net/gh/devicons/devicon@v2.14.0/devicon.min.css"
-    />
-  </head>
-  <body>
-    <div id="output"></div>
-    <div id="modal-root"></div>
-  </body>
-</html>
+          analytics.load = function (key, e) {
+            var t = document.createElement("script");
+            t.type = "text/javascript";
+            t.async = !0;
+            t.src =
+              "https://cdn.segment.com/analytics.js/v1/" +
+              key +
+              "/analytics.min.js";
+            var n = document.getElementsByTagName("script")[0];
+            n.parentNode.insertBefore(t, n);
+            analytics._loadOptions = e;
+          };
+          analytics._writeKey = "<%= htmlWebpackPlugin.options.segmentWriteKey %>";
+          analytics.SNIPPET_VERSION = "4.13.2";
+          analytics.load("<%= htmlWebpackPlugin.options.segmentKey %>");
+          analytics.page();
+        }
+    })();
+  </script>
+  <link rel="icon" href="https://i.ibb.co/HnSk02f/ptr.png" />
+  <meta name="description" content="Kubernetes powered PaaS that runs in your own cloud." />
+  <meta property="og:title" content="Porter" />
+  <meta property="og:image" content="https://i.ibb.co/52g2g7C/porter-wide.png" />
+  <meta property="og:description" content="Kubernetes powered PaaS that runs in your own cloud." />
+  <meta property="og:url" content="https://porter.run" />
+  <link href="https://fonts.googleapis.com/css?family=Work+Sans:400,500,600" rel="stylesheet" />
+  <link href="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.css" rel="stylesheet" />
+  <link href="https://fonts.googleapis.com/icon?family=Material+Icons|Material+Icons+Outlined|Material+Icons+Round"
+    rel="stylesheet" />
+  <!-- Coding languages icons -->
+  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/devicons/devicon@v2.14.0/devicon.min.css" />
+</head>
+
+<body>
+  <div id="output"></div>
+  <div id="modal-root"></div>
+</body>
+
+</html>

+ 1 - 1
dashboard/src/index.tsx

@@ -14,7 +14,7 @@ declare global {
   }
 }
 
-if (process.env.ENABLE_COHERE) {
+if (process.env.ENABLE_COHERE && process.env.COHERE_API_KEY) {
   Cohere.init(process.env.COHERE_API_KEY);
 }
 

+ 14 - 1
dashboard/src/main/home/onboarding/steps/ProvisionResources/ProvisionResources.tsx

@@ -219,7 +219,20 @@ const ProvisionResources: React.FC<{}> = () => {
     if (infraStatus.hasError) {
       Cohere.widget("show");
       Cohere.widget("expand");
-      ProvisionResourcesLogger.critical(new Error(infraStatus.description));
+
+      const cause = new Error(
+        JSON.stringify({
+          description: infraStatus.description,
+          errored_infras: infraStatus.errored_infras,
+        })
+      );
+
+      ProvisionResourcesLogger.critical(
+        new Error(
+          `Provisioner error detected ${snap.StateHandler.project.id}`,
+          { cause }
+        )
+      );
     } else {
       Cohere.widget("hide");
     }

+ 36 - 8
dashboard/src/shared/error_handling/logger.ts

@@ -1,19 +1,47 @@
 import * as Sentry from "@sentry/react";
+import Cohere from "cohere-js";
+import { isEmpty } from "lodash";
 
-type LogFunction = (error: Error) => void;
+type LogFunction = (error: Error, tags?: { [key: string]: string }) => void;
 type LogFunctions = {
   [key in Sentry.Severity]: LogFunction;
 };
 
-const logFunctionBuilder = (scope: string, severity: Sentry.Severity) => (
-  error: Error
+type LogFunctionBuilder = (
+  scope: string,
+  severity: Sentry.Severity
+) => LogFunction;
+
+const logFunctionBuilder: LogFunctionBuilder = (scope, severity) => (
+  error,
+  tags
 ) => {
-  Sentry.withScope((sentryScope) => {
-    sentryScope.setTag("scope", scope);
-    sentryScope.setLevel(severity);
+  if (process.env.ENABLE_COHERE) {
+    Cohere.getSessionUrl((sessionUrl) => {
+      Sentry.withScope((sentryScope) => {
+        sentryScope.setTag("scope", scope);
+        sentryScope.setTag("cohere_link", sessionUrl);
+        sentryScope.setLevel(severity);
+
+        if (!isEmpty(tags)) {
+          sentryScope.setTags(tags);
+        }
+
+        Sentry.captureException(error);
+      });
+    });
+  } else {
+    Sentry.withScope((sentryScope) => {
+      sentryScope.setTag("scope", scope);
+      sentryScope.setLevel(severity);
+
+      if (!isEmpty(tags)) {
+        sentryScope.setTags(tags);
+      }
 
-    Sentry.captureException(error);
-  });
+      Sentry.captureException(error);
+    });
+  }
 };
 
 function buildLogger(scope: string = "global") {

+ 19 - 0
dashboard/src/shared/error_handling/sentry/setup.ts

@@ -1,5 +1,6 @@
 import * as Sentry from "@sentry/react";
 import { Integrations } from "@sentry/tracing";
+import Cohere from "cohere-js";
 import CohereSentry from "cohere-sentry";
 
 const SENTRY_DSN = process.env.SENTRY_DSN;
@@ -19,4 +20,22 @@ export const SetupSentry = () => {
     // Check out https://docs.sentry.io/platforms/javascript/guides/react/configuration/sampling/ for a more refined sample rate
     tracesSampleRate: 1,
   });
+
+  if (process.env.ENABLE_COHERE) {
+    const sessionUrlListener = (sessionUrl: string) => {
+      Sentry.configureScope((scope) => {
+        scope.addEventProcessor((event) => {
+          event.tags = {
+            ...event.tags,
+            cohere_link: `${sessionUrl}${
+              event.timestamp ? `?ts=${event.timestamp * 1000}` : ""
+            }`,
+          };
+
+          return event;
+        });
+      });
+    };
+    Cohere.addSessionUrlListener(sessionUrlListener);
+  }
 };

+ 0 - 1
dashboard/webpack.config.js

@@ -44,7 +44,6 @@ module.exports = () => {
   if (env.IS_HOSTED) {
     htmlPluginOpts = {
       template: path.resolve(__dirname, "src", "hosted.index.html"),
-      cohereKey: `${env.COHERE_KEY}`,
       intercomAppId: `${env.INTERCOM_APP_ID}`,
       intercomSrc: `${process.env.INTERCOM_SRC}`,
       segmentWriteKey: `${process.env.SEGMENT_WRITE_KEY}`,