Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions kof-operator/internal/metrics/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ func (s *Service) CollectHealth() {
condition := getReadyCondition(s.config.Pod.Status.Conditions)

if condition == nil {
s.send(ConditionReadyHealthy, "unhealthy")
s.send(ConditionReadyReason, "MissingReadyCondition")
s.send(ConditionReadyMessage, "Pod status does not contain Ready condition")
s.send(ConditionReadyHealthy, &MetricValue{Value: "unhealthy"})
s.send(ConditionReadyReason, &MetricValue{Value: "MissingReadyCondition"})
s.send(ConditionReadyMessage, &MetricValue{Value: "Pod status does not contain Ready condition"})
s.error(fmt.Errorf("Ready condition not found in pod status"))
return
}

if condition.Status == corev1.ConditionTrue {
s.send(ConditionReadyHealthy, "healthy")
s.send(ConditionReadyHealthy, &MetricValue{Value: "healthy"})
} else {
s.send(ConditionReadyHealthy, "unhealthy")
s.send(ConditionReadyReason, condition.Reason)
s.send(ConditionReadyMessage, condition.Message)
s.send(ConditionReadyHealthy, &MetricValue{Value: "unhealthy"})
s.send(ConditionReadyReason, &MetricValue{Value: condition.Reason})
s.send(ConditionReadyMessage, &MetricValue{Value: condition.Message})
}
}
15 changes: 12 additions & 3 deletions kof-operator/internal/metrics/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,16 @@ func ParsePrometheusMetrics(metricsText string) (Metrics, error) {
value = m.GetUntyped().GetValue()
}

metrics[name] = value
metricLabels := m.GetLabel()
metricValue := &MetricValue{
Labels: make(map[string]string),
Value: value,
}

for _, label := range metricLabels {
metricValue.Labels[*label.Name] = *label.Value
}
metrics.Add(name, metricValue)
}
}

Expand All @@ -62,12 +71,12 @@ func findContainerMetric(containers []v1beta1.ContainerMetrics, name string) (*v
return nil, fmt.Errorf("metrics not found for container: %s", name)
}

