summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi-Robusta <97387909+Avi-Robusta@users.noreply.github.com>2023-08-08 17:07:51 +0300
committerGitHub <noreply@github.com>2023-08-08 17:07:51 +0300
commit3c0615dca2ad50c22e1a554da85ee66a6cb6c981 (patch)
tree3ffe6aa6cef56fee46e708345892676d2eb5b745
parentc503daa35a7e3a227093626158fa94ec51487cb2 (diff)
Unified prometheus support (#121)
* initial refactoring initial changes working version aws test added eks managed prom support coralogix prom support and fix prom bug fixed bug added all aws config changes added docs and fixed requirements copying connect changes from robusta fixing bad typing reformatting added prometrix updated prometrix version * rebase fixes * black formatting * refactored check connection * Fixing victoria metrics check * updating poetry file after rebase
-rw-r--r--README.md32
-rw-r--r--poetry.lock100
-rw-r--r--pyproject.toml4
-rw-r--r--requirements.txt68
-rw-r--r--robusta_krr/core/integrations/prometheus/__init__.py2
-rw-r--r--robusta_krr/core/integrations/prometheus/loader.py6
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics/__init__.py4
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics/base.py2
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics/cpu.py2
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics/memory.py2
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics_service/base_metric_service.py8
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics_service/prometheus_metrics_service.py37
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics_service/thanos_metrics_service.py11
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics_service/victoria_metrics_service.py11
-rw-r--r--robusta_krr/core/integrations/prometheus/prometheus_client.py91
-rw-r--r--robusta_krr/core/integrations/prometheus/prometheus_utils.py50
-rw-r--r--robusta_krr/core/models/config.py11
-rw-r--r--robusta_krr/core/runner.py4
-rw-r--r--robusta_krr/main.py49
19 files changed, 294 insertions, 200 deletions
diff --git a/README.md b/README.md
index 677354c..e91856b 100644
--- a/README.md
+++ b/README.md
@@ -377,6 +377,38 @@ Than run the following command with PROMETHEUS_URL substituted for your Azure Ma
```sh
python krr.py simple --namespace default -p PROMETHEUS_URL --prometheus-auth-header "Bearer $AZURE_BEARER"
```
+<p ><a href="#scanning-with-a-centralized-prometheus">See here about configuring labels for centralized prometheus</a></p>
+
+<p align="right">(<a href="#readme-top">back to top</a>)</p>
+
+## EKS managed Prometheus
+
+For EKS managed Prometheus you need to add your prometheus link and the flag --eks-managed-prom and krr will automatically use your aws credentials
+
+```sh
+python krr.py simple -p "https://aps-workspaces.REGION.amazonaws.com/workspaces/..." --eks-managed-prom
+```
+Additional optional parameters are:
+```sh
+--eks-profile-name PROFILE_NAME_HERE # to specify the profile to use from your config
+--eks-access-key ACCESS_KEY # to specify your access key
+--eks-secret-key SECRET_KEY # to specify your secret key
+--eks-service-name SERVICE_NAME # to use a specific service name in the signature
+--eks-managed-prom-region REGION_NAME # to specify the region the prometheus is in
+```
+<p ><a href="#scanning-with-a-centralized-prometheus">See here about configuring labels for centralized prometheus</a></p>
+
+<p align="right">(<a href="#readme-top">back to top</a>)</p>
+
+## Coralogix managed Prometheus
+
+For Coralogix managed Prometheus you need to specify your prometheus link and add the flag coralogix_token with your Logs Query Key
+
+```sh
+python krr.py simple -p "https://prom-api.coralogix..." --coralogix_token
+```
+
+<p ><a href="#scanning-with-a-centralized-prometheus">See here about configuring labels for centralized prometheus</a></p>
<p align="right">(<a href="#readme-top">back to top</a>)</p>
diff --git a/poetry.lock b/poetry.lock
index 0e1b413..5dbdfd4 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -95,6 +95,44 @@ jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
uvloop = ["uvloop (>=0.15.2)"]
[[package]]
+name = "boto3"
+version = "1.28.15"
+description = "The AWS SDK for Python"
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "boto3-1.28.15-py3-none-any.whl", hash = "sha256:84b7952858e9319968b0348d9894a91a6bb5f31e81a45c68044d040a12362abe"},
+ {file = "boto3-1.28.15.tar.gz", hash = "sha256:a6e711e0b6960c3a5b789bd30c5a18eea7263f2a59fc07f85efa5e04804e49d2"},
+]
+
+[package.dependencies]
+botocore = ">=1.31.15,<1.32.0"
+jmespath = ">=0.7.1,<2.0.0"
+s3transfer = ">=0.6.0,<0.7.0"
+
+[package.extras]
+crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
+
+[[package]]
+name = "botocore"
+version = "1.31.15"
+description = "Low-level, data-driven core of boto 3."
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "botocore-1.31.15-py3-none-any.whl", hash = "sha256:b3a0f787f275711875476cbe12a0123b2e6570b2f505e2fa509dcec3c5410b57"},
+ {file = "botocore-1.31.15.tar.gz", hash = "sha256:b46d1ce4e0cf42d28fdf61ce0c999904645d38b51cb809817a361c0cec16d487"},
+]
+
+[package.dependencies]
+jmespath = ">=0.7.1,<2.0.0"
+python-dateutil = ">=2.1,<3.0.0"
+urllib3 = ">=1.25.4,<1.27"
+
+[package.extras]
+crt = ["awscrt (==0.16.26)"]
+
+[[package]]
name = "cachetools"
version = "5.3.1"
description = "Extensible memoizing collections and decorators"
@@ -526,6 +564,17 @@ plugins = ["setuptools"]
requirements-deprecated-finder = ["pip-api", "pipreqs"]
[[package]]
+name = "jmespath"
+version = "1.0.1"
+description = "JSON Matching Expressions"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"},
+ {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"},
+]
+
+[[package]]
name = "kiwisolver"
version = "1.4.4"
description = "A fast implementation of the Cassowary constraint solver"
@@ -1041,6 +1090,23 @@ pandas = ">=1.4.0"
requests = "*"
[[package]]
+name = "prometrix"
+version = "0.1.10"
+description = ""
+optional = false
+python-versions = ">=3.8,<4.0"
+files = [
+ {file = "prometrix-0.1.10-py3-none-any.whl", hash = "sha256:5caa0ee06d49d7ad1f881614edb81fe4b2f47f730bcd4286209627fdc41d550d"},
+ {file = "prometrix-0.1.10.tar.gz", hash = "sha256:9ed61c0b77b503d38ce9c66d70742ad81a84b7afc6fbf63e8dbba9316b41a4df"},
+]
+
+[package.dependencies]
+boto3 = ">=1.28.15,<2.0.0"
+botocore = ">=1.31.15,<2.0.0"
+prometheus-api-client = ">=0.5.3,<0.6.0"
+pydantic = ">=1.8.1,<2.0.0"
+
+[[package]]
name = "pyasn1"
version = "0.5.0"
description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)"
@@ -1487,6 +1553,23 @@ files = [
pyasn1 = ">=0.1.3"
[[package]]
+name = "s3transfer"
+version = "0.6.1"
+description = "An Amazon S3 Transfer Manager"
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "s3transfer-0.6.1-py3-none-any.whl", hash = "sha256:3c0da2d074bf35d6870ef157158641178a4204a6e689e82546083e31e0311346"},
+ {file = "s3transfer-0.6.1.tar.gz", hash = "sha256:640bb492711f4c0c0905e1f62b6aaeb771881935ad27884852411f8e9cacbca9"},
+]
+
+[package.dependencies]
+botocore = ">=1.12.36,<2.0a.0"
+
+[package.extras]
+crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"]
+
+[[package]]
name = "setuptools"
version = "68.0.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
@@ -1661,20 +1744,19 @@ devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pyte
[[package]]
name = "urllib3"
-version = "2.0.4"
+version = "1.26.16"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
- {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"},
- {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"},
+ {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"},
+ {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"},
]
[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
-secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"]
-socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
-zstd = ["zstandard (>=0.18.0)"]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
+secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "websocket-client"
@@ -1710,4 +1792,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[metadata]
lock-version = "2.0"
python-versions = ">=3.9,<3.12"
-content-hash = "936ab8c06cf4a6e5cc8c3a8cbe6bb50ff8edf019e11cc9a1e20847505a8b62a5"
+content-hash = "bcef0de696e4fbf7bd3140cc79c6d72fdbf3d39c20b7101c55c9613a1cd56a40"
diff --git a/pyproject.toml b/pyproject.toml
index ef99a74..a4f0cca 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -27,9 +27,11 @@ python = ">=3.9,<3.12"
typer = {extras = ["all"], version = "^0.7.0"}
pydantic = "1.10.7"
kubernetes = "^26.1.0"
-prometheus-api-client = "^0.5.3"
numpy = "^1.24.2"
alive-progress = "^3.1.2"
+botocore = "^1.31.10"
+boto3 = "^1.28.10"
+prometrix = "^0.1.10"
[tool.poetry.group.dev.dependencies]
diff --git a/requirements.txt b/requirements.txt
index 907cfed..f887a5e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,52 +1,54 @@
about-time==4.2.1 ; python_version >= "3.9" and python_version < "3.12"
-aiostream==0.4.5 ; python_version >= "3.9" and python_version < "3.12"
-alive-progress==3.1.2 ; python_version >= "3.9" and python_version < "3.12"
-cachetools==5.3.0 ; python_version >= "3.9" and python_version < "3.12"
-certifi==2022.12.7 ; python_version >= "3.9" and python_version < "3.12"
-charset-normalizer==3.0.1 ; python_version >= "3.9" and python_version < "3.12"
-click==8.1.3 ; python_version >= "3.9" and python_version < "3.12"
-colorama==0.4.6 ; python_version >= "3.9" and python_version < "3.12"
+alive-progress==3.1.4 ; python_version >= "3.9" and python_version < "3.12"
+boto3==1.28.15 ; python_version >= "3.9" and python_version < "3.12"
+botocore==1.31.15 ; python_version >= "3.9" and python_version < "3.12"
+cachetools==5.3.1 ; python_version >= "3.9" and python_version < "3.12"
+certifi==2023.7.22 ; python_version >= "3.9" and python_version < "3.12"
+charset-normalizer==3.2.0 ; python_version >= "3.9" and python_version < "3.12"
+click==8.1.6 ; python_version >= "3.9" and python_version < "3.12"
+colorama==0.4.6 ; python_version >= "3.9" and python_version < "3.12" and platform_system == "Windows"
commonmark==0.9.1 ; python_version >= "3.9" and python_version < "3.12"
-contourpy==1.0.7 ; python_version >= "3.9" and python_version < "3.12"
+contourpy==1.1.0 ; python_version >= "3.9" and python_version < "3.12"
cycler==0.11.0 ; python_version >= "3.9" and python_version < "3.12"
-dateparser==1.1.7 ; python_version >= "3.9" and python_version < "3.12"
-fonttools==4.39.0 ; python_version >= "3.9" and python_version < "3.12"
-google-auth==2.16.2 ; python_version >= "3.9" and python_version < "3.12"
+dateparser==1.1.8 ; python_version >= "3.9" and python_version < "3.12"
+fonttools==4.42.0 ; python_version >= "3.9" and python_version < "3.12"
+google-auth==2.17.3 ; python_version >= "3.9" and python_version < "3.12"
grapheme==0.6.0 ; python_version >= "3.9" and python_version < "3.12"
httmock==1.4.0 ; python_version >= "3.9" and python_version < "3.12"
idna==3.4 ; python_version >= "3.9" and python_version < "3.12"
-importlib-resources==5.12.0 ; python_version >= "3.9" and python_version < "3.10"
+importlib-resources==6.0.0 ; python_version >= "3.9" and python_version < "3.10"
+jmespath==1.0.1 ; python_version >= "3.9" and python_version < "3.12"
kiwisolver==1.4.4 ; python_version >= "3.9" and python_version < "3.12"
kubernetes==26.1.0 ; python_version >= "3.9" and python_version < "3.12"
-matplotlib==3.7.1 ; python_version >= "3.9" and python_version < "3.12"
-numpy==1.24.2 ; python_version >= "3.9" and python_version < "3.12"
+matplotlib==3.7.2 ; python_version >= "3.9" and python_version < "3.12"
+numpy==1.25.2 ; python_version >= "3.9" and python_version < "3.12"
oauthlib==3.2.2 ; python_version >= "3.9" and python_version < "3.12"
-packaging==23.0 ; python_version >= "3.9" and python_version < "3.12"
-pandas==1.5.3 ; python_version >= "3.9" and python_version < "3.12"
-pillow==9.4.0 ; python_version >= "3.9" and python_version < "3.12"
+packaging==23.1 ; python_version >= "3.9" and python_version < "3.12"
+pandas==2.0.3 ; python_version >= "3.9" and python_version < "3.12"
+pillow==10.0.0 ; python_version >= "3.9" and python_version < "3.12"
prometheus-api-client==0.5.3 ; python_version >= "3.9" and python_version < "3.12"
-pyasn1-modules==0.2.8 ; python_version >= "3.9" and python_version < "3.12"
-pyasn1==0.4.8 ; python_version >= "3.9" and python_version < "3.12"
+prometrix==0.1.10 ; python_version >= "3.9" and python_version < "3.12"
+pyasn1-modules==0.3.0 ; python_version >= "3.9" and python_version < "3.12"
+pyasn1==0.5.0 ; python_version >= "3.9" and python_version < "3.12"
pydantic==1.10.7 ; python_version >= "3.9" and python_version < "3.12"
-pygments==2.14.0 ; python_version >= "3.9" and python_version < "3.12"
+pygments==2.15.1 ; python_version >= "3.9" and python_version < "3.12"
pyparsing==3.0.9 ; python_version >= "3.9" and python_version < "3.12"
python-dateutil==2.8.2 ; python_version >= "3.9" and python_version < "3.12"
-pytz-deprecation-shim==0.1.0.post0 ; python_version >= "3.9" and python_version < "3.12"
-pytz==2022.7.1 ; python_version >= "3.9" and python_version < "3.12"
-pyyaml==6.0 ; python_version >= "3.9" and python_version < "3.12"
-regex==2022.10.31 ; python_version >= "3.9" and python_version < "3.12"
+pytz==2023.3 ; python_version >= "3.9" and python_version < "3.12"
+pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "3.12"
+regex==2023.6.3 ; python_version >= "3.9" and python_version < "3.12"
requests-oauthlib==1.3.1 ; python_version >= "3.9" and python_version < "3.12"
-requests==2.28.2 ; python_version >= "3.9" and python_version < "3.12"
+requests==2.31.0 ; python_version >= "3.9" and python_version < "3.12"
rich==12.6.0 ; python_version >= "3.9" and python_version < "3.12"
rsa==4.9 ; python_version >= "3.9" and python_version < "3.12"
-setuptools==67.4.0 ; python_version >= "3.9" and python_version < "3.12"
+s3transfer==0.6.1 ; python_version >= "3.9" and python_version < "3.12"
+setuptools==68.0.0 ; python_version >= "3.9" and python_version < "3.12"
shellingham==1.5.0.post1 ; python_version >= "3.9" and python_version < "3.12"
six==1.16.0 ; python_version >= "3.9" and python_version < "3.12"
typer[all]==0.7.0 ; python_version >= "3.9" and python_version < "3.12"
-typing-extensions==4.5.0 ; python_version >= "3.9" and python_version < "3.12"
-tzdata==2022.7 ; python_version >= "3.9" and python_version < "3.12"
-tzlocal==4.2 ; python_version >= "3.9" and python_version < "3.12"
-urllib3==1.26.14 ; python_version >= "3.9" and python_version < "3.12"
-websocket-client==1.5.1 ; python_version >= "3.9" and python_version < "3.12"
-zipp==3.15.0 ; python_version >= "3.9" and python_version < "3.10"
-slack-sdk==3.21.3 ; python_version >= "3.9" and python_version < "3.12"
+typing-extensions==4.7.1 ; python_version >= "3.9" and python_version < "3.12"
+tzdata==2023.3 ; python_version >= "3.9" and python_version < "3.12"
+tzlocal==5.0.1 ; python_version >= "3.9" and python_version < "3.12"
+urllib3==1.26.16 ; python_version >= "3.9" and python_version < "3.12"
+websocket-client==1.6.1 ; python_version >= "3.9" and python_version < "3.12"
+zipp==3.16.2 ; python_version >= "3.9" and python_version < "3.10"
diff --git a/robusta_krr/core/integrations/prometheus/__init__.py b/robusta_krr/core/integrations/prometheus/__init__.py
index e7e545b..cedf1c0 100644
--- a/robusta_krr/core/integrations/prometheus/__init__.py
+++ b/robusta_krr/core/integrations/prometheus/__init__.py
@@ -1,3 +1,3 @@
from .loader import PrometheusMetricsLoader
from .metrics_service.prometheus_metrics_service import PrometheusDiscovery, PrometheusNotFound
-from .prometheus_client import CustomPrometheusConnect, ClusterNotSpecifiedException
+from .prometheus_utils import ClusterNotSpecifiedException
diff --git a/robusta_krr/core/integrations/prometheus/loader.py b/robusta_krr/core/integrations/prometheus/loader.py
index ca0d6f1..70d839a 100644
--- a/robusta_krr/core/integrations/prometheus/loader.py
+++ b/robusta_krr/core/integrations/prometheus/loader.py
@@ -2,21 +2,21 @@ from __future__ import annotations
import datetime
from concurrent.futures import ThreadPoolExecutor
-from typing import Optional, TYPE_CHECKING
+from typing import TYPE_CHECKING, Optional
from kubernetes import config as k8s_config
from kubernetes.client.api_client import ApiClient
+from prometrix import MetricsNotFound, PrometheusNotFound
from robusta_krr.core.models.objects import K8sObjectData
from robusta_krr.utils.configurable import Configurable
-from .metrics_service.base_metric_service import MetricsNotFound
from .metrics_service.prometheus_metrics_service import PrometheusMetricsService, PrometheusNotFound
from .metrics_service.thanos_metrics_service import ThanosMetricsService
from .metrics_service.victoria_metrics_service import VictoriaMetricsService
if TYPE_CHECKING:
- from robusta_krr.core.abstract.strategies import MetricsPodData, BaseStrategy
+ from robusta_krr.core.abstract.strategies import BaseStrategy, MetricsPodData
from robusta_krr.core.models.config import Config
METRICS_SERVICES = {
diff --git a/robusta_krr/core/integrations/prometheus/metrics/__init__.py b/robusta_krr/core/integrations/prometheus/metrics/__init__.py
index daee396..6212a35 100644
--- a/robusta_krr/core/integrations/prometheus/metrics/__init__.py
+++ b/robusta_krr/core/integrations/prometheus/metrics/__init__.py
@@ -1,3 +1,3 @@
-from .cpu import CPULoader, MaxCPULoader, PercentileCPULoader
-from .memory import MemoryLoader, MaxMemoryLoader, PercentileMemoryLoader
from .base import PrometheusMetric
+from .cpu import CPULoader, MaxCPULoader, PercentileCPULoader
+from .memory import MaxMemoryLoader, MemoryLoader, PercentileMemoryLoader
diff --git a/robusta_krr/core/integrations/prometheus/metrics/base.py b/robusta_krr/core/integrations/prometheus/metrics/base.py
index d076ff4..709be92 100644
--- a/robusta_krr/core/integrations/prometheus/metrics/base.py
+++ b/robusta_krr/core/integrations/prometheus/metrics/base.py
@@ -5,7 +5,7 @@ import asyncio
import datetime
import enum
from concurrent.futures import ThreadPoolExecutor
-from typing import Any, TYPE_CHECKING, Optional
+from typing import TYPE_CHECKING, Any, Optional
import numpy as np
import pydantic as pd
diff --git a/robusta_krr/core/integrations/prometheus/metrics/cpu.py b/robusta_krr/core/integrations/prometheus/metrics/cpu.py
index 3aab7b4..f4b9058 100644
--- a/robusta_krr/core/integrations/prometheus/metrics/cpu.py
+++ b/robusta_krr/core/integrations/prometheus/metrics/cpu.py
@@ -1,6 +1,6 @@
from robusta_krr.core.models.objects import K8sObjectData
-from .base import QueryMetric, QueryRangeMetric, FilterMetric
+from .base import FilterMetric, QueryMetric, QueryRangeMetric
class CPULoader(QueryRangeMetric, FilterMetric):
diff --git a/robusta_krr/core/integrations/prometheus/metrics/memory.py b/robusta_krr/core/integrations/prometheus/metrics/memory.py
index 5fc6f73..d8779f2 100644
--- a/robusta_krr/core/integrations/prometheus/metrics/memory.py
+++ b/robusta_krr/core/integrations/prometheus/metrics/memory.py
@@ -1,6 +1,6 @@
from robusta_krr.core.models.objects import K8sObjectData
-from .base import QueryMetric, QueryRangeMetric, FilterMetric
+from .base import FilterMetric, QueryMetric, QueryRangeMetric
class MemoryLoader(QueryRangeMetric, FilterMetric):
diff --git a/robusta_krr/core/integrations/prometheus/metrics_service/base_metric_service.py b/robusta_krr/core/integrations/prometheus/metrics_service/base_metric_service.py
index b0adfb7..8b4beef 100644
--- a/robusta_krr/core/integrations/prometheus/metrics_service/base_metric_service.py
+++ b/robusta_krr/core/integrations/prometheus/metrics_service/base_metric_service.py
@@ -13,14 +13,6 @@ from robusta_krr.utils.configurable import Configurable
from ..metrics import PrometheusMetric
-class MetricsNotFound(Exception):
- """
- An exception raised when Metrics service is not found.
- """
-
- pass
-
-
class MetricsService(Configurable, abc.ABC):
def __init__(
self,
diff --git a/robusta_krr/core/integrations/prometheus/metrics_service/prometheus_metrics_service.py b/robusta_krr/core/integrations/prometheus/metrics_service/prometheus_metrics_service.py
index b2cc135..5480512 100644
--- a/robusta_krr/core/integrations/prometheus/metrics_service/prometheus_metrics_service.py
+++ b/robusta_krr/core/integrations/prometheus/metrics_service/prometheus_metrics_service.py
@@ -1,11 +1,12 @@
import asyncio
import datetime
import time
-from typing import List, Optional
from concurrent.futures import ThreadPoolExecutor
+from typing import List, Optional
from kubernetes.client import ApiClient
from prometheus_api_client import PrometheusApiClientException
+from prometrix import PrometheusNotFound, get_custom_prometheus_connect
from requests.exceptions import ConnectionError, HTTPError
from robusta_krr.core.abstract.strategies import PodsTimeData
@@ -14,8 +15,8 @@ from robusta_krr.core.models.objects import K8sObjectData, PodData
from robusta_krr.utils.service_discovery import MetricsServiceDiscovery
from ..metrics import PrometheusMetric
-from ..prometheus_client import ClusterNotSpecifiedException, CustomPrometheusConnect
-from .base_metric_service import MetricsNotFound, MetricsService
+from ..prometheus_utils import ClusterNotSpecifiedException, generate_prometheus_config
+from .base_metric_service import MetricsService
class PrometheusDiscovery(MetricsServiceDiscovery):
@@ -41,14 +42,6 @@ class PrometheusDiscovery(MetricsServiceDiscovery):
)
-class PrometheusNotFound(MetricsNotFound):
- """
- An exception raised when Prometheus is not found.
- """
-
- pass
-
-
class PrometheusMetricsService(MetricsService):
"""
A class for fetching metrics from Prometheus.
@@ -90,8 +83,10 @@ class PrometheusMetricsService(MetricsService):
headers |= {"Authorization": self.auth_header}
elif not self.config.inside_cluster and self.api_client is not None:
self.api_client.update_params_for_auth(headers, {}, ["BearerToken"])
-
- self.prometheus = CustomPrometheusConnect(url=self.url, disable_ssl=not self.ssl_enabled, headers=headers)
+ self.prom_config = generate_prometheus_config(
+ config, url=self.url, headers=headers, metrics_service=self
+ )
+ self.prometheus = get_custom_prometheus_connect(self.prom_config)
def check_connection(self):
"""
@@ -99,20 +94,8 @@ class PrometheusMetricsService(MetricsService):
Raises:
PrometheusNotFound: If the connection to Prometheus cannot be established.
"""
- try:
- response = self.prometheus._session.get(
- f"{self.prometheus.url}/api/v1/query",
- verify=self.prometheus.ssl_verification,
- headers=self.prometheus.headers,
- # This query should return empty results, but is correct
- params={"query": "example"},
- )
- response.raise_for_status()
- except (ConnectionError, HTTPError) as e:
- raise PrometheusNotFound(
- f"Couldn't connect to Prometheus found under {self.prometheus.url}\nCaused by {e.__class__.__name__}: {e})"
- ) from e
-
+ self.prometheus.check_prometheus_connection()
+
async def query(self, query: str) -> dict:
loop = asyncio.get_running_loop()
return await loop.run_in_executor(self.executor, lambda: self.prometheus.custom_query(query=query))
diff --git a/robusta_krr/core/integrations/prometheus/metrics_service/thanos_metrics_service.py b/robusta_krr/core/integrations/prometheus/metrics_service/thanos_metrics_service.py
index 3b7ef85..eaf1620 100644
--- a/robusta_krr/core/integrations/prometheus/metrics_service/thanos_metrics_service.py
+++ b/robusta_krr/core/integrations/prometheus/metrics_service/thanos_metrics_service.py
@@ -1,10 +1,11 @@
from typing import Optional
from kubernetes.client import ApiClient
+from prometrix import MetricsNotFound, ThanosMetricsNotFound
from robusta_krr.utils.service_discovery import MetricsServiceDiscovery
-from .prometheus_metrics_service import MetricsNotFound, PrometheusMetricsService
+from .prometheus_metrics_service import PrometheusMetricsService
class ThanosMetricsDiscovery(MetricsServiceDiscovery):
@@ -27,14 +28,6 @@ class ThanosMetricsDiscovery(MetricsServiceDiscovery):
)
-class ThanosMetricsNotFound(MetricsNotFound):
- """
- An exception raised when Thanos is not found.
- """
-
- pass
-
-
class ThanosMetricsService(PrometheusMetricsService):
"""
A class for fetching metrics from Thanos.
diff --git a/robusta_krr/core/integrations/prometheus/metrics_service/victoria_metrics_service.py b/robusta_krr/core/integrations/prometheus/metrics_service/victoria_metrics_service.py
index 925136a..a0f1010 100644
--- a/robusta_krr/core/integrations/prometheus/metrics_service/victoria_metrics_service.py
+++ b/robusta_krr/core/integrations/prometheus/metrics_service/victoria_metrics_service.py
@@ -1,10 +1,11 @@
from typing import Optional
from kubernetes.client import ApiClient
+from prometrix import MetricsNotFound, VictoriaMetricsNotFound
from robusta_krr.utils.service_discovery import MetricsServiceDiscovery
-from .prometheus_metrics_service import MetricsNotFound, PrometheusMetricsService
+from .prometheus_metrics_service import PrometheusMetricsService
class VictoriaMetricsDiscovery(MetricsServiceDiscovery):
@@ -26,14 +27,6 @@ class VictoriaMetricsDiscovery(MetricsServiceDiscovery):
)
-class VictoriaMetricsNotFound(MetricsNotFound):
- """
- An exception raised when Victoria Metrics is not found.
- """
-
- pass
-
-
class VictoriaMetricsService(PrometheusMetricsService):
"""
A class for fetching metrics from Victoria Metrics.
diff --git a/robusta_krr/core/integrations/prometheus/prometheus_client.py b/robusta_krr/core/integrations/prometheus/prometheus_client.py
deleted file mode 100644
index ac93608..0000000
--- a/robusta_krr/core/integrations/prometheus/prometheus_client.py
+++ /dev/null
@@ -1,91 +0,0 @@
-from typing import no_type_check
-
-import requests
-from datetime import datetime
-from prometheus_api_client import PrometheusConnect, Retry, PrometheusApiClientException
-from requests.adapters import HTTPAdapter
-
-
-class ClusterNotSpecifiedException(Exception):
- """
- An exception raised when a prometheus requires a cluster label but an invalid one is provided.
- """
-
- pass
-
-
-class CustomPrometheusConnect(PrometheusConnect):
- """
- Custom PrometheusConnect class to handle retries.
- """
-
- @no_type_check
- def __init__(
- self,
- url: str = "http://127.0.0.1:9090",
- headers: dict = None,
- disable_ssl: bool = False,
- retry: Retry = None,
- auth: tuple = None,
- ):
- super().__init__(url, headers, disable_ssl, retry, auth)
- self._session = requests.Session()
- self._session.mount(self.url, HTTPAdapter(max_retries=retry, pool_maxsize=10, pool_block=True))
-
- @no_type_check
- def custom_query(self, query: str, params: dict = None):
- params = params or {}
- data = None
- query = str(query)
- # using the query API to get raw data
- response = self._session.post(
- "{0}/api/v1/query".format(self.url),
- data={"query": query, **params},
- verify=self.ssl_verification,
- headers=self.headers,
- auth=self.auth,
- )
- if response.status_code == 200:
- data = response.json()["data"]["result"]
- else:
- raise PrometheusApiClientException(
- "HTTP Status Code {} ({!r})".format(response.status_code, response.content)
- )
-
- return data
-
- @no_type_check
- def custom_query_range(
- self,
- query: str,
- start_time: datetime,
- end_time: datetime,
- step: str,
- params: dict = None,
- ):
- start = round(start_time.timestamp())
- end = round(end_time.timestamp())
- params = params or {}
- data = None
- query = str(query)
- # using the query_range API to get raw data
- response = self._session.post(
- "{0}/api/v1/query_range".format(self.url),
- data={
- "query": query,
- "start": start,
- "end": end,
- "step": step,
- **params,
- },
- verify=self.ssl_verification,
- headers=self.headers,
- auth=self.auth,
- )
- if response.status_code == 200:
- data = response.json()["data"]["result"]
- else:
- raise PrometheusApiClientException(
- "HTTP Status Code {} ({!r})".format(response.status_code, response.content)
- )
- return data
diff --git a/robusta_krr/core/integrations/prometheus/prometheus_utils.py b/robusta_krr/core/integrations/prometheus/prometheus_utils.py
new file mode 100644
index 0000000..d4c6fd4
--- /dev/null
+++ b/robusta_krr/core/integrations/prometheus/prometheus_utils.py
@@ -0,0 +1,50 @@
+import boto3
+from prometrix import AWSPrometheusConfig, CoralogixPrometheusConfig, PrometheusConfig, VictoriaMetricsPrometheusConfig
+
+from robusta_krr.core.models.config import Config
+
+
+class ClusterNotSpecifiedException(Exception):
+ """
+ An exception raised when a prometheus requires a cluster label but an invalid one is provided.
+ """
+
+ pass
+
+
+def generate_prometheus_config(
+ config: Config, url: str, headers: dict[str, str], metrics_service: "PrometheusMetricsService"
+) -> PrometheusConfig:
+ from .metrics_service.victoria_metrics_service import VictoriaMetricsService
+
+ baseconfig = {
+ "url": url,
+ "disable_ssl": not config.prometheus_ssl_enabled,
+ "headers": headers,
+ }
+
+ # aws config
+ if config.eks_managed_prom:
+ session = boto3.Session(profile_name=config.eks_managed_prom_profile_name)
+ credentials = session.get_credentials()
+ credentials = credentials.get_frozen_credentials()
+ region = config.eks_managed_prom_region if config.eks_managed_prom_region else session.region_name
+ access_key = config.eks_access_key if config.eks_access_key else credentials.access_key
+ secret_key = config.eks_secret_key if config.eks_secret_key else credentials.secret_key
+ service_name = config.eks_service_name if config.eks_secret_key else "aps"
+ if not region:
+ raise Exception("No eks region specified")
+
+ return AWSPrometheusConfig(
+ access_key=access_key,
+ secret_access_key=secret_key,
+ aws_region=region,
+ service_name=service_name,
+ **baseconfig,
+ )
+ # coralogix config
+ if config.coralogix_token:
+ return CoralogixPrometheusConfig(**baseconfig, prometheus_token=config.coralogix_token)
+ if isinstance(metrics_service, VictoriaMetricsService):
+ return VictoriaMetricsPrometheusConfig(**baseconfig)
+ return PrometheusConfig(**baseconfig)
diff --git a/robusta_krr/core/models/config.py b/robusta_krr/core/models/config.py
index 7354a3d..70ae7a9 100644
--- a/robusta_krr/core/models/config.py
+++ b/robusta_krr/core/models/config.py
@@ -19,8 +19,8 @@ class Config(pd.BaseSettings):
selector: Optional[str] = None
# Value settings
- cpu_min_value: int = pd.Field(5, ge=0) # in millicores
- memory_min_value: int = pd.Field(10, ge=0) # in megabytes
+ cpu_min_value: int = pd.Field(100, ge=0) # in millicores
+ memory_min_value: int = pd.Field(100, ge=0) # in megabytes
# Prometheus Settings
prometheus_url: Optional[str] = pd.Field(None)
@@ -29,6 +29,13 @@ class Config(pd.BaseSettings):
prometheus_ssl_enabled: bool = pd.Field(False)
prometheus_cluster_label: Optional[str] = pd.Field(None)
prometheus_label: Optional[str] = pd.Field(None)
+ eks_managed_prom: bool = pd.Field(False)
+ eks_managed_prom_profile_name: Optional[str] = pd.Field(None)
+ eks_access_key: Optional[str] = pd.Field(None)
+ eks_secret_key: Optional[str] = pd.Field(None)
+ eks_service_name: Optional[str] = pd.Field(None)
+ eks_managed_prom_region: Optional[str] = pd.Field(None)
+ coralogix_token: Optional[str] = pd.Field(None)
# Threading settings
max_workers: int = pd.Field(6, ge=1)
diff --git a/robusta_krr/core/runner.py b/robusta_krr/core/runner.py
index 26ac3b1..f419c7c 100644
--- a/robusta_krr/core/runner.py
+++ b/robusta_krr/core/runner.py
@@ -9,10 +9,10 @@ import warnings
from robusta_krr.core.abstract.strategies import ResourceRecommendation, RunResult
from robusta_krr.core.integrations.kubernetes import KubernetesLoader
from robusta_krr.core.integrations.prometheus import (
- ClusterNotSpecifiedException,
PrometheusMetricsLoader,
- PrometheusNotFound,
+ ClusterNotSpecifiedException,
)
+from prometrix import PrometheusNotFound
from robusta_krr.core.models.config import Config
from robusta_krr.core.models.objects import K8sObjectData
from robusta_krr.core.models.result import (
diff --git a/robusta_krr/main.py b/robusta_krr/main.py
index 0b460d6..5fbe456 100644
--- a/robusta_krr/main.py
+++ b/robusta_krr/main.py
@@ -118,6 +118,48 @@ def load_commands() -> None:
help="The label in prometheus used to differentiate clusters. (Only relevant for centralized prometheus)",
rich_help_panel="Prometheus Settings",
),
+ eks_managed_prom: bool = typer.Option(
+ False,
+ "--eks-managed-prom",
+ help="Adds additional signitures for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ eks_managed_prom_profile_name: Optional[str] = typer.Option(
+ None,
+ "--eks-profile-name",
+ help="Sets the profile name for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ eks_access_key: Optional[str] = typer.Option(
+ None,
+ "--eks-access-key",
+ help="Sets the access key for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ eks_secret_key: Optional[str] = typer.Option(
+ None,
+ "--eks-secret-key",
+ help="Sets the secret key for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ eks_service_name: Optional[str] = typer.Option(
+ "aps",
+ "--eks-service-name",
+ help="Sets the service name for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ eks_managed_prom_region: Optional[str] = typer.Option(
+ None,
+ "--eks-managed-prom-region",
+ help="Sets the region for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ coralogix_token: Optional[str] = typer.Option(
+ None,
+ "--coralogix-token",
+ help="Adds the token needed to query Coralogix managed prometheus.",
+ rich_help_panel="Prometheus Coralogix Settings",
+ ),
max_workers: int = typer.Option(
10,
"--max-workers",
@@ -146,6 +188,13 @@ def load_commands() -> None:
prometheus_ssl_enabled=prometheus_ssl_enabled,
prometheus_cluster_label=prometheus_cluster_label,
prometheus_label=prometheus_label,
+ eks_managed_prom=eks_managed_prom,
+ eks_managed_prom_region=eks_managed_prom_region,
+ eks_managed_prom_profile_name=eks_managed_prom_profile_name,
+ eks_access_key=eks_access_key,
+ eks_secret_key=eks_secret_key,
+ eks_service_name=eks_service_name,
+ coralogix_token=coralogix_token,
max_workers=max_workers,
format=format,
verbose=verbose,