From 322a42c29d4fd4bc7952dcab41fa127ba5a9ba2b Mon Sep 17 00:00:00 2001
From: Andree Klattenhoff <andree.klattenhoff@open-xchange.com>
Date: Tue, 21 Mar 2023 15:16:58 +0100
Subject: [PATCH] OXUI-1194: Integrate logging for long running requests (>4s)

---
 README.md                                     |  48 +++----
 .../dashboards/nodejs-ui-mw.json              |   8 +-
 .../templates/deployment.yaml                 |   2 +
 helm/core-ui-middleware/values.yaml           |   1 +
 package.json                                  |   3 +-
 src/routes/autohooks.js                       |   9 +-
 yarn.lock                                     | 120 +++++++++++-------
 7 files changed, 115 insertions(+), 76 deletions(-)

diff --git a/README.md b/README.md
index b8b4fd5..3dffb39 100644
--- a/README.md
+++ b/README.md
@@ -47,33 +47,35 @@ It is possible to horizontally scale the UI Middleware, as more clients are fetc
 
 **local, docker**
 
-| Parameter             | Description                     | Default  |
-|-----------------------|---------------------------------|----------|
-| `PORT`                | Exposed port                    | `"8080"` |
-| `CACHE_TTL`           | Vite manifest caching time      | `30000`  |
-| `LOG_LEVEL`           | Pino log level                  | `"info"` |
-| `REDIS_HOST`          | Redis host (required)           |          |
-| `REDIS_PORT`          | Redis port (optional)           | `6379`   |
-| `REDIS_DB`            | Redis DB, e.g. `"1"` (optional) | null     |
-| `REDIS_PASSWORD`      | Redis password (optional)       | null     |
-| `COMPRESS_FILE_SIZE`  | Larger files will be gzipped    | `600`    |
-| `COMPRESS_FILE_TYPES` | Set of compression mime types   |see values|
+| Parameter                | Description                       | Default  |
+|--------------------------|-----------------------------------|----------|
+| `PORT`                   | Exposed port                      | `"8080"` |
+| `CACHE_TTL`              | Vite manifest caching time        | `30000`  |
+| `LOG_LEVEL`              | Pino log level                    | `"info"` |
+| `REDIS_HOST`             | Redis host (required)             |          |
+| `REDIS_PORT`             | Redis port (optional)             | `6379`   |
+| `REDIS_DB`               | Redis DB, e.g. `"1"` (optional)   | null     |
+| `REDIS_PASSWORD`         | Redis password (optional)         | null     |
+| `COMPRESS_FILE_SIZE`     | Larger files will be gzipped      | `600`    |
+| `COMPRESS_FILE_TYPES`    | Set of compression mime types     |see values|
+| `SLOW_REQUEST_THRESHOLD` | Slow request threshold in ms      | `4000`   |
 
 
 **kubernetes**
 
-| Parameter             | Description                     | Default  |
-|-----------------------|---------------------------------|----------|
-| `port`                | Exposed port                    | `"8080"` |
-| `cacheTTL`            | Vite manifest caching time      | `30000`  |
-| `logLevel`            | Pino log level                  | `"info"` |
-| `redis.enabled`       | Global switch Redis integration |  false   |
-| `redis.host`          | Redis host                      |          |
-| `redis.port`          | Redis port (optional)           | `6379`   |
-| `redis.db`            | Redis DB, e.g. `"1"` (optional) | null     |
-| `redis.password`      | Redis password (optional)       | null     |
-| `compressFileSize`    | Larger files will be gzipped    | `600`    |
-| `compressFileTypes`   | Set of compression mime types   |see values|
+| Parameter             | Description                        | Default  |
+|-----------------------|------------------------------------|----------|
+| `port`                | Exposed port                       | `"8080"` |
+| `cacheTTL`            | Vite manifest caching time         | `30000`  |
+| `logLevel`            | Pino log level                     | `"info"` |
+| `redis.enabled`       | Global switch Redis integration    |  false   |
+| `redis.host`          | Redis host                         |          |
+| `redis.port`          | Redis port (optional)              | `6379`   |
+| `redis.db`            | Redis DB, e.g. `"1"` (optional)    | null     |
+| `redis.password`      | Redis password (optional)          | null     |
+| `compressFileSize`    | Larger files will be gzipped       | `600`    |
+| `compressFileTypes`   | Set of compression mime types      |see values|
+| `slowRequestThreshold`| Slow request threshold in ms       | `4000`   |
 
 **config map**
 