func (s *Service) send(name string, value any) {
func (s *Service) send(name string, metricValue *MetricValue) {
s.config.Metrics <- &Metric{
Cluster: s.config.ClusterName,
Pod: s.config.Pod.Name,
Name: name,
Value: value,
Data: metricValue,
}
}

Expand Down
6 changes: 4 additions & 2 deletions kof-operator/internal/metrics/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ func (s *Service) CollectInternal() {
return
}

for name, val := range metrics {
s.send(name, val)
for name, values := range metrics {
for _, value := range values {
s.send(name, value)
}
}
}
12 changes: 6 additions & 6 deletions kof-operator/internal/metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package metrics

func (c ClusterMetrics) Add(m *Metric) {
func (c Cluster) Add(m *Metric) {
if cluster := c[m.Cluster]; cluster == nil {
c[m.Cluster] = make(PodMetrics)
c[m.Cluster] = make(Pod)
}
c[m.Cluster].Add(m)
}

func (p PodMetrics) Add(m *Metric) {
func (p Pod) Add(m *Metric) {
if pod := p[m.Pod]; pod == nil {
p[m.Pod] = make(Metrics)
}
p[m.Pod].Add(m.Name, m.Value)
p[m.Pod].Add(m.Name, m.Data)
}

func (m Metrics) Add(name string, value any) {
m[name] = value
func (m Metrics) Add(name string, labels *MetricValue) {
m[name] = append(m[name], labels)
}
12 changes: 6 additions & 6 deletions kof-operator/internal/metrics/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ func (s *Service) CollectResources() {
return
}

s.send(ContainerCPUUsage, usage.CPU)
s.send(ContainerMemoryUsage, usage.Memory)
s.send(ContainerCPUUsage, &MetricValue{Value: usage.CPU})
s.send(ContainerMemoryUsage, &MetricValue{Value: usage.Memory})

limits, err := s.getContainerLimits()
if err != nil {
Expand All @@ -28,8 +28,8 @@ func (s *Service) CollectResources() {
}

if limits.CPU > 0 && limits.Memory > 0 {
s.send(ContainerCPULimit, limits.CPU)
s.send(ContainerMemoryLimit, limits.Memory)
s.send(ContainerCPULimit, &MetricValue{Value: limits.CPU})
s.send(ContainerMemoryLimit, &MetricValue{Value: limits.Memory})
return
}

Expand All @@ -38,8 +38,8 @@ func (s *Service) CollectResources() {
s.error(fmt.Errorf("failed to get node limits: %v", err))
return
}
s.send(ContainerCPULimit, nodeAvailableNow.CPU+usage.CPU)
s.send(ContainerMemoryLimit, nodeAvailableNow.Memory+usage.Memory)
s.send(ContainerCPULimit, &MetricValue{Value: nodeAvailableNow.CPU + usage.CPU})
s.send(ContainerMemoryLimit, &MetricValue{Value: nodeAvailableNow.Memory + usage.Memory})
}

func (s *Service) getContainerLimits() (*Resource, error) {
Expand Down
12 changes: 8 additions & 4 deletions kof-operator/internal/metrics/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ import (
)

type MetricChannel chan *Metric
type ClusterMetrics map[string]PodMetrics
type PodMetrics map[string]Metrics
type Metrics map[string]any
type Cluster map[string]Pod
type Pod map[string]Metrics
type Metrics map[string][]*MetricValue
type MetricValue struct {
Labels map[string]string `json:"labels,omitempty"`
Value any `json:"value"`
}

type Resource struct {
CPU int64
Expand All @@ -21,8 +25,8 @@ type Metric struct {
Cluster string
Pod string
Name string
Value any
Err error
Data *MetricValue
}

type ServiceConfig struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

type Response struct {
Clusters metrics.ClusterMetrics `json:"clusters"`
Clusters metrics.Cluster `json:"clusters"`
}

const (
Expand Down
4 changes: 2 additions & 2 deletions kof-operator/internal/server/handlers/metrics_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func NewBaseMetricsHandler(ctx context.Context, kubeClient *k8s.KubeClient, logg
}
}

func (h *BaseMetricsHandler) GetMetrics() metrics.ClusterMetrics {
func (h *BaseMetricsHandler) GetMetrics() metrics.Cluster {
var cancel context.CancelFunc
h.ctx, cancel = context.WithTimeout(h.ctx, CollectorMaxResponseTime)
defer cancel()
Expand All @@ -57,7 +57,7 @@ func (h *BaseMetricsHandler) GetMetrics() metrics.ClusterMetrics {
close(h.metricCh)
}()

metrics := make(metrics.ClusterMetrics)
metrics := make(metrics.Cluster)
errs := make([]error, 0)

for metric := range h.metricCh {
Expand Down
42 changes: 36 additions & 6 deletions kof-operator/webapp/collector/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion kof-operator/webapp/collector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
},
"dependencies": {
"@radix-ui/react-checkbox": "^1.3.2",
"@radix-ui/react-collapsible": "^1.1.11",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-hover-card": "^1.1.14",
"@radix-ui/react-label": "^2.1.7",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Separator } from "@/components/generated/ui/separator";
import { METRICS } from "@/constants/metrics.constants";
import { formatNumber } from "@/utils/formatter";
import { useCollectorMetricsState } from "@/providers/collectors_metrics/CollectorsMetricsProvider";
import { MetricCardRow, MetricsCard } from "@/components/shared/MetricsCard";
import { MetricRow, MetricsCard } from "@/components/shared/MetricsCard";
import { Clock, Send, TriangleAlert } from "lucide-react";

const CollectorExporterTabContent = (): JSX.Element => {
Expand All @@ -28,7 +28,7 @@ const QueueCard = (): JSX.Element => {
return <></>;
}

const rows: MetricCardRow[] = [
const rows: MetricRow[] = [
{
title: "Capacity",
metricName: METRICS.OTELCOL_EXPORTER_QUEUE_CAPACITY.name,
Expand All @@ -42,18 +42,33 @@ const QueueCard = (): JSX.Element => {
{
title: "Utilization",
metricFetchFn: (pod) => {
const cap = pod.getMetric(METRICS.OTELCOL_EXPORTER_QUEUE_CAPACITY.name);
const size = pod.getMetric(METRICS.OTELCOL_EXPORTER_QUEUE_SIZE.name);
const cap = pod.getMetric(
METRICS.OTELCOL_EXPORTER_QUEUE_CAPACITY.name
)?.totalValue;

const size = pod.getMetric(
METRICS.OTELCOL_EXPORTER_QUEUE_SIZE.name
)?.totalValue;

if (!cap || !size) return 0;

return (size / cap) * 100;
},
metricFormat: (val) => `${val.toFixed(1)}%`,
hint: "Percentage of the exporter queue currently in use"
hint: "Percentage of the exporter queue currently in use",
},
{
title: "Utilization Bar",
metricFetchFn: (pod) => {
const cap = pod.getMetric(METRICS.OTELCOL_EXPORTER_QUEUE_CAPACITY.name);
const size = pod.getMetric(METRICS.OTELCOL_EXPORTER_QUEUE_SIZE.name);
const cap = pod.getMetric(
METRICS.OTELCOL_EXPORTER_QUEUE_CAPACITY.name
)?.totalValue;

const size = pod.getMetric(
METRICS.OTELCOL_EXPORTER_QUEUE_SIZE.name
)?.totalValue;

if (!cap || !size) return 0;
return (size / cap) * 100;
},
customRow: ({ rawValue, title }) => (
Expand All @@ -73,7 +88,7 @@ const QueueCard = (): JSX.Element => {
};

const SentRecordsCard = (): JSX.Element => {
const rows: MetricCardRow[] = [
const rows: MetricRow[] = [
{
title: "Log Records",
metricName: METRICS.OTELCOL_EXPORTER_SENT_LOG_RECORDS.name,
Expand Down Expand Up @@ -115,7 +130,7 @@ const SentRecordsCard = (): JSX.Element => {
};

const FailedRecordsCard = (): JSX.Element => {
const rows: MetricCardRow[] = [
const rows: MetricRow[] = [
{
title: "Failed Log Records",
metricName: METRICS.OTELCOL_EXPORTER_SEND_FAILED_LOG_RECORDS.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,33 @@ import { bytesToUnits, formatNumber } from "@/utils/formatter";
import { useCollectorMetricsState } from "@/providers/collectors_metrics/CollectorsMetricsProvider";
import { useTimePeriod } from "@/providers/collectors_metrics/TimePeriodState";
import { getMetricTrendData } from "@/utils/metrics";
import { MetricCardRow, MetricsCard } from "@/components/shared/MetricsCard";
import { MetricRow, MetricsCard } from "@/components/shared/MetricsCard";

const CollectorOverviewTabContent = ({
collector,
}: {
collector: Pod;
}): JSX.Element => {
const memoryUsage: number = collector.getMetric(
METRICS.CONTAINER_RESOURCE_MEMORY_USAGE.name
);
const memoryLimit: number = collector.getMetric(
METRICS.CONTAINER_RESOURCE_MEMORY_LIMIT.name
);

const queueSize = collector.getMetric(METRICS.OTELCOL_EXPORTER_QUEUE_SIZE.name);
const queueCapacity = collector.getMetric(
METRICS.OTELCOL_EXPORTER_QUEUE_CAPACITY.name
);

const cpuUsage = collector.getMetric(METRICS.CONTAINER_RESOURCE_CPU_USAGE.name);
const cpuLimit = collector.getMetric(METRICS.CONTAINER_RESOURCE_CPU_LIMIT.name);
const memoryUsage: number =
collector.getMetric(METRICS.CONTAINER_RESOURCE_MEMORY_USAGE.name)
?.totalValue ?? 0;
const memoryLimit: number =
collector.getMetric(METRICS.CONTAINER_RESOURCE_MEMORY_LIMIT.name)
?.totalValue ?? 0;

const queueSize =
collector.getMetric(METRICS.OTELCOL_EXPORTER_QUEUE_SIZE.name)?.totalValue ??
0;
const queueCapacity =
collector.getMetric(METRICS.OTELCOL_EXPORTER_QUEUE_CAPACITY.name)
?.totalValue ?? 0;

const cpuUsage =
collector.getMetric(METRICS.CONTAINER_RESOURCE_CPU_USAGE.name)
?.totalValue ?? 0;
const cpuLimit =
collector.getMetric(METRICS.CONTAINER_RESOURCE_CPU_LIMIT.name)
?.totalValue ?? 0;

return (
<TabsContent value="overview" className="flex flex-col gap-5">
Expand Down Expand Up @@ -187,7 +193,7 @@ const MetricsStatCard = (): JSX.Element => {
};

const ExportPerformanceCard = (): JSX.Element => {
const rows: MetricCardRow[] = [
const rows: MetricRow[] = [
{
title: "Sent Batches",
metricName: METRICS.OTELCOL_EXPORTER_PROM_WRITE_SENT_BATCHES.name,
Expand Down
Loading
Loading