diff --git a/src/common/promql.ts b/src/common/promql.ts index ba59129..d64a4eb 100644 --- a/src/common/promql.ts +++ b/src/common/promql.ts @@ -22,25 +22,6 @@ enum MatchingModifiers { ON = 'on', } -class PromQLMatchingModifier extends PromQLExpression { - - constructor(private modifier: MatchingModifiers, private labels: string[], private left: PromQLExpression) { - super(); - } - - stringify() { - return `${this.left.stringify()} ${this.modifier}(${this.labels.join(', ')}) `; - } - - groupLeft(labels: string[], vectorExpr: PromQLVectorExpression) { - return new PromQLGroupModifier(GroupModifiers.GROUP_LEFT, labels, this, vectorExpr); - } - - groupRight(labels: string[], vectorExpr: PromQLVectorExpression) { - return new PromQLGroupModifier(GroupModifiers.GROUP_RIGHT, labels, this, vectorExpr); - } -} - enum BinaryOperators { ADD = '+', SUBTRACT = '-', @@ -50,9 +31,6 @@ enum BinaryOperators { POW = '^', } - - - export abstract class PromQLVectorExpression extends PromQLExpression { add() { @@ -79,12 +57,12 @@ export abstract class PromQLVectorExpression extends PromQLExpression { return new PromQLBinaryExpression(BinaryOperators.POW, this); } - or(vectorExpr: PromQLVectorExpression) { - return new PromQLLogicalExpression(LogicalOperators.OR, this, vectorExpr); + or() { + return new PromQLLogicalExpression(LogicalOperators.OR, this); } - and(vectorExpr: PromQLVectorExpression) { - return new PromQLLogicalExpression(LogicalOperators.AND, this, vectorExpr); + and() { + return new PromQLLogicalExpression(LogicalOperators.AND, this); } equals(value: number) { @@ -92,6 +70,36 @@ export abstract class PromQLVectorExpression extends PromQLExpression { } } +class PromQLMatchingModifier extends PromQLVectorExpression { + + private right?: PromQLExpression; + + constructor(private modifier: MatchingModifiers, private labels: string[], private left: PromQLExpression) { + super(); + } + + stringify() { + if (this.right) { + return `${this.left.stringify()} ${this.modifier}(${this.labels.join(', ')}) ${this.right.stringify()}`; + } else { + return `${this.left.stringify()} ${this.modifier}(${this.labels.join(', ')})`; + } + } + + groupLeft(labels: string[], vectorExpr: PromQLVectorExpression) { + return new PromQLGroupModifier(GroupModifiers.GROUP_LEFT, labels, this, vectorExpr); + } + + groupRight(labels: string[], vectorExpr: PromQLVectorExpression) { + return new PromQLGroupModifier(GroupModifiers.GROUP_RIGHT, labels, this, vectorExpr); + } + + withExpression(expr: PromQLExpression) { + this.right = expr; + return PromQL.parenthesis(this); + } +} + class PromQLBinaryExpression extends PromQLVectorExpression { private right?: PromQLExpression; @@ -142,12 +150,36 @@ enum LogicalOperators { } class PromQLLogicalExpression extends PromQLVectorExpression { - constructor(private operator: LogicalOperators, private left: PromQLExpression, private right: PromQLExpression) { + + private right?: PromQLExpression; + + constructor(private operator: LogicalOperators, private left: PromQLExpression) { super(); } stringify() { - return `${this.left.stringify()} ${this.operator} (${this.right.stringify()}) `; + if (this.right) { + return `${this.left.stringify()} ${this.operator} ${this.right.stringify()}`; + } else { + return `${this.left.stringify()} ${this.operator}`; + } + } + + ignoring(labels: string[]) { + return new PromQLMatchingModifier(MatchingModifiers.IGNORING, labels, this); + } + + on(labels: string[]) { + return new PromQLMatchingModifier(MatchingModifiers.ON, labels, this); + } + + withScalar(scalar: number) { + return new PromQLScalarExpression(scalar, this); + } + + withExpression(expr: PromQLExpression) { + this.right = expr; + return PromQL.parenthesis(this); } } @@ -482,7 +514,7 @@ export class PromQL { } static labelReplace(exp: PromQLVectorExpression, dest: string, sourceLabel: string, replacement: string, regex: string) { - return new PromQLLabelReplaceFunction(exp, dest, sourceLabel, replacement, regex); + return new PromQLLabelReplaceFunction(exp, dest, replacement, sourceLabel, regex); } static parenthesis(expr: PromQLVectorExpression) { diff --git a/src/metrics/metrics.ts b/src/metrics/metrics.ts index f11d866..6e558d5 100644 --- a/src/metrics/metrics.ts +++ b/src/metrics/metrics.ts @@ -371,6 +371,13 @@ export const Metrics = { controller: 'controller', } }, + // Nginx Ingress Controller + nginxIngressControllerBuildInfo: { + name: 'nginx_ingress_controller_build_info', + labels:{ + controllerClass: 'controller_class', + } + }, // Services kubeServiceInfo: { name: 'kube_service_info', diff --git a/src/pages/Clusters/tabs/Nodes/Queries.tsx b/src/pages/Clusters/tabs/Nodes/Queries.tsx index 2b62483..0c22ac9 100644 --- a/src/pages/Clusters/tabs/Nodes/Queries.tsx +++ b/src/pages/Clusters/tabs/Nodes/Queries.tsx @@ -53,7 +53,9 @@ export class NodesQueryBuilder implements QueryBuilder { value: '' } }) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) @@ -70,7 +72,9 @@ export class NodesQueryBuilder implements QueryBuilder { ...commonCarryOverLabels, ], this.createCpuRequestsQuery('$cluster', {}) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) @@ -87,7 +91,9 @@ export class NodesQueryBuilder implements QueryBuilder { ...commonCarryOverLabels, ], this.createCoresQuery('$cluster', {}) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) @@ -104,7 +110,9 @@ export class NodesQueryBuilder implements QueryBuilder { ...commonCarryOverLabels, ], this.createPodCountQuery('$cluster', {}) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) @@ -121,7 +129,9 @@ export class NodesQueryBuilder implements QueryBuilder { ...commonCarryOverLabels, ], this.createNodeAgeQuery('$cluster', {}) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) diff --git a/src/pages/Network/pages/ingresses/index.tsx b/src/pages/Network/pages/ingresses/index.tsx index 124cb8c..d9e0724 100644 --- a/src/pages/Network/pages/ingresses/index.tsx +++ b/src/pages/Network/pages/ingresses/index.tsx @@ -22,10 +22,9 @@ import { usePluginJsonData } from "utils/utils.plugin"; import { createTimeRange, createTopLevelVariables } from "common/variableHelpers"; import { AlertsTable } from "components/AlertsTable"; import { createResourceLabels } from "pages/Workloads/components/ResourceLabels"; -import { PromQL } from "common/promql"; +import { MatchOperators, PromQL } from "common/promql"; import { Metrics } from "metrics/metrics"; import React, { useMemo } from "react"; -import { DataFrameView } from "@grafana/data"; import { Spinner } from "@grafana/ui"; import { getNginxFailureRatioPanel, @@ -45,7 +44,7 @@ import Analytics from "components/Analytics"; // Try connecting kube_ingress_path service_name to pods interface ConditionalSceneObjectState extends SceneObjectState { - builder: (data: string) => SceneObject; + builder: (rowCounts: Map) => SceneObject; children?: Array>; } @@ -63,16 +62,16 @@ function ConditionalRenderer({ model }: SceneComponentProps(frame); - const rows = view.toArray(); - - const controller = rows && rows.length > 0 ? rows[0].controller : undefined; + const rowCounts = new Map(); + // result counts per query + for (const serie of data.series) { + rowCounts.set(serie.refId || 'unknown', serie.length); + } // By setting it via state we can trigger render but also grafana connects the model to the scene graph // so that all nested objects could use the variables ... model.setState({ - children: [builder(controller)] + children: [builder(rowCounts)] }); return; @@ -92,19 +91,33 @@ function ConditionalRenderer({ model }: SceneComponentProps, ingress: string, namespace: string) { + + const nginxBuildInfo = rowCounts.get('nginx_ingress_controller_build_info') || 0; + + if (nginxBuildInfo > 0) { return displayBasicNginxMetrics(ingress, namespace); } else { return new SceneFlexLayout({ @@ -222,8 +238,8 @@ function getScene(namespace: string, ingress: string) { }, queries: [ { - refId: 'ingresses', - expr: ingressInfoQuery(namespace, ingress).stringify(), + refId: 'nginx_ingress_controller_build_info', + expr: nginxBuildInfoQuery(namespace, ingress).stringify(), instant: true, format: 'table' }, @@ -289,8 +305,8 @@ function getScene(namespace: string, ingress: string) { width: '100%', body: new ConditionalSceneObject({ $data: ingressInfoData, - builder: (controller: string) => { - return buildRequestsPanels(controller, ingress, namespace) + builder: (rowCounts: Map) => { + return buildRequestsPanels(rowCounts, ingress, namespace) } }), }), diff --git a/src/pages/Workloads/tabs/DaemonSets/Queries.tsx b/src/pages/Workloads/tabs/DaemonSets/Queries.tsx index 2760a0f..9fa4177 100644 --- a/src/pages/Workloads/tabs/DaemonSets/Queries.tsx +++ b/src/pages/Workloads/tabs/DaemonSets/Queries.tsx @@ -80,7 +80,9 @@ export class DaemonSetsQueryBuilder implements QueryBuilder { } }) ).by(['namespace', 'daemonset']) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) @@ -94,7 +96,9 @@ export class DaemonSetsQueryBuilder implements QueryBuilder { .groupRight( [], createReplicasQuery('$cluster', {}) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) diff --git a/src/pages/Workloads/tabs/Deployments/Queries.ts b/src/pages/Workloads/tabs/Deployments/Queries.ts index 4e6974e..fe7e5f5 100644 --- a/src/pages/Workloads/tabs/Deployments/Queries.ts +++ b/src/pages/Workloads/tabs/Deployments/Queries.ts @@ -114,7 +114,9 @@ export class DeploymentQueryBuilder implements QueryBuilder { } }) ).by(['namespace', 'deployment']) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) @@ -128,7 +130,9 @@ export class DeploymentQueryBuilder implements QueryBuilder { .groupRight( [], createReplicasQuery('$cluster', {}) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) diff --git a/src/pages/Workloads/tabs/Pods/Queries.ts b/src/pages/Workloads/tabs/Pods/Queries.ts index 18c26b4..76f4f91 100644 --- a/src/pages/Workloads/tabs/Pods/Queries.ts +++ b/src/pages/Workloads/tabs/Pods/Queries.ts @@ -381,7 +381,9 @@ export function createRootQuery( .groupRight( carryOverLabels, sortQuery - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) diff --git a/src/pages/Workloads/tabs/StatefulSets/Queries.tsx b/src/pages/Workloads/tabs/StatefulSets/Queries.tsx index 890101a..6df6050 100644 --- a/src/pages/Workloads/tabs/StatefulSets/Queries.tsx +++ b/src/pages/Workloads/tabs/StatefulSets/Queries.tsx @@ -80,7 +80,9 @@ export class StatefulSetQueryBuilder implements QueryBuilder { } }) ).by(['namespace', 'statefulset']) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) ) @@ -94,7 +96,9 @@ export class StatefulSetQueryBuilder implements QueryBuilder { .groupRight( [], createReplicasQuery('$cluster', {}) - ).or( + ) + .or() + .withExpression( baseQuery.multiply().withScalar(0) ) )