diff --git a/helm/core-ui-middleware/dashboards/nodejs-ui-mw.json b/helm/core-ui-middleware/dashboards/nodejs-ui-mw.json
index 93964e3..dc2754f 100644
--- a/helm/core-ui-middleware/dashboards/nodejs-ui-mw.json
+++ b/helm/core-ui-middleware/dashboards/nodejs-ui-mw.json
@@ -330,8 +330,8 @@
             "type": "prometheus"
           },
           "editorMode": "code",
-          "expr": "histogram_quantile(0.9, sum(rate(http_request_duration_seconds_bucket{pod=~\"$pod\",namespace=~\"$namespace\",service=~\"$service\"}[10m])) by (le, route)) * 100",
-          "legendFormat": "p90 {{route}}",
+          "expr": "histogram_quantile(0.99, sum by (route,le) (rate(http_request_duration_seconds_bucket{pod=~\"$pod\",namespace=~\"$namespace\",service=~\"$service\"}[5m])))",
+          "legendFormat": "p99 {{route}}",
           "range": true,
           "refId": "A"
         },
@@ -340,7 +340,7 @@
             "type": "prometheus"
           },
           "editorMode": "code",
-          "expr": "histogram_quantile(0.5, sum(rate(http_request_duration_seconds_bucket{pod=~\"$pod\",namespace=~\"$namespace\",service=~\"$service\"}[10m])) by (le, route)) * 100",
+          "expr": "histogram_quantile(0.5, sum by (route,le) (rate(http_request_duration_seconds_bucket{pod=~\"$pod\",namespace=~\"$namespace\",service=~\"$service\"}[5m])))",
           "hide": false,
           "legendFormat": "Median {{route}}",
           "range": true,
@@ -1308,6 +1308,6 @@
   "timezone": "",
   "title": "App Suite / UI Middleware",
   "uid": "PTSqcpJWP",
-  "version": 6,
+  "version": 7,
   "weekStart": ""
 }
diff --git a/helm/core-ui-middleware/templates/deployment.yaml b/helm/core-ui-middleware/templates/deployment.yaml
index 63e0159..450d95c 100644
--- a/helm/core-ui-middleware/templates/deployment.yaml
+++ b/helm/core-ui-middleware/templates/deployment.yaml
@@ -33,6 +33,8 @@ spec:
               value: "{{ .Values.compressFileSize }}"
             - name: COMPRESS_FILE_TYPES
               value: "{{ .Values.compressFileTypes }}"
+            - name: SLOW_REQUEST_THRESHOLD
+              value: "{{ .Values.slowRequestThreshold }}"
             {{- if .Values.redis.enabled }}
             - name: REDIS_HOST
               value: "{{ required "redis.host required" .Values.redis.host }}"
diff --git a/helm/core-ui-middleware/values.yaml b/helm/core-ui-middleware/values.yaml
index a44c48b..588ba96 100644
--- a/helm/core-ui-middleware/values.yaml
+++ b/helm/core-ui-middleware/values.yaml
@@ -109,6 +109,7 @@ logLevel: info
 baseUrls: []
 compressFileSize: 600
 compressFileTypes: application/javascript application/json application/x-javascript application/xml application/xml+rss text/css text/html text/javascript text/plain text/xml image/svg+xml
+slowRequestThreshold: 4000
 
 extras:
   monitoring:
diff --git a/package.json b/package.json
index ea8bd1d..4d34b6c 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,8 @@
     "fastify-plugin": "^4.5.0",
     "ioredis": "^5.3.1",
     "js-yaml": "^4.0.0",
