mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Store prometheus metadata for clusters based on metrics requests
Signed-off-by: Lauri Nevala <lauri.nevala@gmail.com>
This commit is contained in:
parent
04517148c0
commit
2e568d3413
@ -21,7 +21,13 @@ export interface ClusterIconUpload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ClusterMetadata {
|
export interface ClusterMetadata {
|
||||||
[key: string]: string | number | boolean;
|
[key: string]: string | number | boolean | object;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ClusterPrometheusMetadata = {
|
||||||
|
success?: boolean;
|
||||||
|
provider?: string;
|
||||||
|
autoDetected?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClusterStoreModel {
|
export interface ClusterStoreModel {
|
||||||
|
|||||||
@ -139,6 +139,7 @@ export class Cluster implements ClusterModel, ClusterState {
|
|||||||
if (ipcMain) {
|
if (ipcMain) {
|
||||||
this.eventDisposers.push(
|
this.eventDisposers.push(
|
||||||
reaction(() => this.getState(), () => this.pushState()),
|
reaction(() => this.getState(), () => this.pushState()),
|
||||||
|
reaction(() => this.preferences, () => this.contextHandler.setupPrometheus(this.preferences)),
|
||||||
() => {
|
() => {
|
||||||
clearInterval(refreshTimer)
|
clearInterval(refreshTimer)
|
||||||
clearInterval(refreshMetadataTimer)
|
clearInterval(refreshMetadataTimer)
|
||||||
|
|||||||
@ -22,7 +22,7 @@ export class ContextHandler {
|
|||||||
this.setupPrometheus(cluster.preferences);
|
this.setupPrometheus(cluster.preferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setupPrometheus(preferences: ClusterPreferences = {}) {
|
public setupPrometheus(preferences: ClusterPreferences = {}) {
|
||||||
this.prometheusProvider = preferences.prometheusProvider?.type;
|
this.prometheusProvider = preferences.prometheusProvider?.type;
|
||||||
this.prometheusPath = null;
|
this.prometheusPath = null;
|
||||||
if (preferences.prometheus) {
|
if (preferences.prometheus) {
|
||||||
@ -32,13 +32,18 @@ export class ContextHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async resolvePrometheusPath(): Promise<string> {
|
protected async resolvePrometheusPath(): Promise<string> {
|
||||||
const { service, namespace, port } = await this.getPrometheusService()
|
const prometheusService = await this.getPrometheusService()
|
||||||
|
if (!prometheusService) return null
|
||||||
|
const { service, namespace, port } = prometheusService
|
||||||
return `${namespace}/services/${service}:${port}`
|
return `${namespace}/services/${service}:${port}`
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPrometheusProvider() {
|
async getPrometheusProvider() {
|
||||||
if (!this.prometheusProvider) {
|
if (!this.prometheusProvider) {
|
||||||
const service = await this.getPrometheusService()
|
const service = await this.getPrometheusService()
|
||||||
|
if (!service) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
logger.info(`using ${service.id} as prometheus provider`)
|
logger.info(`using ${service.id} as prometheus provider`)
|
||||||
this.prometheusProvider = service.id
|
this.prometheusProvider = service.id
|
||||||
}
|
}
|
||||||
@ -52,13 +57,7 @@ export class ContextHandler {
|
|||||||
return await provider.getPrometheusService(apiClient)
|
return await provider.getPrometheusService(apiClient)
|
||||||
})
|
})
|
||||||
const resolvedPrometheusServices = await Promise.all(prometheusPromises)
|
const resolvedPrometheusServices = await Promise.all(prometheusPromises)
|
||||||
const service = resolvedPrometheusServices.filter(n => n)[0];
|
return resolvedPrometheusServices.filter(n => n)[0];
|
||||||
return service || {
|
|
||||||
id: "lens",
|
|
||||||
namespace: "lens-metrics",
|
|
||||||
service: "prometheus",
|
|
||||||
port: 80
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPrometheusPath(): Promise<string> {
|
async getPrometheusPath(): Promise<string> {
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { LensApiRequest } from "../router"
|
|||||||
import { LensApi } from "../lens-api"
|
import { LensApi } from "../lens-api"
|
||||||
import { Cluster } from "../cluster"
|
import { Cluster } from "../cluster"
|
||||||
import _ from "lodash"
|
import _ from "lodash"
|
||||||
|
import { ClusterPrometheusMetadata } from "../../common/cluster-store"
|
||||||
|
|
||||||
export type IMetricsQuery = string | string[] | {
|
export type IMetricsQuery = string | string[] | {
|
||||||
[metricName: string]: string;
|
[metricName: string]: string;
|
||||||
@ -22,11 +23,8 @@ async function loadMetrics(promQueries: string[], cluster: Cluster, prometheusPa
|
|||||||
try {
|
try {
|
||||||
return await cluster.getMetrics(prometheusPath, { query, ...queryParams })
|
return await cluster.getMetrics(prometheusPath, { query, ...queryParams })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (lastAttempt || error?.statusCode === 404) {
|
if (lastAttempt || (error?.statusCode >= 400 && error?.statusCode < 500)) {
|
||||||
return {
|
throw new Error("Metrics not available");
|
||||||
status: error.toString(),
|
|
||||||
data: { result: [] },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await new Promise(resolve => setTimeout(resolve, (attempt + 1) * 1000)); // add delay before repeating request
|
await new Promise(resolve => setTimeout(resolve, (attempt + 1) * 1000)); // add delay before repeating request
|
||||||
@ -36,20 +34,25 @@ async function loadMetrics(promQueries: string[], cluster: Cluster, prometheusPa
|
|||||||
|
|
||||||
return loaders.get(query) ?? loaders.set(query, loadMetricHelper()).get(query)
|
return loaders.get(query) ?? loaders.set(query, loadMetricHelper()).get(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(queries.map(loadMetric))
|
return Promise.all(queries.map(loadMetric))
|
||||||
}
|
}
|
||||||
|
|
||||||
class MetricsRoute extends LensApi {
|
class MetricsRoute extends LensApi {
|
||||||
async routeMetrics({ response, cluster, payload, query }: LensApiRequest) {
|
async routeMetrics({ response, cluster, payload, query }: LensApiRequest) {
|
||||||
const queryParams: IMetricsQuery = Object.fromEntries(query.entries())
|
const queryParams: IMetricsQuery = Object.fromEntries(query.entries())
|
||||||
|
const prometheusMetadata: ClusterPrometheusMetadata = {}
|
||||||
try {
|
try {
|
||||||
const [prometheusPath, prometheusProvider] = await Promise.all([
|
const [prometheusPath, prometheusProvider] = await Promise.all([
|
||||||
cluster.contextHandler.getPrometheusPath(),
|
cluster.contextHandler.getPrometheusPath(),
|
||||||
cluster.contextHandler.getPrometheusProvider()
|
cluster.contextHandler.getPrometheusProvider()
|
||||||
])
|
])
|
||||||
|
prometheusMetadata["provider"] = prometheusProvider?.id
|
||||||
|
prometheusMetadata["autoDetected"] = !cluster.preferences.prometheusProvider?.type
|
||||||
|
if (!prometheusPath) {
|
||||||
|
prometheusMetadata["success"] = false
|
||||||
|
this.respondJson(response, {})
|
||||||
|
return
|
||||||
|
}
|
||||||
// return data in same structure as query
|
// return data in same structure as query
|
||||||
if (typeof payload === "string") {
|
if (typeof payload === "string") {
|
||||||
const [data] = await loadMetrics([payload], cluster, prometheusPath, queryParams)
|
const [data] = await loadMetrics([payload], cluster, prometheusPath, queryParams)
|
||||||
@ -65,8 +68,12 @@ class MetricsRoute extends LensApi {
|
|||||||
const data = Object.fromEntries(Object.keys(payload).map((metricName, i) => [metricName, result[i]]))
|
const data = Object.fromEntries(Object.keys(payload).map((metricName, i) => [metricName, result[i]]))
|
||||||
this.respondJson(response, data)
|
this.respondJson(response, data)
|
||||||
}
|
}
|
||||||
|
prometheusMetadata["success"] = true
|
||||||
} catch {
|
} catch {
|
||||||
|
prometheusMetadata["success"] = false
|
||||||
this.respondJson(response, {})
|
this.respondJson(response, {})
|
||||||
|
} finally {
|
||||||
|
cluster.metadata["prometheus"] = prometheusMetadata
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user