SIENTIAPDE-1174

SIENTIAPDE-1174 Update dependencies, modify image tag, and enhance metrics tracking in various activities for improved observability and performance.
This commit is contained in:
vitor-aignosi
2025-07-31 12:52:07 -03:00
parent 37d196be14
commit 2efad30304
9 changed files with 88 additions and 8 deletions

View File

@@ -5,6 +5,7 @@ asyncua
redis redis
aiokafka aiokafka
pymongo pymongo
git+ssh://git@github.com/Aignosi/sientia-dataops-library.git@1.3.5 git+ssh://git@github.com/Aignosi/sientia-dataops-library.git@1.3.6
git+ssh://git@github.com/Aignosi/sientia-mlops-library.git@0.38.5 git+ssh://git@github.com/Aignosi/sientia-mlops-library.git@0.38.5
pydruid[pandas] pydruid[pandas]
prometheus-client

View File

@@ -3,6 +3,8 @@ from temporalio import workflow, activity
with workflow.unsafe.imports_passed_through(): with workflow.unsafe.imports_passed_through():
from sientia_do.notifications.models import NotificationLevel from sientia_do.notifications.models import NotificationLevel
from sientia_do.temporal.activities.base import BaseActivity from sientia_do.temporal.activities.base import BaseActivity
from sientia_do.notifications.handlers import NotificationHandler
from sientia_do.temporal.utils.logger import Logger
from scouter.utils.quality.filters import null_values_filter, out_of_bounds_filter from scouter.utils.quality.filters import null_values_filter, out_of_bounds_filter
from typing import Any from typing import Any
import traceback import traceback
@@ -16,6 +18,10 @@ quality_gate_filters = {
class Gates(BaseActivity): class Gates(BaseActivity):
def __init__(self, logger: Logger, notification_handler: NotificationHandler):
BaseActivity.__init__(
self, logger, notification_handler, set_error_counter=True)
def apply_aggregation(self, group: DataFrame, aggr_function: str, def apply_aggregation(self, group: DataFrame, aggr_function: str,
metadata: dict[str, Any]) -> float | None | str: metadata: dict[str, Any]) -> float | None | str:
""" """

View File

@@ -57,7 +57,8 @@ class MongoDB(BaseActivity):
BaseActivity.__init__(self, BaseActivity.__init__(self,
logger=logger, logger=logger,
notification_handler=notification_handler) notification_handler=notification_handler,
set_error_counter=True)
def shutdown(self): def shutdown(self):
""" """

View File

@@ -1,8 +1,8 @@
import traceback
from temporalio import workflow, activity from temporalio import workflow, activity
with workflow.unsafe.imports_passed_through(): with workflow.unsafe.imports_passed_through():
from logging import Logger from logging import Logger
import traceback
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
from sientia_do.notifications.models import NotificationLevel from sientia_do.notifications.models import NotificationLevel
from sientia_do.temporal.activities.redis_base import Redis as RedisBase from sientia_do.temporal.activities.redis_base import Redis as RedisBase
@@ -10,6 +10,7 @@ with workflow.unsafe.imports_passed_through():
from typing import Any from typing import Any
from pandas import DataFrame from pandas import DataFrame
from datetime import datetime from datetime import datetime
from scouter import metrics
class Redis(RedisBase): class Redis(RedisBase):
@@ -136,16 +137,29 @@ class Redis(RedisBase):
return data_hold return data_hold
try: try:
to_register_metrics = []
for _, row in data.iterrows(): for _, row in data.iterrows():
value = row['value'] value = row['value']
data_hold[row['name']] = value data_hold[row['name']] = value
to_register_metrics.append(
(row['name'], value))
data_hold['timestamp'] = data['timestamp'].max() if not data.empty else \ data_hold['timestamp'] = data['timestamp'].max() if not data.empty else \
datetime.now().strftime("%Y-%m-%d %H:%M:%S") datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.set(key, data_hold, ttl=retention_time) self.set(key, data_hold, ttl=retention_time)
# Register metrics
for metric in to_register_metrics:
metrics.TAG_CHANGES_MONITOR.labels(
pod_id=metadata['pod_id'],
model_name=input_data['model_name'],
pipeline_name=input_data['schedule_name'],
tag_name=metric[0]
).set(metric[1])
data_hold_df = DataFrame(data_hold, index=[0]) data_hold_df = DataFrame(data_hold, index=[0])
data_hold_melted = data_hold_df.melt( data_hold_melted = data_hold_df.melt(
id_vars='timestamp', var_name='variable', value_name='value') id_vars='timestamp', var_name='variable', value_name='value')

15
scouter/metrics.py Normal file
View File

@@ -0,0 +1,15 @@
from prometheus_client import Gauge, Counter
CORE_LABELS = ["pod_id", "model_name", "pipeline_name"]
LABORIOUS_DATA_WRITTEN_COUNT = Counter(
"scouter_laborious_data_written_count",
"Number of writings to the database table laborious_data",
CORE_LABELS,
)
TAG_CHANGES_MONITOR = Gauge(
"scouter_tag_changes_monitor",
"Current value change of each tag",
[*CORE_LABELS, "tag_name"],
)

View File

@@ -5,6 +5,7 @@ with workflow.unsafe.imports_passed_through():
from typing import Any from typing import Any
from datetime import timedelta from datetime import timedelta
from sientia_do.temporal.utils.policies import retry_policy from sientia_do.temporal.utils.policies import retry_policy
from os import getenv
@workflow.defn(name="scouter") @workflow.defn(name="scouter")
@@ -37,7 +38,8 @@ class Scouter:
'model_id': input_data['model_id'], 'model_id': input_data['model_id'],
'model_name': input_data['model_name'], 'model_name': input_data['model_name'],
'schedule_name': input_data['schedule_name'], 'schedule_name': input_data['schedule_name'],
'workflow_name': input_data['workflow_name'] 'workflow_name': input_data['workflow_name'],
'pod_id': getenv("HOSTNAME", "localhost")
} }
} }