-    "lightship": "^7.1.1"
+    "lightship": "^7.1.1",
+    "useragent": "^2.3.0"
   },
   "devDependencies": {
     "@open-xchange/lint": "^0.0.2",
diff --git a/src/routes/autohooks.js b/src/routes/autohooks.js
index 41320ea..4ce8d4e 100644
--- a/src/routes/autohooks.js
+++ b/src/routes/autohooks.js
@@ -1,4 +1,5 @@
 import { getLatestVersion } from '../version.js'
+import UserAgent from 'useragent'
 export default async function (app, opts) {
   // Add a hook to set the version headers
   app.addHook('preHandler', async (req, reply) => {
@@ -19,10 +20,16 @@ export default async function (app, opts) {
 
   // Logs the request with the 'debug' level and also logs headers with the 'trace' level
   app.addHook('onResponse', (req, reply, done) => {
-    const loggingOptions = { url: req.raw.url, res: reply, responseTime: reply.getResponseTime() }
+    const responseTime = reply.getResponseTime()
+    const loggingOptions = { url: req.raw.url, res: reply, method: req.method, responseTime }
+    const slowRequestThreshold = parseInt(process.env.SLOW_REQUEST_THRESHOLD) || 4000
     /* c8 ignore next */
     if (process.env.LOG_LEVEL === 'trace') loggingOptions.headers = req.headers
     reply.log.debug(loggingOptions, 'request completed')
+    if (responseTime >= slowRequestThreshold) {
+      loggingOptions.userAgent = UserAgent.lookup(req.headers['user-agent'])
+      reply.log.info(loggingOptions, 'slow request')
+    }
     done()
   })
 }
diff --git a/yarn.lock b/yarn.lock
index f5afffb..7131551 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -29,10 +29,10 @@
     minimatch "^3.1.2"
     strip-json-comments "^3.1.1"
 
-"@eslint/js@8.37.0":
-  version "8.37.0"
-  resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.37.0.tgz#cf1b5fa24217fe007f6487a26d765274925efa7d"
-  integrity sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==
+"@eslint/js@8.38.0":
+  version "8.38.0"
+  resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.38.0.tgz#73a8a0d8aa8a8e6fe270431c5e72ae91b5337892"
+  integrity sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==
 
 "@fastify/accept-negotiator@^1.0.0":
   version "1.1.0"
@@ -121,9 +121,9 @@
     vary "^1.1.2"
 
 "@fastify/static@^6.0.0":
-  version "6.9.0"
-  resolved "https://registry.yarnpkg.com/@fastify/static/-/static-6.9.0.tgz#038efdfe33757cc0ab4b0920e82bc4240fa5d78a"
-  integrity sha512-9SBVNJi2+KTnfiW1WjiVXDsmUxliNI54OF1eOiaop264dh8FwXSuLmO62JXvx7+VD0vQXEqsyRbFCYUJ9aJxng==
+  version "6.10.0"
+  resolved "https://registry.yarnpkg.com/@fastify/static/-/static-6.10.0.tgz#cdb6a5ddcc3ea8691c79aad0c846bc986a4bc721"
+  integrity sha512-TGruNm6ZabkQz2oRNoarPnY2BvS9i9DNf8Nn1aDcZp+WjOQRPCq0Wy2ko78yGB5JHytdCWoHpprc128QtLl8hw==
   dependencies:
     "@fastify/accept-negotiator" "^1.0.0"
     "@fastify/send" "^2.0.0"
@@ -134,9 +134,9 @@
     readable-stream "^4.0.0"
 
 "@fastify/swagger-ui@^1.5.0":
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/@fastify/swagger-ui/-/swagger-ui-1.6.0.tgz#508b69d3ee75d8bfb7d05e572112c47c10f188d7"
-  integrity sha512-CfmRF79Ilrvo8k2M8hL6FrdOVTZyPa6UrEkN7n852CXPE+rqoxlN1eRrUg3qFkA93Wl6xEc1evAhFGz84uyM8A==
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/@fastify/swagger-ui/-/swagger-ui-1.7.0.tgz#a40dcf6f9e70e53e4872900054ffcf0d2ac156fc"
+  integrity sha512-ahhmJspsv+4mkRuKNDgeFUz/K91/SFgb8s6cs4iGDnohFwXTAilAAo9WyD0JBqLFKZyTu26EeHiC80y/3mQ1mA==
   dependencies:
     "@fastify/static" "^6.0.0"
     fastify-plugin "^4.0.0"
@@ -1129,14 +1129,14 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.0:
   integrity sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==
 
 eslint@^8.29.0:
-  version "8.37.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.37.0.tgz#1f660ef2ce49a0bfdec0b0d698e0b8b627287412"
-  integrity sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==
+  version "8.38.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.38.0.tgz#a62c6f36e548a5574dd35728ac3c6209bd1e2f1a"
+  integrity sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==
   dependencies:
     "@eslint-community/eslint-utils" "^4.2.0"
     "@eslint-community/regexpp" "^4.4.0"
     "@eslint/eslintrc" "^2.0.2"
-    "@eslint/js" "8.37.0"
+    "@eslint/js" "8.38.0"
     "@humanwhocodes/config-array" "^0.11.8"
     "@humanwhocodes/module-importer" "^1.0.1"
     "@nodelib/fs.walk" "^1.2.8"
@@ -1263,9 +1263,9 @@ fast-json-stringify@^2.7.10:
     string-similarity "^4.0.1"
 
 fast-json-stringify@^5.0.0:
-  version "5.6.2"
-  resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-5.6.2.tgz#1ea6c2b8d0f27f297f682d1af039398a603af507"
-  integrity sha512-F6xkRrXvtGbAiDSEI5Rk7qk2P63Y9kc8bO6Dnsd3Rt6sBNr2QxNFWs0JbKftgiyOfGxnJaRoHe4SizCTqeAyrA==
+  version "5.7.0"
+  resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-5.7.0.tgz#b0a04c848fdeb6ecd83440c71a4db35067023bed"
+  integrity sha512-sBVPTgnAZseLu1Qgj6lUbQ0HfjFhZWXAmpZ5AaSGkyLh5gAXBga/uPJjQPHpDFjC9adWIpdOcCLSDTgrZ7snoQ==
   dependencies:
     "@fastify/deepmerge" "^1.0.0"
     ajv "^8.10.0"
@@ -1615,9 +1615,9 @@ he@1.2.0:
   integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
 
 helmet@^6.0.0:
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/helmet/-/helmet-6.0.1.tgz#52ec353638b2e87f14fe079d142b368ac11e79a4"
-  integrity sha512-8wo+VdQhTMVBMCITYZaGTbE4lvlthelPYSvoyNvk4RECTmrVjMerp9RfUOQXZWLvCcAn1pKj7ZRxK4lI9Alrcw==
+  version "6.1.4"
+  resolved "https://registry.yarnpkg.com/helmet/-/helmet-6.1.4.tgz#a57dc478532e811f7dfd64b69f9023dad1c6e28e"
+  integrity sha512-nCJIriKjOYcRmHRpK+Z5DayEh6xwOKO0U0qzWL3MEIwsB8OSxxBu/mUE9U5PRH8ln/+WySlK2eYe5FOlo0v9aA==
 
 http-errors@2.0.0, http-errors@^2.0.0:
   version "2.0.0"
@@ -1699,9 +1699,9 @@ internal-slot@^1.0.5:
     side-channel "^1.0.4"
 
 ioredis-mock@^8.2.3:
-  version "8.4.0"
-  resolved "https://registry.yarnpkg.com/ioredis-mock/-/ioredis-mock-8.4.0.tgz#872d7ab1b8ee210094a677f0c1334815f09df775"
-  integrity sha512-ZB+Wj9kzYbYcPrU2Xr61Fo+Fcc8Y1/sAnc/8sCKhyi69C4lQf7cdTEqiqRwneICX2OwgGtpCw8Udr7GEyZixOQ==
+  version "8.5.0"
+  resolved "https://registry.yarnpkg.com/ioredis-mock/-/ioredis-mock-8.5.0.tgz#0a9aa968ce888e19e1a27b848d80de9ffec312fb"
+  integrity sha512-mtYmuQTta9gjlSUvI7imWpP7axR08DyW1WdVn80NthYIzSJeAWI5dd5rU1rVYc22/dVvJGx87SaoE3Zf6Rr8lA==
   dependencies:
     "@ioredis/as-callback" "^3.0.0"
     "@ioredis/commands" "^1.2.0"
@@ -1770,10 +1770,10 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7:
   resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
   integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
 
-is-core-module@^2.11.0, is-core-module@^2.9.0:
-  version "2.11.0"
-  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144"
-  integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==
+is-core-module@^2.11.0:
+  version "2.12.0"
+  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4"
+  integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==
   dependencies:
     has "^1.0.3"
 
@@ -1992,9 +1992,9 @@ lilconfig@2.1.0:
   integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
 
 lint-staged@>=13:
-  version "13.2.0"
-  resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.0.tgz#b7abaf79c91cd36d824f17b23a4ce5209206126a"
-  integrity sha512-GbyK5iWinax5Dfw5obm2g2ccUiZXNGtAS4mCbJ0Lv4rq6iEtfBSjOYdcbOtAIFtM114t0vdpViDDetjVTSd8Vw==
+  version "13.2.1"
+  resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.1.tgz#9d30a14e3e42897ef417bc98556fb757f75cae87"
+  integrity sha512-8gfzinVXoPfga5Dz/ZOn8I2GOhf81Wvs+KwbEXQn/oWZAvCVS2PivrXfVbFJc93zD16uC0neS47RXHIjXKYZQw==
   dependencies:
     chalk "5.2.0"
     cli-truncate "^3.1.0"
@@ -2094,6 +2094,14 @@ loupe@^2.3.1:
   dependencies:
     get-func-name "^2.0.0"
 
+lru-cache@4.1.x:
+  version "4.1.5"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
+  integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
+  dependencies:
+    pseudomap "^1.0.2"
+    yallist "^2.1.2"
+
 lru-cache@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -2516,9 +2524,9 @@ pino-abstract-transport@v1.0.0:
     split2 "^4.0.0"
 
 pino-std-serializers@^6.0.0:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.1.0.tgz#307490fd426eefc95e06067e85d8558603e8e844"
-  integrity sha512-KO0m2f1HkrPe9S0ldjx7za9BJjeHqBku5Ch8JyxETxT8dEFGz1PwgrHaOQupVYitpzbFSYm7nnljxD8dik2c+g==
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.2.0.tgz#169048c0df3f61352fce56aeb7fb962f1b66ab43"
+  integrity sha512-IWgSzUL8X1w4BIWTwErRgtV8PyOGOOi60uqv0oKuS/fOA8Nco/OeI6lBuc4dyP8MMfdFwyHqTMcBIA7nDiqEqA==
 
 pino@^8.5.0:
   version "8.11.0"
@@ -2550,9 +2558,9 @@ prelude-ls@^1.2.1:
   integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
 
 process-warning@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.1.0.tgz#1e60e3bfe8183033bbc1e702c2da74f099422d1a"
-  integrity sha512-9C20RLxrZU/rFnxWncDkuF6O999NdIf3E1ws4B0ZeY3sRVPzWBMsYDE2lxjxhiXxg464cQTgKUGm8/i6y2YGXg==
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.2.0.tgz#008ec76b579820a8e5c35d81960525ca64feb626"
+  integrity sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==
 
 process@^0.11.10:
   version "0.11.10"
@@ -2574,6 +2582,11 @@ proxy-addr@^2.0.7:
     forwarded "0.2.0"
     ipaddr.js "1.9.1"
 
+pseudomap@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+  integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==
+
 punycode@^2.1.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
@@ -2683,11 +2696,11 @@ resolve-from@^4.0.0:
   integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
 
 resolve@^1.22.1:
-  version "1.22.1"
-  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
-  integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
+  version "1.22.2"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
+  integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
   dependencies:
-    is-core-module "^2.9.0"
+    is-core-module "^2.11.0"
     path-parse "^1.0.7"
     supports-preserve-symlinks-flag "^1.0.0"
 
@@ -2789,9 +2802,9 @@ semver@^6.3.0:
   integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
 
 semver@^7.0.0, semver@^7.3.2, semver@^7.3.7, semver@^7.3.8:
-  version "7.3.8"
-  resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
-  integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
+  version "7.4.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-7.4.0.tgz#8481c92feffc531ab1e012a8ffc15bdd3a0f4318"
+  integrity sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==
   dependencies:
     lru-cache "^6.0.0"
 
@@ -3061,11 +3074,11 @@ through@^2.3.8:
   integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
 
 tiny-lru@^10.0.0:
-  version "10.3.0"
-  resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-10.3.0.tgz#2ddc88bbe8d9a2c761df673ebef52a82182a64b3"
-  integrity sha512-vTKRT2AEO1sViFDWAIzZVpV8KURCaMtnHa4RZB3XqtYLbrTO/fLDXKPEX9kVWq9u+nZREkwakbcmzGgvJm8QKA==
+  version "10.4.1"
+  resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-10.4.1.tgz#dec67a62115a4cb31d2065b8116d010daac362fe"
+  integrity sha512-buLIzw7ppqymuO3pt10jHk/6QMeZLbidihMQU+N6sogF6EnBzG0qtDWIHuhw1x3dyNgVL/KTGIZsTK81+yCzLg==
 
-tmp@^0.0.33:
+tmp@0.0.x, tmp@^0.0.33:
   version "0.0.33"
   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
   integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
@@ -3160,6 +3173,14 @@ uri-js@^4.2.2:
   dependencies:
     punycode "^2.1.0"
 
+useragent@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972"
+  integrity sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==
+  dependencies:
+    lru-cache "4.1.x"
+    tmp "0.0.x"
+
 uuid@^8.3.0:
   version "8.3.2"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
@@ -3243,6 +3264,11 @@ y18n@^5.0.5:
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
   integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
 
+yallist@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+  integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==
+
 yallist@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
-- 
GitLab