diff --git a/dashboard/Dockerfile b/dashboard/Dockerfile index 21374ab..0dbdc6c 100644 --- a/dashboard/Dockerfile +++ b/dashboard/Dockerfile @@ -1,5 +1,5 @@ # Step 1: Builds and tests -FROM node:12.22.12-bullseye AS build +FROM node:14.21.3-bullseye AS build ARG kubeflowversion ARG commit @@ -24,7 +24,9 @@ RUN BUILDARCH="$(dpkg --print-architecture)" && npm rebuild && \ npm prune --production # Step 2: Packages assets for serving -FROM node:12.22.12-alpine AS serve +FROM node:14.21.3-alpine3.17 AS serve + +USER node ENV NODE_ENV=production WORKDIR /app diff --git a/dashboard/Makefile b/dashboard/Makefile deleted file mode 100644 index a7debe8..0000000 --- a/dashboard/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -IMG ?= centraldashboard -TAG ?= $(shell git describe --tags --always --dirty) -COMMIT = $(shell git rev-parse HEAD) -DOCKERFILE ?= Dockerfile -ARCH ?= linux/amd64 - - -all: build - -clean: - rm -rf coverage/ dist/ node_modules/ .nyc_output/ - -# Builds the package locally -build-local: - npm install - -# Runs unit tests with coverage -test: build-local - npm run coverage - -# To build without the cache set the environment variable -# export DOCKER_BUILD_OPTS=--no-cache -docker-build: - docker build ${DOCKER_BUILD_OPTS} -t $(IMG):$(TAG) . \ - --build-arg kubeflowversion=$(shell git describe --abbrev=0 --tags) \ - --build-arg commit=$(COMMIT) \ - --label=git-verions=$(TAG) - @echo Built $(IMG):$(TAG) - -docker-push: - docker push $(IMG):$(TAG) - -.PHONY: docker-build-multi-arch -docker-build-multi-arch: ## Build multi-arch docker images with docker buildx - docker buildx build --load --platform ${ARCH} --tag ${IMG}:${TAG} -f ${DOCKERFILE} . - - -.PHONY: docker-build-push-multi-arch -docker-build-push-multi-arch: ## Build multi-arch docker images with docker buildx and push to docker registry - docker buildx build --platform ${ARCH} --tag ${IMG}:${TAG} --push -f ${DOCKERFILE} . - -# Build but don't attach the latest tag. This allows manual testing/inspection of the image -# first. -push: build - gcloud docker -- push $(IMG):$(TAG) - @echo Pushed $(IMG) with :$(TAG) tags - diff --git a/dashboard/app/api.ts b/dashboard/app/api.ts index 9caa5ea..d31a3ee 100644 --- a/dashboard/app/api.ts +++ b/dashboard/app/api.ts @@ -3,6 +3,7 @@ import {KubernetesService} from './k8s_service'; import {Interval, MetricsService} from './metrics_service'; export const ERRORS = { + no_metrics_service_configured: 'No metrics service configured', operation_not_supported: 'Operation not supported', invalid_links_config: 'Cannot load dashboard menu link', invalid_settings: 'Cannot load dashboard settings' @@ -28,6 +29,15 @@ export class Api { */ routes(): Router { return Router() + .get('/metrics', async (req: Request, res: Response) => { + if (!this.metricsService) { + return apiError({ + res, code: 405, + error: ERRORS.operation_not_supported, + }); + } + res.json(this.metricsService.getChartsLink()); + }) .get( '/metrics/:type((node|podcpu|podmem))', async (req: Request, res: Response) => { diff --git a/dashboard/app/api_test.ts b/dashboard/app/api_test.ts index 9ddc344..810c12c 100644 --- a/dashboard/app/api_test.ts +++ b/dashboard/app/api_test.ts @@ -34,11 +34,22 @@ describe('Main API', () => { port = addressInfo.port; }); - it('Should return a 405 status code', (done) => { - get(`http://localhost:${port}/api/metrics/podcpu`, (res) => { - expect(res.statusCode).toBe(405); - done(); + it('Should return a 405 status code', async () => { + const metricsEndpoint = new Promise((resolve) => { + get(`http://localhost:${port}/api/metrics`, (res) => { + expect(res.statusCode).toBe(405); + resolve(); + }); + }); + + const metricsTypeEndpoint = new Promise((resolve) => { + get(`http://localhost:${port}/api/metrics/podcpu`, (res) => { + expect(res.statusCode).toBe(405); + resolve(); + }); }); + + await Promise.all([metricsEndpoint, metricsTypeEndpoint]); }); }); @@ -47,7 +58,7 @@ describe('Main API', () => { mockK8sService = jasmine.createSpyObj(['']); mockProfilesService = jasmine.createSpyObj(['']); mockMetricsService = jasmine.createSpyObj([ - 'getNodeCpuUtilization', 'getPodCpuUtilization', 'getPodMemoryUsage' + 'getNodeCpuUtilization', 'getPodCpuUtilization', 'getPodMemoryUsage', 'getChartsLink' ]); testApp = express(); @@ -64,6 +75,15 @@ describe('Main API', () => { } }); + it('Should retrieve charts link in Metrics service', (done) => { + get(`http://localhost:${port}/api/metrics`, (res) => { + expect(res.statusCode).toBe(200); + expect(mockMetricsService.getChartsLink) + .toHaveBeenCalled(); + done(); + }); + }); + it('Should retrieve Node CPU Utilization for default 15m interval', async () => { const defaultInterval = new Promise((resolve) => { diff --git a/dashboard/app/metrics_service.ts b/dashboard/app/metrics_service.ts index 96f032f..6c18714 100644 --- a/dashboard/app/metrics_service.ts +++ b/dashboard/app/metrics_service.ts @@ -14,6 +14,11 @@ export interface TimeSeriesPoint { value: number; } +export interface MetricsInfo { + resourceChartsLink: string | undefined; + resourceChartsLinkText: string; +} + /** * Interface definition for implementers of metrics services capable of * returning time-series resource utilization metrics for the Kubeflow system. @@ -39,4 +44,10 @@ export interface MetricsService { * @param interval */ getPodMemoryUsage(interval: Interval): Promise; + + /** + * Return a MetricsInfo object containing the url of the metric dashboard and the + * text to display for the redirect button. + */ + getChartsLink(): MetricsInfo; } diff --git a/dashboard/app/prometheus_metrics_service.ts b/dashboard/app/prometheus_metrics_service.ts new file mode 100644 index 0000000..4400387 --- /dev/null +++ b/dashboard/app/prometheus_metrics_service.ts @@ -0,0 +1,90 @@ +import {Interval, MetricsInfo, MetricsService, TimeSeriesPoint} from "./metrics_service"; +import {PrometheusDriver, RangeVector, ResponseType} from 'prometheus-query'; + +export class PrometheusMetricsService implements MetricsService { + private readonly prometheusDriver: PrometheusDriver; + private readonly dashboardUrl: string | undefined; + + constructor(prometheusDriver: PrometheusDriver, dashboardUrl: string | undefined) { + this.prometheusDriver = prometheusDriver; + this.dashboardUrl = dashboardUrl; + } + + async getNodeCpuUtilization(interval: Interval): Promise { + const query = `sum(rate(node_cpu_seconds_total[5m])) by (instance)`; + const result = await this.queryPrometheus(query, this.getCorrespondingTime(interval)); + return this.convertToTimeSeriesPoints(result); + } + + async getPodCpuUtilization(interval: Interval): Promise { + const query = `sum(rate(container_cpu_usage_seconds_total[5m]))`; + const result = await this.queryPrometheus(query, this.getCorrespondingTime(interval)); + return this.convertToTimeSeriesPoints(result); + } + + async getPodMemoryUsage(interval: Interval): Promise { + const query = `sum(container_memory_usage_bytes)`; + const result = await this.queryPrometheus(query, this.getCorrespondingTime(interval)); + return this.convertToTimeSeriesPoints(result); + } + + private async queryPrometheus(query: string, start: number, end: number = Date.now()): Promise { + const result = await this.prometheusDriver.rangeQuery(query, start, end, 10); + if(result.resultType !== ResponseType.MATRIX) { + console.warn(`The prometheus server returned invalid result type: ${result.resultType}`); + return []; + } + return result.result as RangeVector[]; + } + + private getCorrespondingTime(interval: Interval): number { + let minutes = 0; + switch (interval) { + case Interval.Last5m: + minutes = 5; + break; + case Interval.Last15m: + minutes = 15; + break; + case Interval.Last30m: + minutes = 30; + break; + case Interval.Last60m: + minutes = 60; + break; + case Interval.Last180m: + minutes = 180; + break; + default: + console.warn("unknown interval."); + } + return Date.now() - minutes * 60 * 1000; + } + + private convertToTimeSeriesPoints(series: RangeVector[]): TimeSeriesPoint[] { + const timeSeriesPoints: TimeSeriesPoint[] = []; + series.forEach(serie => { + + const label = Object.entries(serie.metric.labels).map((entry) => { + return entry[0] + "=" + entry[1]; + }).join(","); + + // The `public/components/resource-chart.js` is multiplying the timestamp by 1000 and the value by 100 + serie.values.forEach(value => { + timeSeriesPoints.push({ + timestamp: value.time.getTime() / 1000, + label, + value: value.value / 100, + }); + }); + }); + return timeSeriesPoints; + } + + getChartsLink(): MetricsInfo { + return { + resourceChartsLink: this.dashboardUrl, + resourceChartsLinkText: 'View in dashboard' + }; + } +} diff --git a/dashboard/app/prometheus_metrics_service_test.ts b/dashboard/app/prometheus_metrics_service_test.ts new file mode 100644 index 0000000..404d6ba --- /dev/null +++ b/dashboard/app/prometheus_metrics_service_test.ts @@ -0,0 +1,142 @@ +import {Metric, PrometheusDriver, QueryResult, ResponseType} from "prometheus-query"; +import {PrometheusMetricsService} from "./prometheus_metrics_service"; +import {Interval, MetricsService, TimeSeriesPoint} from "./metrics_service"; +import {SampleValue} from "prometheus-query/dist/types"; + +type MetricsServiceKeys = keyof MetricsService; +const methods: MetricsServiceKeys[] = ["getNodeCpuUtilization", "getPodCpuUtilization", "getPodMemoryUsage"]; +const queries: {[id: string]: string} = { + "getNodeCpuUtilization": "sum(rate(node_cpu_seconds_total[5m])) by (instance)", + "getPodCpuUtilization": "sum(rate(container_cpu_usage_seconds_total[5m]))", + "getPodMemoryUsage": "sum(container_memory_usage_bytes)" +}; + +const fixedDate = 1557705600000; + +const emptyDataSet: QueryResult = {"resultType": ResponseType.MATRIX,"result":[]}; +const singleInstanceDataSet: QueryResult = { + "resultType": ResponseType.MATRIX, + "result":[ + { + "metric": {"labels": {"instance":"one"}} as Metric, + "values":[ + { + time: new Date(fixedDate), + value: 95.5, + } as SampleValue + ] + } + ] +}; +const multipleInstancesDataSet: QueryResult = { + "resultType": ResponseType.MATRIX, + "result":[ + { + "metric": {"labels": {"instance":"one"}} as Metric, + "values":[ + { + time: new Date(fixedDate), + value: 1.0, + } as SampleValue + ] + }, + { + "metric": {"labels": {"instance":"two"}} as Metric, + "values":[ + { + time: new Date(fixedDate), + value: 2.0, + } as SampleValue + ] + }, + { + "metric": {"labels": {"instance":"three"}} as Metric, + "values":[ + { + time: new Date(fixedDate), + value: 3.0, + } as SampleValue + ] + } + ] +}; + +describe('PrometheusMetricsService', () => { + let prometheusDriverClient: jasmine.SpyObj; + let service: PrometheusMetricsService; + + beforeEach(() => { + jasmine.clock().install(); + jasmine.clock().mockDate(new Date(1557705600000)); + prometheusDriverClient = jasmine.createSpyObj( + 'prometheusDriverClient', ['rangeQuery']); + + service = + new PrometheusMetricsService(prometheusDriverClient, undefined); + }); + + // Iterate over all methods since they have the same behavior + methods.forEach((method) => { + describe(method, async () => { + it('Empty return', async () => { + prometheusDriverClient.rangeQuery.withArgs( + queries[method], + Date.now() - 5 * 60 * 1000, + Date.now(), + 10 + ).and.returnValue(Promise.resolve(emptyDataSet)); + + const emptyResult = await service[method](Interval.Last5m); + expect(emptyResult).toEqual(Array.of()); + }); + + it('One instance', async () => { + prometheusDriverClient.rangeQuery.withArgs( + queries[method], + Date.now() - 5 * 60 * 1000, + Date.now(), + 10 + ).and.returnValue(Promise.resolve(singleInstanceDataSet)); + + const singleInstanceResult = await service[method](Interval.Last5m); + expect(singleInstanceResult).toEqual(Array.of({ + timestamp: fixedDate / 1000, + value: 0.955, + label: "instance=one" + })); + }); + + it('Multiple instances', async () => { + prometheusDriverClient.rangeQuery.withArgs( + queries[method], + Date.now() - 5 * 60 * 1000, + Date.now(), + 10 + ).and.returnValue(Promise.resolve(multipleInstancesDataSet)); + + const singleInstanceResult = await service[method](Interval.Last5m); + expect(singleInstanceResult).toEqual( + Array.of({ + timestamp: fixedDate / 1000, + value: 0.010, + label: "instance=one" + }, + { + timestamp: fixedDate / 1000, + value: 0.020, + label: "instance=two" + }, + { + timestamp: fixedDate / 1000, + value: 0.030, + label: "instance=three" + }) + ); + }); + }); + }); + + afterEach(() => { + jasmine.clock().uninstall(); + }); +}); diff --git a/dashboard/app/server.ts b/dashboard/app/server.ts index ab17a22..c88e9a5 100644 --- a/dashboard/app/server.ts +++ b/dashboard/app/server.ts @@ -8,6 +8,8 @@ import {DefaultApi} from './clients/profile_controller'; import {WorkgroupApi} from './api_workgroup'; import {KubernetesService} from './k8s_service'; import {getMetricsService} from './metrics_service_factory'; +import {PrometheusMetricsService} from "./prometheus_metrics_service"; +import {PrometheusDriver} from "prometheus-query"; const isProduction = process.env.NODE_ENV === 'production'; const codeEnvironment = isProduction?'production':'development'; @@ -29,6 +31,8 @@ const { USERID_HEADER = 'X-Goog-Authenticated-User-Email', USERID_PREFIX = 'accounts.google.com:', REGISTRATION_FLOW = "true", + PROMETHEUS_URL = undefined, + METRICS_DASHBOARD = undefined, } = process.env; @@ -41,7 +45,11 @@ async function main() { const app: express.Application = express(); const k8sService = new KubernetesService(new KubeConfig()); - const metricsService = await getMetricsService(k8sService); + + const metricsService = PROMETHEUS_URL + ? new PrometheusMetricsService(new PrometheusDriver({ endpoint: PROMETHEUS_URL }), METRICS_DASHBOARD) + : await getMetricsService(k8sService); + console.info(`Using Profiles service at ${profilesServiceUrl}`); const profilesService = new DefaultApi(profilesServiceUrl); diff --git a/dashboard/app/stackdriver_metrics_service.ts b/dashboard/app/stackdriver_metrics_service.ts index a012942..18a545a 100644 --- a/dashboard/app/stackdriver_metrics_service.ts +++ b/dashboard/app/stackdriver_metrics_service.ts @@ -1,7 +1,7 @@ import * as monitoring from '@google-cloud/monitoring'; import fetch from 'node-fetch'; -import {Interval, MetricsService, TimeSeriesPoint} from './metrics_service'; +import {Interval, MetricsInfo, MetricsService, TimeSeriesPoint} from './metrics_service'; const CLUSTER_NAME_URL = 'http://metadata.google.internal/computeMetadata/v1/instance/attributes/cluster-name'; @@ -194,4 +194,11 @@ export class StackdriverMetricsService implements MetricsService { } return this.clusterName; } + + getChartsLink(): MetricsInfo { + return { + resourceChartsLink: `https://app.google.stackdriver.com/kubernetes?project=${this.projectId}`, + resourceChartsLinkText: 'View in Stackdriver' + }; + } } diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json index 67401b6..60e1301 100644 --- a/dashboard/package-lock.json +++ b/dashboard/package-lock.json @@ -123,6 +123,12 @@ "lodash": "^4.17.13" } }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, "@babel/helper-explode-assignable-expression": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", @@ -262,6 +268,12 @@ "@babel/types": "^7.4.4" } }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true + }, "@babel/helper-validator-identifier": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", @@ -846,40 +858,133 @@ } }, "@babel/traverse": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.2.tgz", - "integrity": "sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.2", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.6.2", - "@babel/types": "^7.6.0", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" + "globals": "^11.1.0" }, "dependencies": { "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "requires": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + } + }, + "@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "requires": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -1061,6 +1166,45 @@ } } }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "@kubernetes/client-node": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/@kubernetes/client-node/-/client-node-0.8.2.tgz", @@ -2503,6 +2647,14 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -2809,6 +2961,15 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bluebird": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.0.tgz", @@ -3203,28 +3364,21 @@ "dev": true }, "chart.js": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.8.0.tgz", - "integrity": "sha512-Di3wUL4BFvqI5FB5K26aQ+hvWh8wnP9A3DWGvXHVkO13D3DSnaSsdZx29cXlEsYKVkn1E2az+ZYFS4t0zi8x0w==", + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", + "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", "requires": { "chartjs-color": "^2.1.0", "moment": "^2.10.2" } }, "chartjs-color": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.3.0.tgz", - "integrity": "sha512-hEvVheqczsoHD+fZ+tfPUE+1+RbV6b+eksp2LwAhwRTVXEjCSEavvk+Hg3H6SZfGlPh/UfmWKGIvZbtobOEm3g==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", + "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", "requires": { "chartjs-color-string": "^0.6.0", - "color-convert": "^0.5.3" - }, - "dependencies": { - "color-convert": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", - "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" - } + "color-convert": "^1.9.3" } }, "chartjs-color-string": { @@ -3436,7 +3590,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -5147,6 +5300,12 @@ "schema-utils": "^1.0.0" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", @@ -5242,8 +5401,7 @@ "follow-redirects": { "version": "1.14.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", - "dev": true + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" }, "for-in": { "version": "1.0.2", @@ -5379,11 +5537,10 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true }, "function-bind": { "version": "1.1.1", @@ -8140,9 +8297,9 @@ } }, "moment": { - "version": "2.29.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", - "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, "move-concurrently": { "version": "1.0.1", @@ -8189,8 +8346,7 @@ "version": "2.13.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", - "dev": true, - "optional": true + "dev": true }, "nanomatch": { "version": "1.2.13", @@ -8442,551 +8598,13 @@ } }, "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, - "optional": true, "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } + "bindings": "^1.5.0", + "nan": "^2.12.1" } }, "is-binary-path": { @@ -9939,6 +9557,14 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "prometheus-query": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prometheus-query/-/prometheus-query-3.3.2.tgz", + "integrity": "sha512-xNgDjDdueiTkA3sY9CJPLa4OgGGoH1ug+TPq3aYY6hnhN7nq1ykP9UmciWnMTYCc178eQ3yesG4HFsRg72CgOg==", + "requires": { + "axios": "^0.26.1" + } + }, "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", @@ -11251,9 +10877,9 @@ "dev": true }, "socket.io-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz", - "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz", + "integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==", "dev": true, "requires": { "@socket.io/component-emitter": "~3.1.0", @@ -12686,551 +12312,13 @@ } }, "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, - "optional": true, "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } + "bindings": "^1.5.0", + "nan": "^2.12.1" } }, "is-binary-path": { @@ -13673,551 +12761,13 @@ } }, "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, - "optional": true, "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } + "bindings": "^1.5.0", + "nan": "^2.12.1" } }, "is-binary-path": { diff --git a/dashboard/package.json b/dashboard/package.json index 2cceeaf..b0d1e75 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -67,10 +67,11 @@ "@types/dotenv": "^6.1.1", "@vaadin/vaadin-grid": "^5.4.9", "@webcomponents/webcomponentsjs": "^2.3.0", - "chart.js": "^2.8.0", + "chart.js": "^2.9.4", "chartjs-plugin-crosshair": "^1.1.4", "express": "^4.17.1", "node-fetch": "^2.6.7", + "prometheus-query": "^3.3.2", "web-animations-js": "^2.3.2" }, "devDependencies": { diff --git a/dashboard/public/components/dashboard-view.js b/dashboard/public/components/dashboard-view.js index dfbe320..b3ea528 100644 --- a/dashboard/public/components/dashboard-view.js +++ b/dashboard/public/components/dashboard-view.js @@ -40,6 +40,7 @@ export class DashboardView extends utilitiesMixin(PolymerElement) { observer: '_namespaceChanged', }, platformDetails: Object, + metrics: Object, platformInfo: { type: Object, observer: '_platformInfoChanged', diff --git a/dashboard/public/components/dashboard-view.pug b/dashboard/public/components/dashboard-view.pug index 39f7154..a367fde 100644 --- a/dashboard/public/components/dashboard-view.pug +++ b/dashboard/public/components/dashboard-view.pug @@ -9,15 +9,15 @@ div#grid .header [[item.text]] aside(secondary) [[item.desc]] paper-ripple - template(is='dom-if', if='[[platformDetails.resourceChartsLink]]') + template(is='dom-if', if='[[metrics.resourceChartsLinkText]]') resource-chart(header-text='Cluster CPU Utilization', metric='cpu', interval='Last60m', - external-link='[[platformDetails.resourceChartsLink]]', - external-link-text='[[platformDetails.resourceChartsLinkText]]') + external-link='[[metrics.resourceChartsLink]]', + external-link-text='[[metrics.resourceChartsLinkText]]') resource-chart(header-text='Pod CPU Utilization', metric='podcpu', interval='Last60m', - external-link='[[platformDetails.resourceChartsLink]]' - external-link-text='[[platformDetails.resourceChartsLinkText]]') + external-link='[[metrics.resourceChartsLink]]' + external-link-text='[[metrics.resourceChartsLinkText]]') .column notebooks-card(namespace='[[namespace]]') pipelines-card(heading='Recent Pipelines', artifact-type='pipelines', namespace='[[namespace]]') diff --git a/dashboard/public/components/dashboard-view_test.js b/dashboard/public/components/dashboard-view_test.js index fff8045..a24a0e2 100644 --- a/dashboard/public/components/dashboard-view_test.js +++ b/dashboard/public/components/dashboard-view_test.js @@ -78,6 +78,11 @@ describe('Dashboard View', () => { 'https://console.cloud.google.com/dm/deployments?project=test-project', 'https://console.cloud.google.com/kubernetes/list?project=test-project', ]); + }); + + it('Show charts when metrics not empty', () => { + dashboardView.metrics = {resourceChartsLinkText: 'dummy'}; + flush(); expect(dashboardView.shadowRoot.querySelectorAll('resource-chart') .length).toBe(2); }); diff --git a/dashboard/public/components/main-page.css b/dashboard/public/components/main-page.css index e13ca3e..9c03ee5 100644 --- a/dashboard/public/components/main-page.css +++ b/dashboard/public/components/main-page.css @@ -4,7 +4,7 @@ :host { @apply --layout-vertical; - --accent-color: #ff6e42; + --accent-color: #007dfc; --primary-background-color: #0a3b71; --sidebar-default-color: rgba(255, 255, 255, 0.5); --divider-color: #dadce0; @@ -27,6 +27,18 @@ overflow: auto; } +.scrollable::-webkit-scrollbar { + -webkit-appearance: none; + width: 7px; + height: 7px; +} + +.scrollable::-webkit-scrollbar-thumb { + border-radius: 4px; + background-color: rgba(238, 238, 239, 0.5); + box-shadow: 0 0 1px rgba(255,255,255,.5); +} + #MainDrawer { color: white; --app-drawer-content-container: { diff --git a/dashboard/public/components/main-page.js b/dashboard/public/components/main-page.js index 3238903..098888e 100644 --- a/dashboard/public/components/main-page.js +++ b/dashboard/public/components/main-page.js @@ -90,6 +90,7 @@ export class MainPage extends utilitiesMixin(PolymerElement) { dashVersion: {type: String, value: VERSION}, logoutUrl: {type: String, value: '/logout'}, platformInfo: Object, + metrics: Object, inIframe: {type: Boolean, value: false, readOnly: true}, hideTabs: {type: Boolean, value: false, readOnly: true}, hideSidebar: {type: Boolean, value: false, readOnly: true}, diff --git a/dashboard/public/components/main-page.pug b/dashboard/public/components/main-page.pug index cf2df80..bd3a2ba 100644 --- a/dashboard/public/components/main-page.pug +++ b/dashboard/public/components/main-page.pug @@ -1,5 +1,7 @@ iron-ajax(auto, url='/api/workgroup/exists', handle-as='json', on-response='_onHasWorkgroupResponse', on-error='_onHasWorkgroupError', loading='{{pageLoading}}') +iron-ajax(auto, url='/api/metrics', handle-as='json', + last-response='{{metrics}}', loading='{{pageLoading}}') iron-ajax(auto, url='/api/dashboard-links', handle-as='json', on-response='_onHasDashboardLinksResponse', on-error='_onHasDashboardLinksError', loading='{{pageLoading}}') iron-ajax#envInfo(auto='[[_shouldFetchEnv]]', url='/api/workgroup/env-info', handle-as='json', @@ -72,7 +74,7 @@ app-drawer-layout.flex(narrow='{{narrowMode}}', query-params='{{queryParams}}', route='{{route}}', namespaces='[[namespaces]]', selected='{{namespace}}', hides, hidden$='[[hideNamespaces]]' - all-namespaces='[[allNamespaces]]', + all-namespaces='[[allNamespaces]]', user='[[user]]') footer#User-Badge logout-button(logout-url='[[logoutUrl]]') @@ -88,7 +90,7 @@ app-drawer-layout.flex(narrow='{{narrowMode}}', exit-animation='fade-out-animation') neon-animatable(page='dashboard') dashboard-view(namespace='[[queryParams.ns]]', - platform-info='[[platformInfo]]', quick-links='[[quickLinks]]', documentation-items='[[documentationItems]]') + platform-info='[[platformInfo]]', quick-links='[[quickLinks]]', documentation-items='[[documentationItems]]' metrics='[[metrics]]') neon-animatable(page='activity') activity-view(namespace='[[queryParams.ns]]') neon-animatable(page='manage-users') diff --git a/dashboard/public/components/manage-users-view.js b/dashboard/public/components/manage-users-view.js index 4fb7481..44c60ce 100644 --- a/dashboard/public/components/manage-users-view.js +++ b/dashboard/public/components/manage-users-view.js @@ -17,6 +17,7 @@ import './resources/md2-input/md2-input.js'; import css from './manage-users-view.css'; import template from './manage-users-view.pug'; import utilitiesMixin from './utilities-mixin.js'; +import {ALL_NAMESPACES} from './namespace-selector'; export class ManageUsersView extends utilitiesMixin(PolymerElement) { static get template() { @@ -60,8 +61,10 @@ export class ManageUsersView extends utilitiesMixin(PolymerElement) { ]; if (ns.length <= 1) return arr; const otherNamespaces = namespaces - .filter((n) => n != ownedNamespace) + .filter((n) => n != ownedNamespace + && n.namespace !== ALL_NAMESPACES) .map((i) => i.namespace).join(', '); + if (!otherNamespaces.length) return arr; arr.push( [otherNamespaces, 'Contributor'], ); diff --git a/dashboard/public/components/pipelines-card.js b/dashboard/public/components/pipelines-card.js index c917bb2..2809ba6 100644 --- a/dashboard/public/components/pipelines-card.js +++ b/dashboard/public/components/pipelines-card.js @@ -96,7 +96,6 @@ export class PipelinesCard extends utilitiesMixin(PolymerElement) { */ _getListPipelinesUrl(artifactType, namespace) { if (!VALID_ARTIFACT_TYPES.has(artifactType)) return null; - if (namespace === undefined) return null; let link = `/pipeline/apis/v1beta1/${artifactType}?` + 'page_size=5&sort_by=created_at%20desc'; if (artifactType === RUNS) { diff --git a/dashboard/public/components/resource-chart.js b/dashboard/public/components/resource-chart.js index 3eb1e6d..e7965ae 100644 --- a/dashboard/public/components/resource-chart.js +++ b/dashboard/public/components/resource-chart.js @@ -118,15 +118,17 @@ class ResourceChart extends PolymerElement { - + `]); } diff --git a/dashboard/public/components/resources/cloud-platform-data.js b/dashboard/public/components/resources/cloud-platform-data.js index 0686618..7887a4d 100644 --- a/dashboard/public/components/resources/cloud-platform-data.js +++ b/dashboard/public/components/resources/cloud-platform-data.js @@ -39,7 +39,5 @@ export function getGCPData(project) { title: 'Google Cloud Platform', logo: '/assets/gcp-logo.png', name: 'GCP', - resourceChartsLink: `https://app.google.stackdriver.com/kubernetes?project=${project}`, - resourceChartsLinkText: 'View in Stackdriver', }; }