diff --git a/open-lens/package.json b/open-lens/package.json index 0a2cea4562..838c37f897 100644 --- a/open-lens/package.json +++ b/open-lens/package.json @@ -206,6 +206,7 @@ "@k8slens/messaging-for-renderer": "^1.0.0", "@k8slens/metrics": "^6.5.0", "@k8slens/node-fetch": "^6.5.0", + "@k8slens/prometheus": "^1.0.0", "@k8slens/random": "^1.0.0", "@k8slens/react-application": "^1.0.0", "@k8slens/resizing-anchor": "^1.0.0", diff --git a/open-lens/src/main/index.ts b/open-lens/src/main/index.ts index 58592cc42b..8a90aaca46 100644 --- a/open-lens/src/main/index.ts +++ b/open-lens/src/main/index.ts @@ -14,6 +14,7 @@ import { messagingFeatureForMain } from "@k8slens/messaging-for-main"; import { loggerFeature } from "@k8slens/logger"; import { randomFeature } from "@k8slens/random"; import { kubeApiSpecificsFeature } from "@k8slens/kube-api-specifics"; +import { prometheusFeature } from "@k8slens/prometheus"; const environment = "main"; @@ -26,12 +27,10 @@ registerMobX(di); runInAction(() => { registerLensCore(di, environment); - registerFeature(di, - loggerFeature, - ); - registerFeature( di, + loggerFeature, + prometheusFeature, applicationFeature, applicationFeatureForElectronMain, messagingFeatureForMain, diff --git a/package-lock.json b/package-lock.json index 6f89bb48e6..eb92446d12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3831,6 +3831,10 @@ "resolved": "packages/node-fetch", "link": true }, + "node_modules/@k8slens/prometheus": { + "resolved": "packages/technical-features/prometheus", + "link": true + }, "node_modules/@k8slens/random": { "resolved": "packages/random-id", "link": true @@ -33993,6 +33997,7 @@ "@k8slens/messaging-for-renderer": "^1.0.0", "@k8slens/metrics": "^6.5.0", "@k8slens/node-fetch": "^6.5.0", + "@k8slens/prometheus": "^1.0.0", "@k8slens/random": "^1.0.0", "@k8slens/react-application": "^1.0.0", "@k8slens/resizing-anchor": "^1.0.0", @@ -34335,6 +34340,7 @@ "@k8slens/messaging-for-renderer": "^1.0.0-alpha.1", "@k8slens/metrics": "^6.5.0-alpha.7", "@k8slens/node-fetch": "^6.5.0-alpha.3", + "@k8slens/prometheus": "^1.0.0", "@k8slens/random": "^1.0.0", "@k8slens/react-application": "^1.0.0-alpha.5", "@k8slens/resizing-anchor": "^1.0.0-alpha.5", @@ -35248,6 +35254,28 @@ "url": "https://opencollective.com/node-fetch" } }, + "packages/prometheus": { + "name": "@k8slens/prometheus", + "version": "1.0.0", + "extraneous": true, + "license": "MIT", + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.3", + "@k8slens/jest": "^6.5.0-alpha.5", + "@k8slens/typescript": "^6.5.0-alpha.3", + "@k8slens/webpack": "^6.5.0-alpha.9" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.2", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/utilities": "^1.0.0-alpha.7", + "@kubernetes/client-node": "^0.18.1", + "@ogre-tools/fp": "^16.1.0", + "@ogre-tools/injectable": "^16.1.0", + "@ogre-tools/injectable-extension-for-auto-registration": "^16.1.0", + "@ogre-tools/injectable-extension-for-mobx": "^16.1.0" + } + }, "packages/random-id": { "name": "@k8slens/random", "version": "1.0.0", @@ -35517,6 +35545,27 @@ "mobx": "^6.9.0" } }, + "packages/technical-features/prometheus": { + "name": "@k8slens/prometheus", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.3", + "@k8slens/jest": "^6.5.0-alpha.5", + "@k8slens/typescript": "^6.5.0-alpha.3", + "@k8slens/webpack": "^6.5.0-alpha.9" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.2", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/utilities": "^1.0.0-alpha.7", + "@kubernetes/client-node": "^0.18.1", + "@ogre-tools/fp": "^17.2.0", + "@ogre-tools/injectable": "^17.2.0", + "@ogre-tools/injectable-extension-for-auto-registration": "^17.2.0", + "@ogre-tools/injectable-extension-for-mobx": "^17.2.0" + } + }, "packages/technical-features/react-application": { "name": "@k8slens/react-application", "version": "1.0.0", diff --git a/packages/core/package.json b/packages/core/package.json index 919de6d364..47538264d4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -228,6 +228,7 @@ "@k8slens/messaging-for-renderer": "^1.0.0-alpha.1", "@k8slens/metrics": "^6.5.0-alpha.7", "@k8slens/node-fetch": "^6.5.0-alpha.3", + "@k8slens/prometheus": "^1.0.0", "@k8slens/react-application": "^1.0.0-alpha.5", "@k8slens/random": "^1.0.0", "@k8slens/resizing-anchor": "^1.0.0-alpha.5", diff --git a/packages/core/src/main/__test__/prometheus-handler.test.ts b/packages/core/src/main/__test__/prometheus-handler.test.ts index df0e1b37c9..84f0f154cb 100644 --- a/packages/core/src/main/__test__/prometheus-handler.test.ts +++ b/packages/core/src/main/__test__/prometheus-handler.test.ts @@ -7,8 +7,8 @@ import { getDiForUnitTesting } from "../getDiForUnitTesting"; import { Cluster } from "../../common/cluster/cluster"; import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; -import type { PrometheusProvider } from "../prometheus/provider"; -import { prometheusProviderInjectionToken } from "../prometheus/provider"; +import type { PrometheusProvider } from "@k8slens/prometheus"; +import { prometheusProviderInjectionToken } from "@k8slens/prometheus"; import { runInAction } from "mobx"; import prometheusHandlerInjectable from "../cluster/prometheus-handler/prometheus-handler.injectable"; import directoryForTempInjectable from "../../common/app-paths/directory-for-temp/directory-for-temp.injectable"; diff --git a/packages/core/src/main/cluster/prometheus-handler/prometheus-handler.ts b/packages/core/src/main/cluster/prometheus-handler/prometheus-handler.ts index 81c3901750..142a69bb07 100644 --- a/packages/core/src/main/cluster/prometheus-handler/prometheus-handler.ts +++ b/packages/core/src/main/cluster/prometheus-handler/prometheus-handler.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { PrometheusProvider, PrometheusService } from "../../prometheus/provider"; +import type { PrometheusProvider, PrometheusService } from "@k8slens/prometheus"; import type { ClusterPrometheusPreferences } from "../../../common/cluster-types"; import type { Cluster } from "../../../common/cluster/cluster"; import { CoreV1Api } from "@kubernetes/client-node"; diff --git a/packages/core/src/main/prometheus/get-by-kind.injectable.ts b/packages/core/src/main/prometheus/get-by-kind.injectable.ts index 93d7567f6e..3930c77e62 100644 --- a/packages/core/src/main/prometheus/get-by-kind.injectable.ts +++ b/packages/core/src/main/prometheus/get-by-kind.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { matches } from "lodash/fp"; -import type { PrometheusProvider } from "./provider"; +import type { PrometheusProvider } from "@k8slens/prometheus"; import prometheusProvidersInjectable from "./providers.injectable"; export type GetPrometheusProviderByKind = (kind: string) => PrometheusProvider; diff --git a/packages/core/src/main/prometheus/providers.injectable.ts b/packages/core/src/main/prometheus/providers.injectable.ts index 73fe2dfe50..43ec48d769 100644 --- a/packages/core/src/main/prometheus/providers.injectable.ts +++ b/packages/core/src/main/prometheus/providers.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx"; -import { prometheusProviderInjectionToken } from "./provider"; +import { prometheusProviderInjectionToken } from "@k8slens/prometheus"; const prometheusProvidersInjectable = getInjectable({ id: "prometheus-providers", diff --git a/packages/technical-features/prometheus/.eslintrc.js b/packages/technical-features/prometheus/.eslintrc.js new file mode 100644 index 0000000000..f404cf0ace --- /dev/null +++ b/packages/technical-features/prometheus/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + extends: "@k8slens/eslint-config/eslint", + parserOptions: { + project: "./tsconfig.json", + }, + }; diff --git a/packages/technical-features/prometheus/.prettierrc b/packages/technical-features/prometheus/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/technical-features/prometheus/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/technical-features/prometheus/CHANGELOG.md b/packages/technical-features/prometheus/CHANGELOG.md new file mode 100644 index 0000000000..e4d87c4d45 --- /dev/null +++ b/packages/technical-features/prometheus/CHANGELOG.md @@ -0,0 +1,4 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/technical-features/prometheus/index.ts b/packages/technical-features/prometheus/index.ts new file mode 100644 index 0000000000..426758e06e --- /dev/null +++ b/packages/technical-features/prometheus/index.ts @@ -0,0 +1,7 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +export { prometheusFeature } from "./src/feature"; +export * from "./src/provider"; diff --git a/packages/technical-features/prometheus/jest.config.js b/packages/technical-features/prometheus/jest.config.js new file mode 100644 index 0000000000..c6074967eb --- /dev/null +++ b/packages/technical-features/prometheus/jest.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; diff --git a/packages/technical-features/prometheus/package.json b/packages/technical-features/prometheus/package.json new file mode 100644 index 0000000000..f6c7ff26d4 --- /dev/null +++ b/packages/technical-features/prometheus/package.json @@ -0,0 +1,50 @@ +{ + "name": "@k8slens/prometheus", + "private": false, + "version": "1.0.0", + "description": "Prometheus support for Lens", + "type": "commonjs", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/lensapp/lens.git" + }, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "author": { + "name": "OpenLens Authors", + "email": "info@k8slens.dev" + }, + "license": "MIT", + "homepage": "https://github.com/lensapp/lens", + "scripts": { + "build": "lens-webpack-build", + "clean": "rimraf dist/", + "dev": "webpack --mode=development --watch", + "test": "jest --coverage --runInBand", + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.2", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/utilities": "^1.0.0-alpha.7", + "@kubernetes/client-node": "^0.18.1", + "@ogre-tools/fp": "^17.2.0", + "@ogre-tools/injectable": "^17.2.0", + "@ogre-tools/injectable-extension-for-auto-registration": "^17.2.0", + "@ogre-tools/injectable-extension-for-mobx": "^17.2.0" + }, + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.3", + "@k8slens/jest": "^6.5.0-alpha.5", + "@k8slens/typescript": "^6.5.0-alpha.3", + "@k8slens/webpack": "^6.5.0-alpha.9" + } +} diff --git a/packages/technical-features/prometheus/src/feature.ts b/packages/technical-features/prometheus/src/feature.ts new file mode 100644 index 0000000000..1a6b24eaa7 --- /dev/null +++ b/packages/technical-features/prometheus/src/feature.ts @@ -0,0 +1,17 @@ +import { getFeature } from "@k8slens/feature-core"; +import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; +import { applicationFeature } from "@k8slens/application"; + +export const prometheusFeature = getFeature({ + id: "prometheus", + + register: (di) => { + autoRegister({ + di, + targetModule: module, + getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)], + }); + }, + + dependencies: [applicationFeature], +}); diff --git a/packages/core/src/main/prometheus/helm-14-provider.injectable.ts b/packages/technical-features/prometheus/src/helm-14-provider.injectable.ts similarity index 65% rename from packages/core/src/main/prometheus/helm-14-provider.injectable.ts rename to packages/technical-features/prometheus/src/helm-14-provider.injectable.ts index 6cc66c519e..35d55abe7d 100644 --- a/packages/core/src/main/prometheus/helm-14-provider.injectable.ts +++ b/packages/technical-features/prometheus/src/helm-14-provider.injectable.ts @@ -9,15 +9,15 @@ import { getInjectable } from "@ogre-tools/injectable"; const helm14PrometheusProviderInjectable = getInjectable({ id: "helm14-prometheus-provider", - instantiate: () => createPrometheusProvider({ - kind: "helm14", - name: "Helm 14.x", - isConfigurable: true, - getQuery: getLensLikeQueryFor({ rateAccuracy: "5m" }), - getService: (client) => findFirstNamespacedService(client, "app=prometheus,component=server,heritage=Helm"), - }), + instantiate: () => + createPrometheusProvider({ + kind: "helm14", + name: "Helm 14.x", + isConfigurable: true, + getQuery: getLensLikeQueryFor({ rateAccuracy: "5m" }), + getService: (client) => findFirstNamespacedService(client, "app=prometheus,component=server,heritage=Helm"), + }), injectionToken: prometheusProviderInjectionToken, }); export default helm14PrometheusProviderInjectable; - diff --git a/packages/core/src/main/prometheus/helm-provider.injectable.ts b/packages/technical-features/prometheus/src/helm-provider.injectable.ts similarity index 91% rename from packages/core/src/main/prometheus/helm-provider.injectable.ts rename to packages/technical-features/prometheus/src/helm-provider.injectable.ts index 953bd68277..ac6b46d4e4 100644 --- a/packages/core/src/main/prometheus/helm-provider.injectable.ts +++ b/packages/technical-features/prometheus/src/helm-provider.injectable.ts @@ -4,16 +4,25 @@ */ import type { PrometheusProvider } from "./provider"; -import { createPrometheusProvider, bytesSent, findFirstNamespacedService, prometheusProviderInjectionToken } from "./provider"; +import { + createPrometheusProvider, + bytesSent, + findFirstNamespacedService, + prometheusProviderInjectionToken, +} from "./provider"; import { getInjectable } from "@ogre-tools/injectable"; -export const getHelmLikeQueryFor = ({ rateAccuracy }: { rateAccuracy: string }): PrometheusProvider["getQuery"] => ( +export const getHelmLikeQueryFor = + ({ rateAccuracy }: { rateAccuracy: string }): PrometheusProvider["getQuery"] => (opts, queryName) => { - switch(opts.category) { + switch (opts.category) { case "cluster": switch (queryName) { case "memoryUsage": - return `sum(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (component)`.replace(/_bytes/g, `_bytes{node=~"${opts.nodes}"}`); + return `sum(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (component)`.replace( + /_bytes/g, + `_bytes{node=~"${opts.nodes}"}`, + ); case "workloadMemoryUsage": return `sum(container_memory_working_set_bytes{container!="POD",container!="",instance=~"${opts.nodes}"}) by (component)`; case "memoryRequests": @@ -127,20 +136,19 @@ export const getHelmLikeQueryFor = ({ rateAccuracy }: { rateAccuracy: string }): } throw new Error(`Unknown queryName="${queryName}" for category="${opts.category}"`); - } -); + }; const helmPrometheusProviderInjectable = getInjectable({ id: "helm-prometheus-provider", - instantiate: () => createPrometheusProvider({ - kind: "helm", - name: "Helm", - isConfigurable: true, - getQuery: getHelmLikeQueryFor({ rateAccuracy: "5m" }), - getService: (client) => findFirstNamespacedService(client, "app=prometheus,component=server,heritage=Helm"), - }), + instantiate: () => + createPrometheusProvider({ + kind: "helm", + name: "Helm", + isConfigurable: true, + getQuery: getHelmLikeQueryFor({ rateAccuracy: "5m" }), + getService: (client) => findFirstNamespacedService(client, "app=prometheus,component=server,heritage=Helm"), + }), injectionToken: prometheusProviderInjectionToken, }); export default helmPrometheusProviderInjectable; - diff --git a/packages/core/src/main/prometheus/lens-provider.injectable.ts b/packages/technical-features/prometheus/src/lens-provider.injectable.ts similarity index 91% rename from packages/core/src/main/prometheus/lens-provider.injectable.ts rename to packages/technical-features/prometheus/src/lens-provider.injectable.ts index c523c72582..cb8b7bbf5a 100644 --- a/packages/core/src/main/prometheus/lens-provider.injectable.ts +++ b/packages/technical-features/prometheus/src/lens-provider.injectable.ts @@ -3,17 +3,26 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { bytesSent, prometheusProviderInjectionToken, findNamespacedService, createPrometheusProvider } from "./provider"; -import type { PrometheusProvider } from "./provider"; +import { + bytesSent, + prometheusProviderInjectionToken, + findNamespacedService, + createPrometheusProvider, +} from "./provider"; +import type { PrometheusProvider } from "./provider"; import { getInjectable } from "@ogre-tools/injectable"; -export const getLensLikeQueryFor = ({ rateAccuracy }: { rateAccuracy: string }): PrometheusProvider["getQuery"] => ( +export const getLensLikeQueryFor = + ({ rateAccuracy }: { rateAccuracy: string }): PrometheusProvider["getQuery"] => (opts, queryName) => { - switch(opts.category) { + switch (opts.category) { case "cluster": switch (queryName) { case "memoryUsage": - return `sum(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (kubernetes_name)`.replace(/_bytes/g, `_bytes{kubernetes_node=~"${opts.nodes}"}`); + return `sum(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (kubernetes_name)`.replace( + /_bytes/g, + `_bytes{kubernetes_node=~"${opts.nodes}"}`, + ); case "workloadMemoryUsage": return `sum(container_memory_working_set_bytes{container!="POD",container!="",instance=~"${opts.nodes}"}) by (component)`; case "memoryRequests": @@ -127,20 +136,19 @@ export const getLensLikeQueryFor = ({ rateAccuracy }: { rateAccuracy: string }): } throw new Error(`Unknown queryName="${queryName}" for category="${opts.category}"`); - } -); + }; const lensPrometheusProviderInjectable = getInjectable({ id: "lens-prometheus-provider", - instantiate: () => createPrometheusProvider({ - kind: "lens", - name: "Lens", - isConfigurable: false, - getQuery: getLensLikeQueryFor({ rateAccuracy: "1m" }), - getService: (client) => findNamespacedService(client, "prometheus", "lens-metrics"), - }), + instantiate: () => + createPrometheusProvider({ + kind: "lens", + name: "Lens", + isConfigurable: false, + getQuery: getLensLikeQueryFor({ rateAccuracy: "1m" }), + getService: (client) => findNamespacedService(client, "prometheus", "lens-metrics"), + }), injectionToken: prometheusProviderInjectionToken, }); export default lensPrometheusProviderInjectable; - diff --git a/packages/core/src/main/prometheus/operator-provider.injectable.ts.ts b/packages/technical-features/prometheus/src/operator-provider.injectable.ts.ts similarity index 91% rename from packages/core/src/main/prometheus/operator-provider.injectable.ts.ts rename to packages/technical-features/prometheus/src/operator-provider.injectable.ts.ts index 5215f2dff2..d8da7255b6 100644 --- a/packages/core/src/main/prometheus/operator-provider.injectable.ts.ts +++ b/packages/technical-features/prometheus/src/operator-provider.injectable.ts.ts @@ -4,16 +4,25 @@ */ import type { PrometheusProvider } from "./provider"; -import { bytesSent, createPrometheusProvider, findFirstNamespacedService, prometheusProviderInjectionToken } from "./provider"; +import { + bytesSent, + createPrometheusProvider, + findFirstNamespacedService, + prometheusProviderInjectionToken, +} from "./provider"; import { getInjectable } from "@ogre-tools/injectable"; -export const getOperatorLikeQueryFor = ({ rateAccuracy }: { rateAccuracy: string }): PrometheusProvider["getQuery"] => ( +export const getOperatorLikeQueryFor = + ({ rateAccuracy }: { rateAccuracy: string }): PrometheusProvider["getQuery"] => (opts, queryName) => { - switch(opts.category) { + switch (opts.category) { case "cluster": switch (queryName) { case "memoryUsage": - return `sum(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes))`.replace(/_bytes/g, `_bytes * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"}`); + return `sum(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes))`.replace( + /_bytes/g, + `_bytes * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"}`, + ); case "workloadMemoryUsage": return `sum(container_memory_working_set_bytes{container!="", instance=~"${opts.nodes}"}) by (component)`; case "memoryRequests": @@ -127,20 +136,19 @@ export const getOperatorLikeQueryFor = ({ rateAccuracy }: { rateAccuracy: string } throw new Error(`Unknown queryName="${queryName}" for category="${opts.category}"`); - } -); + }; const operatorPrometheusProviderInjectable = getInjectable({ id: "operator-prometheus-provider", - instantiate: () => createPrometheusProvider({ - kind: "operator", - name: "Prometheus Operator", - isConfigurable: true, - getService: (client) => findFirstNamespacedService(client, "operated-prometheus=true"), - getQuery: getOperatorLikeQueryFor({ rateAccuracy: "1m" }), - }), + instantiate: () => + createPrometheusProvider({ + kind: "operator", + name: "Prometheus Operator", + isConfigurable: true, + getService: (client) => findFirstNamespacedService(client, "operated-prometheus=true"), + getQuery: getOperatorLikeQueryFor({ rateAccuracy: "1m" }), + }), injectionToken: prometheusProviderInjectionToken, }); export default operatorPrometheusProviderInjectable; - diff --git a/packages/core/src/main/prometheus/provider.ts b/packages/technical-features/prometheus/src/provider.ts similarity index 73% rename from packages/core/src/main/prometheus/provider.ts rename to packages/technical-features/prometheus/src/provider.ts index 5bd9588a06..ad38958be8 100644 --- a/packages/core/src/main/prometheus/provider.ts +++ b/packages/technical-features/prometheus/src/provider.ts @@ -35,13 +35,16 @@ export interface CreatePrometheusProviderOpts { getService(client: CoreV1Api): Promise; } -export const createPrometheusProvider = ({ getService, ...opts }: CreatePrometheusProviderOpts): PrometheusProvider => ({ +export const createPrometheusProvider = ({ + getService, + ...opts +}: CreatePrometheusProviderOpts): PrometheusProvider => ({ ...opts, getPrometheusService: async (client) => { try { return { kind: opts.kind, - ...await getService(client), + ...(await getService(client)), }; } catch (error) { throw new Error(`Failed to find Prometheus provider for "${opts.name}"`, { cause: error }); @@ -49,10 +52,17 @@ export const createPrometheusProvider = ({ getService, ...opts }: CreatePromethe }, }); -export async function findFirstNamespacedService(client: CoreV1Api, ...selectors: string[]): Promise { +export async function findFirstNamespacedService( + client: CoreV1Api, + ...selectors: string[] +): Promise { try { for (const selector of selectors) { - const { body: { items: [service] }} = await client.listServiceForAllNamespaces(undefined, undefined, undefined, selector); + const { + body: { + items: [service], + }, + } = await client.listServiceForAllNamespaces(undefined, undefined, undefined, selector); if (service?.metadata?.namespace && service.metadata.name && service.spec?.ports) { return { @@ -63,13 +73,19 @@ export async function findFirstNamespacedService(client: CoreV1Api, ...selectors } } } catch (error) { - throw new Error(`Failed to list services in all namespaces: ${isRequestError(error) ? error.response?.body.message : error}`); + throw new Error( + `Failed to list services in all namespaces: ${isRequestError(error) ? error.response?.body.message : error}`, + ); } throw new Error(`No service found from any namespace`); } -export async function findNamespacedService(client: CoreV1Api, name: string, namespace: string): Promise { +export async function findNamespacedService( + client: CoreV1Api, + name: string, + namespace: string, +): Promise { try { const { body: service } = await client.readNamespacedService(name, namespace); @@ -82,8 +98,12 @@ export async function findNamespacedService(client: CoreV1Api, name: string, nam service: service.metadata.name, port: service.spec.ports[0].port, }; - } catch(error) { - throw new Error(`Failed to list services in namespace="${namespace}": ${isRequestError(error) ? error.response?.body.message : error}`); + } catch (error) { + throw new Error( + `Failed to list services in namespace="${namespace}": ${ + isRequestError(error) ? error.response?.body.message : error + }`, + ); } } diff --git a/packages/core/src/main/prometheus/stacklight-provider.injectable.ts b/packages/technical-features/prometheus/src/stacklight-provider.injectable.ts similarity index 91% rename from packages/core/src/main/prometheus/stacklight-provider.injectable.ts rename to packages/technical-features/prometheus/src/stacklight-provider.injectable.ts index ca7a946466..36979d36ea 100644 --- a/packages/core/src/main/prometheus/stacklight-provider.injectable.ts +++ b/packages/technical-features/prometheus/src/stacklight-provider.injectable.ts @@ -4,16 +4,25 @@ */ import type { PrometheusProvider } from "./provider"; -import { bytesSent, createPrometheusProvider, findFirstNamespacedService, prometheusProviderInjectionToken } from "./provider"; +import { + bytesSent, + createPrometheusProvider, + findFirstNamespacedService, + prometheusProviderInjectionToken, +} from "./provider"; import { getInjectable } from "@ogre-tools/injectable"; -export const getStacklightLikeQueryFor = ({ rateAccuracy }: { rateAccuracy: string }): PrometheusProvider["getQuery"] => ( +export const getStacklightLikeQueryFor = + ({ rateAccuracy }: { rateAccuracy: string }): PrometheusProvider["getQuery"] => (opts, queryName) => { - switch(opts.category) { + switch (opts.category) { case "cluster": switch (queryName) { case "memoryUsage": - return `sum(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (kubernetes_name)`.replace(/_bytes/g, `_bytes{node=~"${opts.nodes}"}`); + return `sum(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (kubernetes_name)`.replace( + /_bytes/g, + `_bytes{node=~"${opts.nodes}"}`, + ); case "workloadMemoryUsage": return `sum(container_memory_working_set_bytes{container!="POD",container!="",instance=~"${opts.nodes}"}) by (component)`; case "memoryRequests": @@ -127,20 +136,19 @@ export const getStacklightLikeQueryFor = ({ rateAccuracy }: { rateAccuracy: stri } throw new Error(`Unknown queryName="${queryName}" for category="${opts.category}"`); - } -); + }; const stacklightPrometheusProviderInjectable = getInjectable({ id: "stacklight-prometheus-provider", - instantiate: () => createPrometheusProvider({ - kind: "stacklight", - name: "Stacklight", - isConfigurable: true, - getService: (client) => findFirstNamespacedService(client, "prometheus-server", "stacklight"), - getQuery: getStacklightLikeQueryFor({ rateAccuracy: "1m" }), - }), + instantiate: () => + createPrometheusProvider({ + kind: "stacklight", + name: "Stacklight", + isConfigurable: true, + getService: (client) => findFirstNamespacedService(client, "prometheus-server", "stacklight"), + getQuery: getStacklightLikeQueryFor({ rateAccuracy: "1m" }), + }), injectionToken: prometheusProviderInjectionToken, }); export default stacklightPrometheusProviderInjectable; - diff --git a/packages/technical-features/prometheus/tsconfig.json b/packages/technical-features/prometheus/tsconfig.json new file mode 100644 index 0000000000..2b0f0e5603 --- /dev/null +++ b/packages/technical-features/prometheus/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts"] + } diff --git a/packages/technical-features/prometheus/webpack.config.js b/packages/technical-features/prometheus/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/technical-features/prometheus/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode;