Skip to content

Commit

Permalink
feat: Expose metrics about used TeamForCapella license usage
Browse files Browse the repository at this point in the history
A new gauge metric `t4c_licenses` was added to the `/metrics` endpoint,
which contains the number of currently used licenses per TeamForCapella
instance. The instance name is used as label for the metric.

Note: If you have multiple TeamForCapella server instances, which point
to the same license server, this is not detected. Therefore, make sure to
filter the `t4c_licenses` for one instance first.
  • Loading branch information
MoritzWeber0 committed Feb 28, 2024
1 parent 4f90b53 commit 910d169
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 32 deletions.
6 changes: 4 additions & 2 deletions backend/capellacollab/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
from fastapi.middleware import cors

import capellacollab.projects.toolmodels.backups.runs.interface as pipeline_runs_interface
import capellacollab.sessions.metrics
import capellacollab.sessions.metrics as sessions_metrics
import capellacollab.settings.modelsources.t4c.metrics as t4c_metrics

# This import statement is required and should not be removed! (Alembic will not work otherwise)
from capellacollab.config import config
Expand Down Expand Up @@ -84,7 +85,8 @@ async def shutdown():
on_startup=[
startup,
idletimeout.terminate_idle_sessions_in_background,
capellacollab.sessions.metrics.register,
sessions_metrics.register,
t4c_metrics.register,
pipeline_runs_interface.schedule_refresh_and_trigger_pipeline_jobs,
],
middleware=[
Expand Down
39 changes: 39 additions & 0 deletions backend/capellacollab/settings/modelsources/t4c/metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
# SPDX-License-Identifier: Apache-2.0

import typing as t

import prometheus_client
import prometheus_client.core

from capellacollab.core import database

from . import crud, interface


class UsedT4CLicensesCollector:
def collect(self) -> t.Iterable[prometheus_client.core.Metric]:
metric = prometheus_client.core.GaugeMetricFamily(
"t4c_licenses",
"Currently used T4C licenses per registered TeamForCapella instance.",
)

with database.SessionLocal() as db:
instances = crud.get_t4c_instances(db)

if not instances:
return

for instance in instances:
try:
t4c_status = interface.get_t4c_status(instance)
used_licenses = t4c_status.total - t4c_status.free
except: # pylint: disable=bare-except
used_licenses = -1

metric.add_metric([instance.name], used_licenses)
yield metric


def register() -> None:
prometheus_client.REGISTRY.register(UsedT4CLicensesCollector())
22 changes: 0 additions & 22 deletions backend/tests/settings/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import pytest
from sqlalchemy import orm

from capellacollab.settings.modelsources.t4c import crud as t4c_crud
from capellacollab.settings.modelsources.t4c import models as t4c_models
from capellacollab.tools import crud as tools_crud
from capellacollab.tools import models as tools_models
from capellacollab.users import crud as users_crud
Expand All @@ -25,23 +23,3 @@ def fixture_admin_user(
db: orm.Session, executor_name: str
) -> users_models.DatabaseUser:
return users_crud.create_user(db, executor_name, users_models.Role.ADMIN)


@pytest.fixture(name="t4c_instance")
def fixture_t4c_instance(
db: orm.Session,
test_tool_version: tools_models.DatabaseVersion,
) -> t4c_models.DatabaseT4CInstance:
server = t4c_models.DatabaseT4CInstance(
name="test server",
license="lic",
host="localhost",
usage_api="http://localhost:8086",
rest_api="http://localhost:8080/api/v1.0",
username="user",
password="pass",
protocol=t4c_models.Protocol.tcp,
version=test_tool_version,
)

return t4c_crud.create_t4c_instance(db, server)
42 changes: 42 additions & 0 deletions backend/tests/settings/teamforcapella/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
# SPDX-License-Identifier: Apache-2.0

import pytest
import responses
from fastapi import status
from sqlalchemy import orm

from capellacollab.settings.modelsources.t4c import crud as t4c_crud
from capellacollab.settings.modelsources.t4c import models as t4c_models
from capellacollab.tools import models as tools_models


@pytest.fixture(name="t4c_instance")
def fixture_t4c_instance(
db: orm.Session,
test_tool_version: tools_models.DatabaseVersion,
) -> t4c_models.DatabaseT4CInstance:
server = t4c_models.DatabaseT4CInstance(
name="test server",
license="lic",
host="localhost",
usage_api="http://localhost:8086",
rest_api="http://localhost:8080/api/v1.0",
username="user",
password="pass",
protocol=t4c_models.Protocol.tcp,
version=test_tool_version,
)

return t4c_crud.create_t4c_instance(db, server)


@pytest.fixture(name="mock_license_server")
def fixture_mock_license_server():
with responses.RequestsMock() as rsps:
rsps.get(
"http://localhost:8086/status/json",
status=status.HTTP_200_OK,
json={"status": {"used": 1, "free": 19, "total": 20}},
)
yield rsps
Original file line number Diff line number Diff line change
Expand Up @@ -290,20 +290,14 @@ def test_update_t4c_instance_password_empty_string(
assert updated_t4c_instance.password == expected_password


@responses.activate
@pytest.mark.usefixtures("mock_license_server")
def test_get_t4c_license_usage(
client: testclient.TestClient,
db: orm.Session,
executor_name: str,
t4c_instance: t4c_models.DatabaseT4CInstance,
):
users_crud.create_user(db, executor_name, users_models.Role.ADMIN)
responses.get(
"http://localhost:8086/status/json",
status=status.HTTP_200_OK,
json={"status": {"used": 1, "free": 19, "total": 20}},
)

response = client.get(
f"/api/v1/settings/modelsources/t4c/{t4c_instance.id}/licenses",
)
Expand Down
27 changes: 27 additions & 0 deletions backend/tests/settings/teamforcapella/test_t4c_metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
# SPDX-License-Identifier: Apache-2.0

import pytest

from capellacollab.settings.modelsources.t4c import metrics


@pytest.mark.usefixtures("mock_license_server", "t4c_instance")
def test_t4c_license_metrics_collector():
collector = metrics.UsedT4CLicensesCollector()

data = list(collector.collect())

sample = data[0].samples[0]
assert sample.name == "t4c_licenses"
assert sample.value == 1


def test_t4c_license_metrics_collector_error():
collector = metrics.UsedT4CLicensesCollector()

data = list(collector.collect())

sample = data[0].samples[0]
assert sample.name == "t4c_licenses"
assert sample.value == -1
2 changes: 1 addition & 1 deletion capella-dockerimages
Submodule capella-dockerimages updated 42 files
+19 −0 .commitlintrc.yml
+10 −0 .github/dependabot.yml
+56 −0 .github/workflows/commits.yml
+5 −5 .github/workflows/deploy-docker-images.yml
+2 −2 .github/workflows/docs.yml
+1 −1 .github/workflows/projects.yml
+22 −19 .pre-commit-config.yaml
+2 −0 Makefile
+4 −2 README.md
+26 −22 ci-templates/gitlab/diagram-cache.yml
+19 −0 docs/.readthedocs.yaml
+21 −16 docs/docs/base.md
+82 −60 docs/docs/capella/base.md
+9 −7 docs/docs/capella/build-from-source.md
+21 −12 docs/docs/capella/introduction.md
+44 −21 docs/docs/capella/readonly.md
+23 −16 docs/docs/capella/t4c/base.md
+6 −3 docs/docs/capella/t4c/exporter.md
+25 −10 docs/docs/capella/t4c/importer.md
+4 −3 docs/docs/ci-templates/github/diagram-cache.md
+16 −10 docs/docs/ci-templates/gitlab/cleanup.md
+4 −3 docs/docs/ci-templates/gitlab/diagram-cache.md
+38 −22 docs/docs/ci-templates/gitlab/image-builder.md
+8 −4 docs/docs/ci-templates/gitlab/model-validation.md
+18 −8 docs/docs/ci-templates/gitlab/release-train.md
+4 −3 docs/docs/ci-templates/gitlab/t4c-export.md
+14 −7 docs/docs/ci-templates/index.md
+37 −29 docs/docs/ease.md
+40 −24 docs/docs/eclipse/base.md
+25 −6 docs/docs/git-hooks/git-hooks.md
+53 −33 docs/docs/index.md
+6 −5 docs/docs/jupyter/index.md
+31 −20 docs/docs/papyrus/base.md
+29 −14 docs/docs/pure-variants.md
+13 −7 docs/docs/remote.md
+4 −1 jupyter-notebook/jupyter_lab_config.py
+2 −5 readonly/Dockerfile
+0 −12 readonly/prepare_workspace.sh
+1 −1 remote/startup.sh
+3 −1 t4c/backup.py
+5 −3 t4c/setup_workspace.py
+3 −3 tests/test_exporter_git.py

0 comments on commit 910d169

Please sign in to comment.