View File

@@ -1,5 +1,7 @@
from temporalio import workflow from temporalio import workflow
from scouter import metrics
with workflow.unsafe.imports_passed_through(): with workflow.unsafe.imports_passed_through():
from scouter.activities.activities import Activities from scouter.activities.activities import Activities
from typing import Any from typing import Any
@@ -86,6 +88,12 @@ class CoreScouter:
start_to_close_timeout=timedelta(seconds=60) start_to_close_timeout=timedelta(seconds=60)
) )
metrics.LABORIOUS_DATA_WRITTEN_COUNT.labels(
pod_id=metadata['pod_id'],
model_name=input_data['model_name'],
pipeline_name=input_data['workflow_name']
).inc()
if input_data.get('debug_data_package', False): if input_data.get('debug_data_package', False):
await workflow.execute_activity_method( await workflow.execute_activity_method(
Activities.store_data_package, Activities.store_data_package,

25
tests/test_metrics.py Normal file
View File

@@ -0,0 +1,25 @@
# tests/unit/test_metrics.py
import pytest
from prometheus_client import Counter, Gauge, Histogram
import scouter.metrics as metrics
# --- Test Functions for Each Metric (Corrected for v0.22.0 _name behavior) ---
def test_scouter_laborious_data_written_count():
"""Verify the definition of LABORIOUS_DATA_WRITTEN_COUNT."""
assert metrics.LABORIOUS_DATA_WRITTEN_COUNT is not None
assert isinstance(metrics.LABORIOUS_DATA_WRITTEN_COUNT, Counter)
assert metrics.LABORIOUS_DATA_WRITTEN_COUNT._name == "scouter_laborious_data_written_count"
assert set(metrics.LABORIOUS_DATA_WRITTEN_COUNT._labelnames) == {
"pod_id", "model_name", "pipeline_name"}
def test_scouter_tag_changes_monitor():
"""Verify the definition of TAG_CHANGES_MONITOR."""
assert metrics.TAG_CHANGES_MONITOR is not None
assert isinstance(metrics.TAG_CHANGES_MONITOR, Gauge)
assert metrics.TAG_CHANGES_MONITOR._name == "scouter_tag_changes_monitor"
assert set(metrics.TAG_CHANGES_MONITOR._labelnames) == {
"pod_id", "model_name", "pipeline_name", "tag_name"}

View File

@@ -11,7 +11,7 @@ image:
# This sets the pull policy for images. # This sets the pull policy for images.
pullPolicy: Always pullPolicy: Always
# Overrides the image tag whose default is the chart appVersion. # Overrides the image tag whose default is the chart appVersion.
tag: "0.2.7" tag: "0.3.0"
# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ # This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
imagePullSecrets: imagePullSecrets:
@@ -111,14 +111,20 @@ tolerations: []
affinity: {} affinity: {}
service: {} services:
metrics:
enabled: true
type: ClusterIP
port: 9090
targetPort: 9090
name: metrics
env: env:
# Entrypoint variables # Entrypoint variables
- name: GITHUB_REPO_URL - name: GITHUB_REPO_URL
value: "git@github.com:Aignosi/sientia-dataops-scouter_temporal.git" value: "git@github.com:Aignosi/sientia-dataops-scouter_temporal.git"
- name: GITHUB_BRANCH - name: GITHUB_BRANCH
value: "SIENTIAPDE-1172-criar-pipeline-de-alertas-orquestrador" value: "SIENTIAPDE-1174-mapear-e-implementar-metricas-a-serem-criadas"
- name: PYTHON_APP - name: PYTHON_APP
value: "scouter.worker.worker" value: "scouter.worker.worker"
@@ -160,6 +166,8 @@ env:
- name: LOG_LEVEL - name: LOG_LEVEL
value: "DEBUG" value: "DEBUG"
- name: HTTP_METRICS_PORT
value: "9090"
- name: PROJECT_NAME - name: PROJECT_NAME
value: "sientia-scouter" value: "sientia-scouter"