diff --git a/numalogic/_constants.py b/numalogic/_constants.py index 8e4eee33..c55df908 100644 --- a/numalogic/_constants.py +++ b/numalogic/_constants.py @@ -18,6 +18,9 @@ BASE_CONF_DIR = os.path.join(BASE_DIR, "config") DEFAULT_BASE_CONF_PATH = os.path.join(BASE_CONF_DIR, "default-configs", "config.yaml") +DEFAULT_METRICS_CONF_PATH = os.path.join( + BASE_CONF_DIR, "default-configs", "numalogic_udf_metrics.yaml" +) DEFAULT_APP_CONF_PATH = os.path.join(BASE_CONF_DIR, "app-configs", "config.yaml") DEFAULT_METRICS_PORT = 8490 NUMALOGIC_METRICS = "numalogic_metrics" diff --git a/numalogic/monitoring/__init__.py b/numalogic/monitoring/__init__.py deleted file mode 100644 index 171a76d8..00000000 --- a/numalogic/monitoring/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2022 The Numaproj Authors. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import logging - -from prometheus_client import start_http_server - -_LOGGER = logging.getLogger(__name__) -_LOGGER.addHandler(logging.NullHandler()) - - -def start_metrics_server(port: int) -> None: - """ - Starts the Prometheus monitoring server. - - Args: - port: Port number - """ - _LOGGER.info("Starting Prometheus monitoring server on port: %s", port) - start_http_server(port) diff --git a/numalogic/monitoring/metrics.py b/numalogic/monitoring/metrics.py deleted file mode 100644 index 178aac8b..00000000 --- a/numalogic/monitoring/metrics.py +++ /dev/null @@ -1,120 +0,0 @@ -import logging -from typing import Optional -from collections.abc import Sequence - -from prometheus_client import Counter, Info, Summary, Gauge - -_LOGGER = logging.getLogger(__name__) - - -class _BaseMetric: - __slots__ = ("name", "description", "label_keys") - - """ - Base class for metrics. - - Args: - name: Name of the metric - description: Description of the metric - label_keys: List of labels - """ - - def __init__(self, name: str, description: str, label_keys: Optional[list[str]]) -> None: - self.name = name - self.description = description - self.label_keys = label_keys - - -class PromCounterMetric(_BaseMetric): - """Class is used to create a counter object and increment it.""" - - __slots__ = "counter" - - def __init__(self, name: str, description: str, label_keys: list[str]) -> None: - super().__init__(name, description, label_keys) - self.counter = Counter(name, description, label_keys) - - def increment_counter(self, *label_values: Sequence[str], amount: int = 1) -> None: - """ - Utility function is used to increment the counter. - - Args: - *label_values: List of labels - amount: Amount to increment the counter by - """ - if len(label_values) != len(self.label_keys): - raise ValueError(f"Labels length mismatch with the definition: {self.label_keys}") - self.counter.labels(*label_values).inc(amount=amount) - - -class PromInfoMetric(_BaseMetric): - """Class is used to create an info object and increment it.""" - - __slots__ = "info" - - def __init__(self, name: str, description: str, label_keys: Optional[list[str]]) -> None: - super().__init__(name, description, label_keys) - self.info = Info(name, description, label_keys) - - def add_info( - self, - *label_values: Sequence[str], - data: dict, - ) -> None: - """ - Utility function is used to increment the info. - - Args: - *label_values: List of labels - data: Dictionary of data - """ - if len(label_values) != len(self.label_keys): - raise ValueError(f"Labels length mismatch with the definition: {self.label_keys}") - self.info.labels(*label_values).info(data) - - -class PromSummaryMetric(_BaseMetric): - """Class is used to create a histogram object and increment it.""" - - __slots__ = "summary" - - def __init__(self, name: str, description: str, label_keys: Optional[list[str]]) -> None: - super().__init__(name, description, label_keys) - self.summary = Summary(name, description, label_keys) - - def add_observation(self, *label_values, value: float) -> None: - """ - Utility function is to update the summary value with the given value. - - Args: - *label_values: List of labels - value: Value to be updated - """ - if len(label_values) != len(self.label_keys): - raise ValueError(f"Labels length mismatch with the definition: {self.label_keys}") - self.summary.labels(*label_values).observe(amount=value) - - -class PromGaugeMetric(_BaseMetric): - """Class is used to create an info object and increment it.""" - - __slots__ = "info" - - def __init__(self, name: str, description: str, label_keys: Optional[list[str]]) -> None: - super().__init__(name, description, label_keys) - self.info = Gauge(name, description, label_keys) - - def set_gauge( - self, - *label_values: Sequence[str], - data: float, - ) -> None: - """ - Utility function is used to increment the info. - Args: - *label_values: List of labels - data: float data. - """ - if len(label_values) != len(self.label_keys): - raise ValueError(f"Labels mismatch with the definition: {self.label_keys}") - self.info.labels(*label_values).set(data) diff --git a/numalogic/tools/exceptions.py b/numalogic/tools/exceptions.py index abb359ec..bd7d001d 100644 --- a/numalogic/tools/exceptions.py +++ b/numalogic/tools/exceptions.py @@ -70,6 +70,12 @@ class RedisRegistryError(Exception): pass +class MetricConfigError(Exception): + """Raised when a numalogic udf metric config is not valid.""" + + pass + + class DynamoDBRegistryError(Exception): """Base class for all exceptions raised by the DynamoDBRegistry class.""" diff --git a/numalogic/transforms/_stateless.py b/numalogic/transforms/_stateless.py index 0ecde53f..129337db 100644 --- a/numalogic/transforms/_stateless.py +++ b/numalogic/transforms/_stateless.py @@ -91,6 +91,12 @@ def _validate_args( if len(lower) != len(upper): raise ValueError("lower and upper should have the same length.") lower, upper = np.asarray(lower, dtype=np.float32), np.asarray(upper, dtype=np.float32) + elif lower is not None and upper is not None: + if type(lower) is not type(upper): + if isinstance(lower, Sequence): + upper = np.asarray(upper, dtype=np.float32) + else: + lower = np.asarray(lower, dtype=np.float32) if upper is not None and lower is not None and np.any(lower > upper): raise ValueError("lower value should be less than or equal to upper value") return lower, upper diff --git a/numalogic/udfs/__init__.py b/numalogic/udfs/__init__.py index 98492c2e..5d5c4fdb 100644 --- a/numalogic/udfs/__init__.py +++ b/numalogic/udfs/__init__.py @@ -5,6 +5,7 @@ from numalogic._constants import BASE_DIR from numalogic.udfs._base import NumalogicUDF from numalogic.udfs._config import StreamConf, PipelineConf, MLPipelineConf, load_pipeline_conf +from numalogic.udfs._metrics_utility import MetricsLoader from numalogic.udfs.factory import UDFFactory, ServerFactory from numalogic.udfs.payloadtx import PayloadTransformer from numalogic.udfs.inference import InferenceUDF @@ -23,6 +24,11 @@ def set_logger() -> None: logging.getLogger("root").setLevel(logging.DEBUG) +def set_metrics(conf_file: str) -> None: + """Sets the metrics for the UDFs.""" + MetricsLoader().load_metrics(config_file_path=conf_file) + + __all__ = [ "NumalogicUDF", "PayloadTransformer", @@ -40,4 +46,6 @@ def set_logger() -> None: "load_pipeline_conf", "ServerFactory", "set_logger", + "set_metrics", + "MetricsLoader", ] diff --git a/numalogic/udfs/__main__.py b/numalogic/udfs/__main__.py index a29c46f9..2fcb8ab7 100644 --- a/numalogic/udfs/__main__.py +++ b/numalogic/udfs/__main__.py @@ -3,16 +3,24 @@ import sys from typing import Final -from numalogic._constants import DEFAULT_BASE_CONF_PATH, DEFAULT_APP_CONF_PATH, DEFAULT_METRICS_PORT +from numaprom.monitoring import start_metrics_server + +from numalogic._constants import ( + DEFAULT_BASE_CONF_PATH, + DEFAULT_APP_CONF_PATH, + DEFAULT_METRICS_PORT, + DEFAULT_METRICS_CONF_PATH, +) from numalogic.connectors.redis import get_redis_client_from_conf -from numalogic.monitoring import start_metrics_server -from numalogic.udfs import load_pipeline_conf, UDFFactory, ServerFactory, set_logger +from numalogic.udfs import load_pipeline_conf, UDFFactory, ServerFactory, set_logger, set_metrics LOGGER = logging.getLogger(__name__) BASE_CONF_FILE_PATH: Final[str] = os.getenv("BASE_CONF_PATH", default=DEFAULT_BASE_CONF_PATH) APP_CONF_FILE_PATH: Final[str] = os.getenv("APP_CONF_PATH", default=DEFAULT_APP_CONF_PATH) METRICS_PORT: Final[int] = int(os.getenv("METRICS_PORT", default=DEFAULT_METRICS_PORT)) +METRICS_ENABLED: Final[bool] = bool(int(os.getenv("METRICS_ENABLED", default="1"))) +METRICS_CONF_PATH: Final[str] = os.getenv("METRICS_CONF_PATH", default=DEFAULT_METRICS_CONF_PATH) def init_server(step: str, server_type: str): @@ -43,8 +51,9 @@ def start_server() -> None: LOGGER.info("Running %s on %s server", step, server_type) - # Start the metrics server at port METRICS_PORT = 8490 - start_metrics_server(METRICS_PORT) + if METRICS_ENABLED: + set_metrics(conf_file=METRICS_CONF_PATH) + start_metrics_server(METRICS_PORT) server = init_server(step, server_type) server.start() diff --git a/numalogic/udfs/_metrics.py b/numalogic/udfs/_metrics.py deleted file mode 100644 index 2f793f7b..00000000 --- a/numalogic/udfs/_metrics.py +++ /dev/null @@ -1,182 +0,0 @@ -from collections.abc import Sequence - -from prometheus_client import Histogram - -from numalogic.monitoring.metrics import ( - PromCounterMetric, - PromInfoMetric, - PromSummaryMetric, - PromGaugeMetric, -) - -# Define metrics - -# COUNTERS -SOURCE_COUNTER = PromCounterMetric( - "numalogic_artifact_source_counter", - "Count artifact source calls", - ["artifact_source", "source", "vertex", "composite_key", "config_id", "pipeline_id"], -) - -INSUFFICIENT_DATA_COUNTER = PromCounterMetric( - "numalogic_insufficient_data_counter", - "Count insufficient data while Training", - ["source", "composite_key", "config_id", "pipeline_id"], -) -MODEL_STATUS_COUNTER = PromCounterMetric( - "numalogic_new_model_counter", - "Count status of the model", - ["source", "status", "vertex", "composite_key", "config_id", "pipeline_id"], -) - -DATASHAPE_ERROR_COUNTER = PromCounterMetric( - "numalogic_datashape_error_counter", - "Count datashape errors in preprocess", - ["source", "vertex", "composite_key", "config_id", "pipeline_id"], -) -MSG_DROPPED_COUNTER = PromCounterMetric( - "numalogic_msg_dropped_counter", - "Count dropped msgs", - ["source", "vertex", "composite_key", "config_id", "pipeline_id"], -) - -REDIS_ERROR_COUNTER = PromCounterMetric( - "numalogic_redis_error_counter", - "Count redis errors", - ["source", "vertex", "composite_key", "config_id", "pipeline_id"], -) -EXCEPTION_COUNTER = PromCounterMetric( - "numalogic_exception_counter", - "Count exceptions", - ["source", "vertex", "composite_key", "config_id", "pipeline_id"], -) -RUNTIME_ERROR_COUNTER = PromCounterMetric( - "numalogic_runtime_error_counter", - "Count runtime errors", - ["source", "vertex", "composite_key", "config_id", "pipeline_id"], -) - -FETCH_EXCEPTION_COUNTER = PromCounterMetric( - "numalogic_fetch_exception_counter", - "count exceptions during fetch call", - ["source", "composite_key", "config_id", "pipeline_id"], -) - -MSG_IN_COUNTER = PromCounterMetric( - "numalogic_msg_in_counter", - "Count msgs flowing in", - ["source", "vertex", "composite_key", "config_id", "pipeline_id"], -) -MSG_PROCESSED_COUNTER = PromCounterMetric( - "numalogic_msg_processed_counter", - "Count msgs processed", - ["source", "vertex", "composite_key", "config_id", "pipeline_id"], -) - -# SUMMARY -DATAFRAME_SHAPE_SUMMARY = PromSummaryMetric( - "numalogic_dataframe_shape_summary", - "len of dataframe for training", - ["source", "composite_key", "config_id", "pipeline_id"], -) -NAN_SUMMARY = PromSummaryMetric( - "numalogic_nan_summary", - "Count nan's in train data", - ["source", "composite_key", "config_id", "pipeline_id"], -) -INF_SUMMARY = PromSummaryMetric( - "numalogic_inf_summary", - "Count inf's in train data", - ["source", "composite_key", "config_id", "pipeline_id"], -) -FETCH_TIME_SUMMARY = PromSummaryMetric( - "numalogic_fetch_time_summary", - "Train data fetch time", - ["source", "composite_key", "config_id", "pipeline_id"], -) -# Gauge Metrics -RECORDED_DATA_GAUGE = PromGaugeMetric( - "numalogic_recorded_value_gauge", - "Gauge metric to observe the mean value of the window", - ["source", "vertex", "composite_key", "config_id", "pipeline_id", "metric_name"], -) - -# Info -MODEL_INFO = PromInfoMetric( - "numalogic_model_info", "Model info", ["source", "composite_key", "config_id", "pipeline_id"] -) - -# HISTOGRAM -buckets = ( - 0.001, - 0.002, - 0.003, - 0.004, - 0.005, - 0.006, - 0.007, - 0.008, - 0.009, - 0.01, - 0.025, - 0.05, - 0.075, - 0.1, - 0.25, -) - -UDF_TIME = Histogram( - "numalogic_udf_time_histogram", - "Histogram for udf processing time", - buckets=buckets, -) - - -# helper functions - - -def _increment_counter(counter: PromCounterMetric, labels: Sequence[str], amount: int = 1) -> None: - """ - Utility function is used to increment the counter. - - Args: - counter: Counter object - labels: Sequence of labels - amount: Amount to increment the counter by - """ - counter.increment_counter(*labels, amount=amount) - - -def _add_info(info: PromInfoMetric, labels: Sequence[str], data: dict) -> None: - """ - Utility function is used to add the info. - - Args: - info: Info object - labels: Sequence of labels - data: Dictionary of data - """ - info.add_info(*labels, data=data) - - -def _add_summary(summary: PromSummaryMetric, labels: Sequence[str], data: float) -> None: - """ - Utility function is used to add the summary. - - Args: - summary: Summary object - labels: Sequence of labels - data: Summary value - """ - summary.add_observation(*labels, value=data) - - -def _set_gauge(gauge: PromGaugeMetric, labels: Sequence[str], data: float) -> None: - """ - Utility function is used to add the info. - Args: - gauge: Gauge object - labels: Sequence of labels - data: data. - """ - gauge.set_gauge(*labels, data=data) diff --git a/numalogic/udfs/_metrics_utility.py b/numalogic/udfs/_metrics_utility.py new file mode 100644 index 00000000..a7345131 --- /dev/null +++ b/numalogic/udfs/_metrics_utility.py @@ -0,0 +1,128 @@ +from typing import Optional, TypeVar + +from numalogic import LOGGER +from numalogic.tools.exceptions import MetricConfigError +from numalogic.tools.types import Singleton +from numaprom.monitoring.metrics import BaseMetric +from numaprom.monitoring.utility import get_metric +from omegaconf import OmegaConf + +metrics_t = TypeVar("metrics_t", bound=BaseMetric, covariant=True) + + +def create_metrics_from_config_file(config_file_path: str) -> dict[str, metrics_t]: + config = OmegaConf.load(config_file_path) + metrics = {} + for metric_config in config.get("numalogic_metrics", []): + metric_type = metric_config["type"] + for metric in metric_config["metrics"]: + name = metric["name"] + description = metric.get("description", "") + label_pairs = metric.get("label_pairs", {}) + metrics[name] = get_metric(metric_type, name, description, label_pairs) + return metrics + + +class MetricsLoader(metaclass=Singleton): + _instance = None + _metrics = None + + def __new__(cls, *args, **kwargs): + if not cls._instance: + cls._instance = super().__new__(cls, *args, **kwargs) + return cls._instance + + def load_metrics(self, config_file_path: str): + if not self._metrics: + if config_file_path is None: + raise ValueError("file path is required to load metrics") + self._metrics = create_metrics_from_config_file(config_file_path) + + def get_metrics(self) -> dict[str, metrics_t]: + return self._metrics + + +_METRICS_LOADER = MetricsLoader() + + +# helper functions +def _increment_counter( + counter: str, labels: Optional[dict], amount: int = 1, is_enabled=True +) -> None: + """ + Utility function is used to increment the counter. + + Args: + counter: counter metric name + labels: dict of label keys, value pair + amount: Amount to increment the counter by + """ + if not is_enabled: + return + + try: + _metrics = _METRICS_LOADER.get_metrics() + _metrics[counter].increment_counter(labels=labels, amount=amount) + except MetricConfigError: + LOGGER.exception("Problem loading initializing the config") + except KeyError: + LOGGER.error(f"Metric {counter} not found in metrics") + + +def _add_info(info: str, labels: Optional[dict], data: dict, is_enabled=True) -> None: + """ + Utility function is used to add the info. + + Args: + info: Info metric name + labels: dict of label keys, value pair + data: Dictionary of data + """ + if not is_enabled: + return + try: + _metrics = _METRICS_LOADER.get_metrics() + _metrics[info].add_info(labels=labels, data=data) + except MetricConfigError: + LOGGER.exception("Problem loading initializing the config") + except KeyError: + LOGGER.error(f"Metric {info} not found in metrics") + + +def _add_summary(summary: str, labels: Optional[dict], data: float, is_enabled=True) -> None: + """ + Utility function is used to add the summary. + + Args: + summary: Summary metric name + labels: dict of labels key, value pair + data: Summary value + """ + if not is_enabled: + return + try: + _metrics = _METRICS_LOADER.get_metrics() + _metrics[summary].add_observation(labels=labels, value=data) + except MetricConfigError: + LOGGER.exception("Problem loading initializing the config") + except KeyError: + LOGGER.error(f"Metric {summary} not found in metrics") + + +def _set_gauge(gauge: str, labels: Optional[dict], data: float, is_enabled=True) -> None: + """ + Utility function is used to add the info. + Args: + gauge: Gauge metric name + labels: dict of label keys, value pair + data: data. + """ + if not is_enabled: + return + try: + _metrics = _METRICS_LOADER.get_metrics() + _metrics[gauge].set_gauge(labels=labels, data=data) + except MetricConfigError: + LOGGER.exception("Problem loading initializing the config") + except KeyError: + LOGGER.error(f"Metric {gauge} not found in metrics") diff --git a/numalogic/udfs/factory.py b/numalogic/udfs/factory.py index 096a181f..c6244ea7 100644 --- a/numalogic/udfs/factory.py +++ b/numalogic/udfs/factory.py @@ -28,7 +28,6 @@ class UDFFactory: from numalogic.udfs.staticthresh import StaticThresholdUDF nl_udf_t = TypeVar("nl_udf_t", bound=NumalogicUDF, covariant=True) - _UDF_MAP: ClassVar[dict[str, type[NumalogicUDF]]] = { "mlpipeline": PayloadTransformer, "preprocess": PreprocessUDF, diff --git a/numalogic/udfs/inference.py b/numalogic/udfs/inference.py index 0f19d7b8..86028cb5 100644 --- a/numalogic/udfs/inference.py +++ b/numalogic/udfs/inference.py @@ -14,18 +14,13 @@ from numalogic.tools.types import artifact_t, redis_client_t from numalogic.udfs._base import NumalogicUDF from numalogic.udfs._config import PipelineConf + from numalogic.udfs._logger import configure_logger, log_data_payload_values -from numalogic.udfs._metrics import ( - RUNTIME_ERROR_COUNTER, - MSG_PROCESSED_COUNTER, - MSG_IN_COUNTER, - UDF_TIME, - _increment_counter, -) +from numalogic.udfs._metrics_utility import _increment_counter from numalogic.udfs.entities import StreamPayload, Status from numalogic.udfs.tools import ( _load_artifact, - _update_info_metric, + _update_gauge_metric, get_trainer_message, get_static_thresh_message, ) @@ -36,6 +31,7 @@ LOCAL_CACHE_TTL = int(os.getenv("LOCAL_CACHE_TTL", "3600")) LOCAL_CACHE_SIZE = int(os.getenv("LOCAL_CACHE_SIZE", "10000")) LOAD_LATEST = os.getenv("LOAD_LATEST", "false").lower() == "true" +METRICS_ENABLED = bool(int(os.getenv("METRICS_ENABLED", default="1"))) class InferenceUDF(NumalogicUDF): @@ -89,7 +85,6 @@ def compute(cls, model: artifact_t, input_: npt.NDArray[float], **_) -> npt.NDAr raise RuntimeError("Model forward pass failed!") from err return np.ascontiguousarray(recon_err).squeeze(0) - @UDF_TIME.time() def exec(self, keys: list[str], datum: Datum) -> Messages: """ Perform inference on the input data. @@ -108,14 +103,18 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: # Construct payload object json_data_payload = orjson.loads(datum.value) payload = StreamPayload(**json_data_payload) - _metric_label_values = ( - payload.metadata["numalogic_opex_tags"]["source"], - self._vtx, - ":".join(payload.composite_keys), - payload.config_id, - payload.pipeline_id, + _metric_label_values = { + "source": payload.metadata["numalogic_opex_tags"]["source"], + "vertex": self._vtx, + "composite_key": ":".join(payload.composite_keys), + "config_id": payload.config_id, + "pipeline_id": payload.pipeline_id, + } + _increment_counter( + counter="MSG_IN_COUNTER", + labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) - _increment_counter(counter=MSG_IN_COUNTER, labels=_metric_label_values) _stream_conf = self.get_stream_conf(payload.config_id) _conf = _stream_conf.ml_pipelines[payload.pipeline_id] @@ -142,9 +141,13 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: # Perform inference try: x_inferred = self.compute(artifact_data.artifact, payload.get_data()) - _update_info_metric(x_inferred, payload.metrics, _metric_label_values) + _update_gauge_metric(x_inferred, payload.metrics, _metric_label_values) except RuntimeError: - _increment_counter(counter=RUNTIME_ERROR_COUNTER, labels=_metric_label_values) + _increment_counter( + counter="RUNTIME_ERROR_COUNTER", + labels=_metric_label_values, + is_enabled=METRICS_ENABLED, + ) logger.exception( "Runtime inference error!", keys=payload.composite_keys, @@ -174,9 +177,13 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: # Send trainer message if artifact is stale if status == Status.ARTIFACT_STALE: logger.info("Inference artifact found is stale") - msgs.append(get_trainer_message(keys, _stream_conf, payload, *_metric_label_values)) + msgs.append(get_trainer_message(keys, _stream_conf, payload, **_metric_label_values)) - _increment_counter(counter=MSG_PROCESSED_COUNTER, labels=_metric_label_values) + _increment_counter( + counter="MSG_PROCESSED_COUNTER", + labels=_metric_label_values, + is_enabled=METRICS_ENABLED, + ) msgs.append(Message(keys=keys, value=payload.to_json(), tags=["postprocess"])) logger.info( diff --git a/numalogic/udfs/payloadtx.py b/numalogic/udfs/payloadtx.py index 7251a433..c5b05513 100644 --- a/numalogic/udfs/payloadtx.py +++ b/numalogic/udfs/payloadtx.py @@ -1,3 +1,4 @@ +import os import time from typing import Optional @@ -9,6 +10,9 @@ from numalogic.udfs import NumalogicUDF from numalogic.udfs._config import PipelineConf from numalogic.udfs._logger import configure_logger, log_data_payload_values +from numalogic.udfs._metrics_utility import _increment_counter + +METRICS_ENABLED = bool(int(os.getenv("METRICS_ENABLED", default="1"))) _struct_log = configure_logger() @@ -54,6 +58,17 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: logger.exception("Error while decoding input json") return Messages(Message.to_drop()) + _metric_label_values = { + "vertex": self._vtx, + "composite_key": ":".join(keys), + "config_id": data_payload["config_id"], + "pipeline_id": data_payload["pipeline_id"], + } + _increment_counter( + counter="MSG_IN_COUNTER", + labels=_metric_label_values, + is_enabled=METRICS_ENABLED, + ) _stream_conf = self.get_stream_conf(data_payload["config_id"]) # create a new message for each ML pipeline @@ -68,4 +83,9 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: keys=keys, execution_time_ms=round((time.perf_counter() - _start_time) * 1000, 4), ) + _increment_counter( + counter="MSG_PROCESSED_COUNTER", + labels=_metric_label_values, + is_enabled=METRICS_ENABLED, + ) return messages diff --git a/numalogic/udfs/postprocess.py b/numalogic/udfs/postprocess.py index 540c503a..3f7e629f 100644 --- a/numalogic/udfs/postprocess.py +++ b/numalogic/udfs/postprocess.py @@ -22,13 +22,7 @@ from numalogic.udfs import NumalogicUDF from numalogic.udfs._config import PipelineConf, MLPipelineConf from numalogic.udfs._logger import configure_logger, log_data_payload_values -from numalogic.udfs._metrics import ( - RUNTIME_ERROR_COUNTER, - MSG_PROCESSED_COUNTER, - MSG_IN_COUNTER, - UDF_TIME, - _increment_counter, -) +from numalogic.udfs._metrics_utility import _increment_counter from numalogic.udfs.entities import StreamPayload, Header, Status, OutputPayload from numalogic.udfs.tools import _load_artifact, get_trainer_message, get_static_thresh_message @@ -36,6 +30,7 @@ LOCAL_CACHE_TTL = int(os.getenv("LOCAL_CACHE_TTL", "3600")) LOCAL_CACHE_SIZE = int(os.getenv("LOCAL_CACHE_SIZE", "10000")) LOAD_LATEST = os.getenv("LOAD_LATEST", "false").lower() == "true" +METRICS_ENABLED = bool(int(os.getenv("METRICS_ENABLED", default="1"))) SCORE_PREFIX = os.getenv("SCORE_PREFIX", "unified") _struct_log = configure_logger() @@ -71,7 +66,6 @@ def __init__( ) self.postproc_factory = PostprocessFactory() - @UDF_TIME.time() def exec(self, keys: list[str], datum: Datum) -> Messages: """ The postprocess function here receives data from the previous udf. @@ -92,17 +86,17 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: # Construct payload object json_payload = orjson.loads(datum.value) payload = StreamPayload(**json_payload) - _metric_label_values = ( - payload.composite_keys, - self._vtx, - ":".join(payload.composite_keys), - payload.config_id, - payload.pipeline_id, - ) - + _metric_label_values = { + "source": ":".join(payload.composite_keys), + "vertex": self._vtx, + "composite_key": ":".join(payload.composite_keys), + "config_id": payload.config_id, + "pipeline_id": payload.pipeline_id, + } _increment_counter( - counter=MSG_IN_COUNTER, + counter="MSG_IN_COUNTER", labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) # load configs @@ -162,7 +156,9 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: a_adjusted, y_unified, y_features = self._adjust_score(_conf, a_unified, payload) except RuntimeError: - _increment_counter(RUNTIME_ERROR_COUNTER, _metric_label_values) + _increment_counter( + "RUNTIME_ERROR_COUNTER", _metric_label_values, is_enabled=METRICS_ENABLED + ) logger.exception( "Runtime postprocess error!", uuid=payload.uuid, @@ -201,8 +197,9 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: ) _increment_counter( - MSG_PROCESSED_COUNTER, + "MSG_PROCESSED_COUNTER", labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) logger.info( diff --git a/numalogic/udfs/preprocess.py b/numalogic/udfs/preprocess.py index d91de0ba..8efe0db1 100644 --- a/numalogic/udfs/preprocess.py +++ b/numalogic/udfs/preprocess.py @@ -12,26 +12,17 @@ from numalogic._constants import NUMALOGIC_METRICS from numalogic.config import PreprocessFactory, RegistryFactory from numalogic.udfs._logger import configure_logger, log_data_payload_values -from numalogic.udfs._metrics import ( - DATASHAPE_ERROR_COUNTER, - MSG_DROPPED_COUNTER, - SOURCE_COUNTER, - MSG_PROCESSED_COUNTER, - MSG_IN_COUNTER, - RUNTIME_ERROR_COUNTER, - UDF_TIME, - _increment_counter, -) from numalogic.registry import LocalLRUCache from numalogic.tools.types import redis_client_t, artifact_t from numalogic.udfs import NumalogicUDF from numalogic.udfs._config import PipelineConf +from numalogic.udfs._metrics_utility import _increment_counter from numalogic.udfs.entities import Status, Header from numalogic.udfs.tools import ( make_stream_payload, get_df, _load_artifact, - _update_info_metric, + _update_gauge_metric, get_trainer_message, get_static_thresh_message, ) @@ -40,7 +31,7 @@ LOCAL_CACHE_TTL = int(os.getenv("LOCAL_CACHE_TTL", "3600")) LOCAL_CACHE_SIZE = int(os.getenv("LOCAL_CACHE_SIZE", "10000")) LOAD_LATEST = os.getenv("LOAD_LATEST", "false").lower() == "true" - +METRICS_ENABLED = bool(int(os.getenv("METRICS_ENABLED", default="1"))) _struct_log = configure_logger() @@ -83,7 +74,6 @@ def _load_model_from_config(self, preprocess_cfg): preproc_clfs.append(_clf) return make_pipeline(*preproc_clfs) - @UDF_TIME.time() def exec(self, keys: list[str], datum: Datum) -> Messages: """ The preprocess function here receives data from the data source. @@ -123,25 +113,31 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: ): source = data_payload["metadata"]["numalogic_opex_tags"]["source"] - _metric_label_values = ( - source, - self._vtx, - ":".join(keys), - data_payload["config_id"], - data_payload.get("pipeline_id", "default"), - ) + _metric_label_values = { + "source": source, + "vertex": self._vtx, + "composite_key": ":".join(keys), + "config_id": data_payload["config_id"], + "pipeline_id": data_payload.get("pipeline_id", "default"), + } - _increment_counter(counter=MSG_IN_COUNTER, labels=_metric_label_values) + _increment_counter( + counter="MSG_IN_COUNTER", + labels=_metric_label_values, + is_enabled=METRICS_ENABLED, + ) # Drop message if dataframe shape conditions are not met if raw_df.shape[0] < _stream_conf.window_size or raw_df.shape[1] != len(_conf.metrics): logger.critical("Dataframe shape conditions not met ", raw_df_shape=raw_df.shape) _increment_counter( - counter=DATASHAPE_ERROR_COUNTER, + counter="DATASHAPE_ERROR_COUNTER", labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) _increment_counter( - counter=MSG_DROPPED_COUNTER, + counter="MSG_DROPPED_COUNTER", labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) return Messages(Message.to_drop()) @@ -176,7 +172,11 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: # Model will not be in registry else: # Load configuration for the config_id - _increment_counter(SOURCE_COUNTER, labels=("config", *_metric_label_values)) + _increment_counter( + "SOURCE_COUNTER", + labels=({"artifact_source": "config"} | _metric_label_values), + is_enabled=METRICS_ENABLED, + ) preproc_clf = self._load_model_from_config(_conf.numalogic_conf.preprocess) payload = replace(payload, status=Status.ARTIFACT_FOUND) try: @@ -187,7 +187,7 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: payload, metrics=_get_updated_metrics(payload.metrics, x_scaled.shape) ) - _update_info_metric(x_scaled, payload.metrics, _metric_label_values) + _update_gauge_metric(x_scaled, payload.metrics, _metric_label_values) payload = replace( payload, data=x_scaled, @@ -203,8 +203,9 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: ) except RuntimeError: _increment_counter( - counter=RUNTIME_ERROR_COUNTER, + counter="RUNTIME_ERROR_COUNTER", labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) logger.exception( "Runtime preprocess error!", @@ -218,15 +219,16 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: status=Status.RUNTIME_ERROR, ) msgs = Messages( - get_trainer_message(keys, _stream_conf, payload, *_metric_label_values), + get_trainer_message(keys, _stream_conf, payload, **_metric_label_values), ) if _conf.numalogic_conf.score.adjust: msgs.append(get_static_thresh_message(keys, payload)) return msgs _increment_counter( - counter=MSG_PROCESSED_COUNTER, + counter="MSG_PROCESSED_COUNTER", labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) return Messages(Message(keys=keys, value=payload.to_json(), tags=["inference"])) diff --git a/numalogic/udfs/staticthresh.py b/numalogic/udfs/staticthresh.py index 1be7e3ab..51bbf213 100644 --- a/numalogic/udfs/staticthresh.py +++ b/numalogic/udfs/staticthresh.py @@ -10,9 +10,11 @@ import numpy.typing as npt from numalogic.udfs._logger import configure_logger, log_data_payload_values +from numalogic.udfs._metrics_utility import _increment_counter from numalogic.udfs.entities import StreamPayload, OutputPayload +from numalogic.udfs.tools import _update_gauge_metric - +METRICS_ENABLED = bool(int(os.getenv("METRICS_ENABLED", default="1"))) SCORE_PREFIX = os.getenv("SCORE_PREFIX", "unified") _struct_log = configure_logger() @@ -45,7 +47,18 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: payload = StreamPayload(**json_data_payload) conf = self.get_ml_pipeline_conf(payload.config_id, payload.pipeline_id) adjust_conf = conf.numalogic_conf.score.adjust - + _metric_label_values = { + "source": ":".join(payload.composite_keys), + "vertex": self._vtx, + "composite_key": ":".join(payload.composite_keys), + "config_id": payload.config_id, + "pipeline_id": payload.pipeline_id, + } + _increment_counter( + counter="MSG_IN_COUNTER", + labels=_metric_label_values, + is_enabled=METRICS_ENABLED, + ) logger = _struct_log.bind(udf_vertex=self._vtx) logger = log_data_payload_values(logger, json_data_payload) @@ -58,9 +71,13 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: input_=payload.get_data(original=True, metrics=list(adjust_conf.upper_limits)), adjust_conf=adjust_conf, ) + _update_gauge_metric(y_features, list(adjust_conf.upper_limits), _metric_label_values) y_unified = self.compute_unified_score(y_features, adjust_conf.feature_agg) except RuntimeError: logger.exception("Error occurred while computing static anomaly scores") + _increment_counter( + "RUNTIME_ERROR_COUNTER", _metric_label_values, is_enabled=METRICS_ENABLED + ) return Messages(Message.to_drop()) out_payload = OutputPayload( @@ -79,6 +96,11 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: y_unified=y_unified, y_features=y_features, ) + _increment_counter( + counter="MSG_PROCESSED_COUNTER", + labels=_metric_label_values, + is_enabled=METRICS_ENABLED, + ) return Messages(Message(keys=keys, value=out_payload.to_json(), tags=["output"])) @staticmethod diff --git a/numalogic/udfs/tools.py b/numalogic/udfs/tools.py index c86b4d6a..b450fad7 100644 --- a/numalogic/udfs/tools.py +++ b/numalogic/udfs/tools.py @@ -1,3 +1,4 @@ +import os from dataclasses import replace import time from typing import Optional, NamedTuple @@ -14,18 +15,10 @@ from numalogic.tools.types import KEYS, redis_client_t from numalogic.udfs._config import StreamConf from numalogic.udfs._logger import configure_logger +from numalogic.udfs._metrics_utility import _set_gauge, _increment_counter, _add_info from numalogic.udfs.entities import StreamPayload, TrainerPayload -from numalogic.udfs._metrics import ( - SOURCE_COUNTER, - MODEL_INFO, - REDIS_ERROR_COUNTER, - EXCEPTION_COUNTER, - _increment_counter, - _add_info, - RECORDED_DATA_GAUGE, - _set_gauge, - MODEL_STATUS_COUNTER, -) + +METRICS_ENABLED = bool(int(os.getenv("METRICS_ENABLED", default="1"))) _struct_log = configure_logger() @@ -62,24 +55,22 @@ def get_df( return df[features].astype(np.float32), df["timestamp"].astype(int).tolist() -def _update_info_metric( - data: np.ndarray, metric_names: Sequence[str], labels: Sequence[str] +def _update_gauge_metric( + data: np.ndarray, metric_name: Sequence[str], labels: dict[str, str] ) -> None: """ Utility function is used to update the gauge metric. Args: data: data - metric_names: metric name in the payload + metric_name: metric name in the payload labels: labels. """ - metric_mean = np.mean(data, axis=0) - if metric_mean.shape[0] != len(metric_names): - raise ValueError("Data Shape and metric name length do not match") - for _data, _metric_name in zip(metric_mean, metric_names): + for _data, _metric_name in zip(data.T, metric_name): _set_gauge( - gauge=RECORDED_DATA_GAUGE, - labels=(*labels, _metric_name), - data=_data, + gauge="RECORDED_DATA_GAUGE", + labels=labels | {"metric_name": _metric_name}, + is_enabled=METRICS_ENABLED, + data=np.mean(_data).squeeze(), ) @@ -119,25 +110,6 @@ def _get_artifact_stats(artifact_data): } -def _update_info_metric( - data: np.ndarray, metric_name: Sequence[str], labels: Sequence[str] -) -> None: - """ - Utility function is used to update the gauge metric. - Args: - data: data - metric_name: metric name in the payload - labels: labels. - - """ - for _data, _metric_name in zip(data.T, metric_name): - _set_gauge( - gauge=RECORDED_DATA_GAUGE, - labels=(*labels, _metric_name), - data=np.mean(_data).squeeze(), - ) - - def _load_artifact( skeys: KEYS, dkeys: KEYS, @@ -160,13 +132,13 @@ def _load_artifact( StreamPayload object """ - _metric_label_values = ( - payload.metadata["numalogic_opex_tags"]["source"], - vertex, - ":".join(skeys), - payload.config_id, - payload.pipeline_id, - ) + _metric_label_values = { + "source": payload.metadata["numalogic_opex_tags"]["source"], + "vertex": vertex, + "composite_key": ":".join(skeys), + "config_id": payload.config_id, + "pipeline_id": payload.pipeline_id, + } logger = _struct_log.bind( uuid=payload.uuid, @@ -199,12 +171,16 @@ def _load_artifact( skeys=skeys, dkeys=dkeys, latest=False, version=version_to_load ) except RedisRegistryError: - _increment_counter(REDIS_ERROR_COUNTER, labels=_metric_label_values) + _increment_counter( + "REDIS_ERROR_COUNTER", labels=_metric_label_values, is_enabled=METRICS_ENABLED + ) logger.warning("Error while fetching artifact") return None, payload except Exception: - _increment_counter(EXCEPTION_COUNTER, labels=_metric_label_values) + _increment_counter( + "EXCEPTION_COUNTER", labels=_metric_label_values, is_enabled=METRICS_ENABLED + ) logger.exception("Unhandled exception while fetching artifact") return None, payload else: @@ -214,18 +190,20 @@ def _load_artifact( ) logger.debug("Loaded Model!") _increment_counter( - counter=SOURCE_COUNTER, - labels=(artifact_data.extras.get("source"), *_metric_label_values), + counter="SOURCE_COUNTER", + labels=({"artifact_source": artifact_data.extras.get("source")} | _metric_label_values), + is_enabled=METRICS_ENABLED, ) _add_info( - info=MODEL_INFO, - labels=( - payload.metadata["numalogic_opex_tags"]["source"], - ":".join(skeys), - payload.config_id, - payload.pipeline_id, - ), + info="MODEL_INFO", + labels={ + "source": payload.metadata["numalogic_opex_tags"]["source"], + "composite_key": ":".join(skeys), + "config_id": payload.config_id, + "pipeline_id": payload.pipeline_id, + }, data=_get_artifact_stats(artifact_data), + is_enabled=METRICS_ENABLED, ) if ( artifact_data.metadata @@ -396,7 +374,7 @@ def get_trainer_message( keys: list[str], stream_conf: StreamConf, payload: StreamPayload, - *metric_values: str, + **metric_values: dict, ) -> Message: """ Get message for training request. @@ -422,8 +400,9 @@ def get_trainer_message( ) if metric_values: _increment_counter( - counter=MODEL_STATUS_COUNTER, - labels=(payload.status, *metric_values), + counter="MODEL_STATUS_COUNTER", + labels={"status": payload.status} | metric_values, + is_enabled=METRICS_ENABLED, ) _struct_log.debug( "Sending training request", diff --git a/numalogic/udfs/trainer/_base.py b/numalogic/udfs/trainer/_base.py index cfeb25a0..cbb5ed27 100644 --- a/numalogic/udfs/trainer/_base.py +++ b/numalogic/udfs/trainer/_base.py @@ -1,3 +1,4 @@ +import os import time from dataclasses import asdict from typing import Optional @@ -19,22 +20,12 @@ from numalogic.udfs import NumalogicUDF from numalogic.udfs._config import PipelineConf from numalogic.udfs._logger import configure_logger, log_data_payload_values -from numalogic.udfs._metrics import ( - REDIS_ERROR_COUNTER, - INSUFFICIENT_DATA_COUNTER, - NAN_SUMMARY, - INF_SUMMARY, - MSG_IN_COUNTER, - MSG_DROPPED_COUNTER, - MSG_PROCESSED_COUNTER, - UDF_TIME, - _increment_counter, - _add_summary, -) +from numalogic.udfs._metrics_utility import _increment_counter, _add_summary from numalogic.udfs.entities import TrainerPayload from numalogic.udfs.tools import TrainMsgDeduplicator import torch +METRICS_ENABLED = bool(int(os.getenv("METRICS_ENABLED", default="1"))) _struct_log = configure_logger() @@ -144,7 +135,6 @@ def compute( return dict_artifacts - @UDF_TIME.time() def exec(self, keys: list[str], datum: Datum) -> Messages: """ Main run function for the UDF. @@ -163,19 +153,20 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: # Construct payload object json_payload = orjson.loads(datum.value) payload = TrainerPayload(**json_payload) - _metric_label_values = ( - payload.composite_keys, - ":".join(payload.composite_keys), - payload.config_id, - payload.pipeline_id, - ) + _metric_label_values = { + "composite_key": ":".join(payload.composite_keys), + "source": ":".join(payload.composite_keys), + "config_id": payload.config_id, + "pipeline_id": payload.pipeline_id, + } _conf = self.get_ml_pipeline_conf( config_id=payload.config_id, pipeline_id=payload.pipeline_id ) _increment_counter( - counter=MSG_IN_COUNTER, - labels=[self._vtx, *_metric_label_values], + counter="MSG_IN_COUNTER", + labels={"vertex": self._vtx} | _metric_label_values, + is_enabled=METRICS_ENABLED, ) logger = log_data_payload_values(logger, json_payload) @@ -192,8 +183,9 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: data_freq=_conf.numalogic_conf.trainer.data_freq_sec, ): _increment_counter( - counter=MSG_DROPPED_COUNTER, - labels=(self._vtx, *_metric_label_values), + counter="MSG_DROPPED_COUNTER", + labels={"vertex": self._vtx} | _metric_label_values, + is_enabled=METRICS_ENABLED, ) return Messages(Message.to_drop()) @@ -204,8 +196,9 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: # while fetching the data if df is None: _increment_counter( - counter=MSG_DROPPED_COUNTER, - labels=(self._vtx, *_metric_label_values), + counter="MSG_DROPPED_COUNTER", + labels={"vertex": self._vtx} | _metric_label_values, + is_enabled=METRICS_ENABLED, ) logger.warning( "Caught exception/error while fetching from source", @@ -224,12 +217,14 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: shape=df.shape, ) _increment_counter( - counter=INSUFFICIENT_DATA_COUNTER, + counter="INSUFFICIENT_DATA_COUNTER", labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) _increment_counter( - counter=MSG_DROPPED_COUNTER, - labels=(self._vtx, *_metric_label_values), + counter="MSG_DROPPED_COUNTER", + labels={"vertex": self._vtx} | _metric_label_values, + is_enabled=METRICS_ENABLED, ) return Messages(Message.to_drop()) @@ -238,14 +233,16 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: # Construct feature array x_train, nan_counter, inf_counter = self.get_feature_arr(df, _conf.metrics) _add_summary( - summary=NAN_SUMMARY, + summary="NAN_SUMMARY", labels=_metric_label_values, data=np.sum(nan_counter), + is_enabled=METRICS_ENABLED, ) _add_summary( - summary=INF_SUMMARY, + summary="INF_SUMMARY", labels=_metric_label_values, data=np.sum(inf_counter), + is_enabled=METRICS_ENABLED, ) # Initialize artifacts @@ -283,11 +280,9 @@ def exec(self, keys: list[str], datum: Datum) -> Messages: "Time taken in trainer", execution_time_secs=round(time.perf_counter() - _start_time, 4) ) _increment_counter( - counter=MSG_PROCESSED_COUNTER, - labels=( - self._vtx, - *_metric_label_values, - ), + counter="MSG_PROCESSED_COUNTER", + labels={"vertex": self._vtx} | _metric_label_values, + is_enabled=METRICS_ENABLED, ) return Messages(Message.to_drop()) @@ -340,8 +335,14 @@ def artifacts_to_save( ) except RedisRegistryError: _increment_counter( - counter=REDIS_ERROR_COUNTER, - labels=(vertex_name, ":".join(payload.composite_keys), payload.config_id), + counter="REDIS_ERROR_COUNTER", + labels={ + "vertex": vertex_name, + "composite_key": ":".join(skeys), + "config_id": payload.config_id, + "pipeline_id": payload.pipeline_id, + }, + is_enabled=METRICS_ENABLED, ) logger.exception( "Error while saving artifact with skeys", uuid=payload.uuid, skeys=skeys diff --git a/numalogic/udfs/trainer/_druid.py b/numalogic/udfs/trainer/_druid.py index 7a348bae..ebe8f633 100644 --- a/numalogic/udfs/trainer/_druid.py +++ b/numalogic/udfs/trainer/_druid.py @@ -1,3 +1,4 @@ +import os import time from typing import Optional @@ -10,15 +11,10 @@ from numalogic.udfs._config import PipelineConf from numalogic.udfs._logger import configure_logger from numalogic.udfs.entities import TrainerPayload -from numalogic.udfs._metrics import ( - FETCH_EXCEPTION_COUNTER, - DATAFRAME_SHAPE_SUMMARY, - FETCH_TIME_SUMMARY, - _increment_counter, - _add_summary, -) from numalogic.udfs.trainer._base import TrainerUDF +from numalogic.udfs._metrics_utility import _increment_counter, _add_summary +METRICS_ENABLED = bool(int(os.getenv("METRICS_ENABLED", default="1"))) _struct_log = configure_logger() @@ -94,12 +90,12 @@ def fetch_data(self, payload: TrainerPayload) -> Optional[pd.DataFrame]: _start_time = time.perf_counter() logger = _struct_log.bind(udf_vertex=self._vtx) - _metric_label_values = ( - payload.composite_keys, - ":".join(payload.composite_keys), - payload.config_id, - payload.pipeline_id, - ) + _metric_label_values = { + "source": ":".join(payload.composite_keys), + "config_id": payload.config_id, + "pipeline_id": payload.pipeline_id, + "composite_key": ":".join(payload.composite_keys), + } _stream_conf = self.get_stream_conf(payload.config_id) _conf = _stream_conf.ml_pipelines[payload.pipeline_id] _fetcher_conf = self.dataconn_conf.fetcher or ( @@ -131,16 +127,18 @@ def fetch_data(self, payload: TrainerPayload) -> Optional[pd.DataFrame]: ) except DruidFetcherError: _increment_counter( - counter=FETCH_EXCEPTION_COUNTER, + counter="FETCH_EXCEPTION_COUNTER", labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) logger.exception("Error while fetching data from druid") return None _end_time = time.perf_counter() - _start_time _add_summary( - FETCH_TIME_SUMMARY, + "FETCH_TIME_SUMMARY", labels=_metric_label_values, data=_end_time, + is_enabled=METRICS_ENABLED, ) logger.info( @@ -154,7 +152,7 @@ def fetch_data(self, payload: TrainerPayload) -> Optional[pd.DataFrame]: ) _add_summary( - DATAFRAME_SHAPE_SUMMARY, + "DATAFRAME_SHAPE_SUMMARY", labels=_metric_label_values, data=_df.shape[0], ) diff --git a/numalogic/udfs/trainer/_prom.py b/numalogic/udfs/trainer/_prom.py index 07c4e549..d887160c 100644 --- a/numalogic/udfs/trainer/_prom.py +++ b/numalogic/udfs/trainer/_prom.py @@ -1,3 +1,4 @@ +import os import time from datetime import datetime, timedelta from typing import Optional @@ -11,15 +12,10 @@ from numalogic.udfs._config import PipelineConf from numalogic.udfs._logger import configure_logger from numalogic.udfs.entities import TrainerPayload -from numalogic.udfs._metrics import ( - DATAFRAME_SHAPE_SUMMARY, - FETCH_EXCEPTION_COUNTER, - FETCH_TIME_SUMMARY, - _add_summary, - _increment_counter, -) +from numalogic.udfs._metrics_utility import _increment_counter, _add_summary from numalogic.udfs.trainer._base import TrainerUDF +METRICS_ENABLED = bool(int(os.getenv("METRICS_ENABLED", default="1"))) _struct_log = configure_logger() @@ -62,12 +58,12 @@ def fetch_data(self, payload: TrainerPayload) -> Optional[pd.DataFrame]: _start_time = time.perf_counter() logger = _struct_log.bind(udf_vertex=self._vtx) - _metric_label_values = ( - payload.composite_keys, - ":".join(payload.composite_keys), - payload.config_id, - payload.pipeline_id, - ) + _metric_label_values = { + "config_id": payload.config_id, + "pipeline_id": payload.pipeline_id, + "composite_key": ":".join(payload.composite_keys), + "source": ":".join(payload.composite_keys), + } _stream_conf = self.get_stream_conf(payload.config_id) _conf = _stream_conf.ml_pipelines[payload.pipeline_id] @@ -89,16 +85,18 @@ def fetch_data(self, payload: TrainerPayload) -> Optional[pd.DataFrame]: ) except PrometheusFetcherError: _increment_counter( - counter=FETCH_EXCEPTION_COUNTER, + counter="FETCH_EXCEPTION_COUNTER", labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) logger.exception("Error while fetching data from Prometheus", uuid=payload.uuid) return None _end_time = time.perf_counter() - _start_time _add_summary( - FETCH_TIME_SUMMARY, + "FETCH_TIME_SUMMARY", labels=_metric_label_values, data=_end_time, + is_enabled=METRICS_ENABLED, ) logger.info( "Fetched data from Prometheus", @@ -110,8 +108,9 @@ def fetch_data(self, payload: TrainerPayload) -> Optional[pd.DataFrame]: execution_time_ms=round(_end_time * 1000, 4), ) _add_summary( - DATAFRAME_SHAPE_SUMMARY, + "DATAFRAME_SHAPE_SUMMARY", labels=_metric_label_values, data=_df.shape[0], + is_enabled=METRICS_ENABLED, ) return _df diff --git a/numalogic/udfs/trainer/_rds.py b/numalogic/udfs/trainer/_rds.py index ae5e1010..f27eab74 100644 --- a/numalogic/udfs/trainer/_rds.py +++ b/numalogic/udfs/trainer/_rds.py @@ -1,4 +1,5 @@ import logging +import os import time from typing import Optional import pandas as pd @@ -9,17 +10,12 @@ from numalogic.tools.types import redis_client_t from numalogic.udfs._config import PipelineConf from numalogic.udfs.entities import TrainerPayload -from numalogic.udfs._metrics import ( - FETCH_EXCEPTION_COUNTER, - DATAFRAME_SHAPE_SUMMARY, - FETCH_TIME_SUMMARY, - _increment_counter, - _add_summary, -) +from numalogic.udfs._metrics_utility import _increment_counter, _add_summary from numalogic.udfs.trainer._base import TrainerUDF from datetime import datetime, timedelta import pytz +METRICS_ENABLED = bool(int(os.getenv("METRICS_ENABLED", default="1"))) _LOGGER = logging.getLogger(__name__) @@ -199,12 +195,12 @@ def fetch_data(self, payload: TrainerPayload) -> Optional[pd.DataFrame]: # TODO : Make this code generic and add to trainer utils _config_id = payload.config_id _pipeline_id = payload.pipeline_id - _metric_label_values = ( - payload.composite_keys, - ":".join(payload.composite_keys), - _config_id, - _pipeline_id, - ) + _metric_label_values = { + "composite_key": ":".join(payload.composite_keys), + "config_id": _config_id, + "pipeline_id": _pipeline_id, + "source": ":".join(payload.composite_keys), + } _stream_conf = self.get_stream_conf(_config_id) _conf = _stream_conf.ml_pipelines[_pipeline_id] _fetcher_conf = self.dataconn_conf.fetcher or ( @@ -242,16 +238,18 @@ def fetch_data(self, payload: TrainerPayload) -> Optional[pd.DataFrame]: ) except RDSFetcherError: _increment_counter( - counter=FETCH_EXCEPTION_COUNTER, + counter="FETCH_EXCEPTION_COUNTER", labels=_metric_label_values, + is_enabled=METRICS_ENABLED, ) _LOGGER.exception("%s - Error while fetching data from RDS", payload.uuid) return None _end_time = time.perf_counter() - _start_time _add_summary( - FETCH_TIME_SUMMARY, + "FETCH_TIME_SUMMARY", labels=_metric_label_values, data=_end_time, + is_enabled=METRICS_ENABLED, ) _LOGGER.debug( @@ -261,9 +259,9 @@ def fetch_data(self, payload: TrainerPayload) -> Optional[pd.DataFrame]: _df.shape, ) _add_summary( - DATAFRAME_SHAPE_SUMMARY, + "DATAFRAME_SHAPE_SUMMARY", labels=_metric_label_values, data=_df.shape[0], + is_enabled=METRICS_ENABLED, ) - return _df diff --git a/poetry.lock b/poetry.lock index a9e96b21..64e50674 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiohttp" @@ -406,17 +406,17 @@ css = ["tinycss2 (>=1.1.0,<1.3)"] [[package]] name = "boto3" -version = "1.34.123" +version = "1.34.128" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.34.123-py3-none-any.whl", hash = "sha256:56bec52d485d5670ce96d53ae7b2cd4ae4e8a705fb2298a21093cdd77d642331"}, - {file = "boto3-1.34.123.tar.gz", hash = "sha256:42b140fc850cf261ee4b1e8ef527fa071b1f1592a6d6a68d34b29f37cc46b4dd"}, + {file = "boto3-1.34.128-py3-none-any.whl", hash = "sha256:a048ff980a81cd652724a73bc496c519b336fabe19cc8bfc6c53b2ff6eb22c7b"}, + {file = "boto3-1.34.128.tar.gz", hash = "sha256:43a6e99f53a8d34b3b4dbe424dbcc6b894350dc41a85b0af7c7bc24a7ec2cead"}, ] [package.dependencies] -botocore = ">=1.34.123,<1.35.0" +botocore = ">=1.34.128,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -425,13 +425,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.34.123" +version = "1.34.128" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.34.123-py3-none-any.whl", hash = "sha256:8c34ada2a708c82e7174bff700611643db7ce2cb18f1130c35045c24310d299d"}, - {file = "botocore-1.34.123.tar.gz", hash = "sha256:a8577f6574600c4d159b5cd103ee05744a443d77f7778304e17307940b369c4f"}, + {file = "botocore-1.34.128-py3-none-any.whl", hash = "sha256:db67fda136c372ab3fa432580c819c89ba18d28a6152a4d2a7ea40d44082892e"}, + {file = "botocore-1.34.128.tar.gz", hash = "sha256:8d8e03f7c8c080ecafda72036eb3b482d649f8417c90b5dca33b7c2c47adb0c9"}, ] [package.dependencies] @@ -1114,13 +1114,13 @@ probabilistic = ["pyprobables (>=0.6,<0.7)"] [[package]] name = "fastjsonschema" -version = "2.19.1" +version = "2.20.0" description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" files = [ - {file = "fastjsonschema-2.19.1-py3-none-any.whl", hash = "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0"}, - {file = "fastjsonschema-2.19.1.tar.gz", hash = "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d"}, + {file = "fastjsonschema-2.20.0-py3-none-any.whl", hash = "sha256:5875f0b0fa7a0043a91e93a9b8f793bcbbba9691e7fd83dca95c28ba26d21f0a"}, + {file = "fastjsonschema-2.20.0.tar.gz", hash = "sha256:3d48fc5300ee96f5d116f10fe6f28d938e6008f59a6a025c2649475b87f76a23"}, ] [package.extras] @@ -1128,18 +1128,18 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "filelock" -version = "3.14.0" +version = "3.15.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, - {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, + {file = "filelock-3.15.1-py3-none-any.whl", hash = "sha256:71b3102950e91dfc1bb4209b64be4dc8854f40e5f534428d8684f953ac847fac"}, + {file = "filelock-3.15.1.tar.gz", hash = "sha256:58a2549afdf9e02e10720eaa4d4470f56386d7a6f72edd7d0596337af8ed7ad8"}, ] [package.extras] docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] @@ -2530,32 +2530,32 @@ typing = ["mypy (>=1.0.0)", "types-setuptools"] [[package]] name = "llvmlite" -version = "0.42.0" +version = "0.43.0" description = "lightweight wrapper around basic LLVM functionality" optional = false python-versions = ">=3.9" files = [ - {file = "llvmlite-0.42.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3366938e1bf63d26c34fbfb4c8e8d2ded57d11e0567d5bb243d89aab1eb56098"}, - {file = "llvmlite-0.42.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c35da49666a21185d21b551fc3caf46a935d54d66969d32d72af109b5e7d2b6f"}, - {file = "llvmlite-0.42.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70f44ccc3c6220bd23e0ba698a63ec2a7d3205da0d848804807f37fc243e3f77"}, - {file = "llvmlite-0.42.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763f8d8717a9073b9e0246998de89929071d15b47f254c10eef2310b9aac033d"}, - {file = "llvmlite-0.42.0-cp310-cp310-win_amd64.whl", hash = "sha256:8d90edf400b4ceb3a0e776b6c6e4656d05c7187c439587e06f86afceb66d2be5"}, - {file = "llvmlite-0.42.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ae511caed28beaf1252dbaf5f40e663f533b79ceb408c874c01754cafabb9cbf"}, - {file = "llvmlite-0.42.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81e674c2fe85576e6c4474e8c7e7aba7901ac0196e864fe7985492b737dbab65"}, - {file = "llvmlite-0.42.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb3975787f13eb97629052edb5017f6c170eebc1c14a0433e8089e5db43bcce6"}, - {file = "llvmlite-0.42.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5bece0cdf77f22379f19b1959ccd7aee518afa4afbd3656c6365865f84903f9"}, - {file = "llvmlite-0.42.0-cp311-cp311-win_amd64.whl", hash = "sha256:7e0c4c11c8c2aa9b0701f91b799cb9134a6a6de51444eff5a9087fc7c1384275"}, - {file = "llvmlite-0.42.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:08fa9ab02b0d0179c688a4216b8939138266519aaa0aa94f1195a8542faedb56"}, - {file = "llvmlite-0.42.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b2fce7d355068494d1e42202c7aff25d50c462584233013eb4470c33b995e3ee"}, - {file = "llvmlite-0.42.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebe66a86dc44634b59a3bc860c7b20d26d9aaffcd30364ebe8ba79161a9121f4"}, - {file = "llvmlite-0.42.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d47494552559e00d81bfb836cf1c4d5a5062e54102cc5767d5aa1e77ccd2505c"}, - {file = "llvmlite-0.42.0-cp312-cp312-win_amd64.whl", hash = "sha256:05cb7e9b6ce69165ce4d1b994fbdedca0c62492e537b0cc86141b6e2c78d5888"}, - {file = "llvmlite-0.42.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bdd3888544538a94d7ec99e7c62a0cdd8833609c85f0c23fcb6c5c591aec60ad"}, - {file = "llvmlite-0.42.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d0936c2067a67fb8816c908d5457d63eba3e2b17e515c5fe00e5ee2bace06040"}, - {file = "llvmlite-0.42.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a78ab89f1924fc11482209f6799a7a3fc74ddc80425a7a3e0e8174af0e9e2301"}, - {file = "llvmlite-0.42.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7599b65c7af7abbc978dbf345712c60fd596aa5670496561cc10e8a71cebfb2"}, - {file = "llvmlite-0.42.0-cp39-cp39-win_amd64.whl", hash = "sha256:43d65cc4e206c2e902c1004dd5418417c4efa6c1d04df05c6c5675a27e8ca90e"}, - {file = "llvmlite-0.42.0.tar.gz", hash = "sha256:f92b09243c0cc3f457da8b983f67bd8e1295d0f5b3746c7a1861d7a99403854a"}, + {file = "llvmlite-0.43.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a289af9a1687c6cf463478f0fa8e8aa3b6fb813317b0d70bf1ed0759eab6f761"}, + {file = "llvmlite-0.43.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d4fd101f571a31acb1559ae1af30f30b1dc4b3186669f92ad780e17c81e91bc"}, + {file = "llvmlite-0.43.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d434ec7e2ce3cc8f452d1cd9a28591745de022f931d67be688a737320dfcead"}, + {file = "llvmlite-0.43.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6912a87782acdff6eb8bf01675ed01d60ca1f2551f8176a300a886f09e836a6a"}, + {file = "llvmlite-0.43.0-cp310-cp310-win_amd64.whl", hash = "sha256:14f0e4bf2fd2d9a75a3534111e8ebeb08eda2f33e9bdd6dfa13282afacdde0ed"}, + {file = "llvmlite-0.43.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3e8d0618cb9bfe40ac38a9633f2493d4d4e9fcc2f438d39a4e854f39cc0f5f98"}, + {file = "llvmlite-0.43.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0a9a1a39d4bf3517f2af9d23d479b4175ead205c592ceeb8b89af48a327ea57"}, + {file = "llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2"}, + {file = "llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977525a1e5f4059316b183fb4fd34fa858c9eade31f165427a3977c95e3ee749"}, + {file = "llvmlite-0.43.0-cp311-cp311-win_amd64.whl", hash = "sha256:d5bd550001d26450bd90777736c69d68c487d17bf371438f975229b2b8241a91"}, + {file = "llvmlite-0.43.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f99b600aa7f65235a5a05d0b9a9f31150c390f31261f2a0ba678e26823ec38f7"}, + {file = "llvmlite-0.43.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:35d80d61d0cda2d767f72de99450766250560399edc309da16937b93d3b676e7"}, + {file = "llvmlite-0.43.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eccce86bba940bae0d8d48ed925f21dbb813519169246e2ab292b5092aba121f"}, + {file = "llvmlite-0.43.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df6509e1507ca0760787a199d19439cc887bfd82226f5af746d6977bd9f66844"}, + {file = "llvmlite-0.43.0-cp312-cp312-win_amd64.whl", hash = "sha256:7a2872ee80dcf6b5dbdc838763d26554c2a18aa833d31a2635bff16aafefb9c9"}, + {file = "llvmlite-0.43.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cd2a7376f7b3367019b664c21f0c61766219faa3b03731113ead75107f3b66c"}, + {file = "llvmlite-0.43.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18e9953c748b105668487b7c81a3e97b046d8abf95c4ddc0cd3c94f4e4651ae8"}, + {file = "llvmlite-0.43.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74937acd22dc11b33946b67dca7680e6d103d6e90eeaaaf932603bec6fe7b03a"}, + {file = "llvmlite-0.43.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9efc739cc6ed760f795806f67889923f7274276f0eb45092a1473e40d9b867"}, + {file = "llvmlite-0.43.0-cp39-cp39-win_amd64.whl", hash = "sha256:47e147cdda9037f94b399bf03bfd8a6b6b1f2f90be94a454e3386f006455a9b4"}, + {file = "llvmlite-0.43.0.tar.gz", hash = "sha256:ae2b5b5c3ef67354824fb75517c8db5fbe93bc02cd9671f3c62271626bc041d5"}, ] [[package]] @@ -2725,13 +2725,13 @@ tbb = "==2021.*" [[package]] name = "mlflow-skinny" -version = "2.13.2" +version = "2.14.0" description = "MLflow is an open source platform for the complete machine learning lifecycle" optional = true python-versions = ">=3.8" files = [ - {file = "mlflow_skinny-2.13.2-py3-none-any.whl", hash = "sha256:af5c4f0a658ce16cf695069c548d377fe93d6831ffb7129df1170fec11c2f155"}, - {file = "mlflow_skinny-2.13.2.tar.gz", hash = "sha256:76ec6d5d8d54f022634d878cfebaed2ddd6acff982ec3391aacde91b5343d603"}, + {file = "mlflow_skinny-2.14.0-py3-none-any.whl", hash = "sha256:a634acf3061fc49a530c6a0f4f2159b04465394d08d21101ace7f7392eed4f42"}, + {file = "mlflow_skinny-2.14.0.tar.gz", hash = "sha256:769e92694c2be11935f57ca489d873901c50b24280bac63e7d555d2cc9598b7b"}, ] [package.dependencies] @@ -2741,8 +2741,8 @@ cloudpickle = "<4" entrypoints = "<1" gitpython = ">=3.1.9,<4" importlib-metadata = ">=3.7.0,<4.7.0 || >4.7.0,<8" -opentelemetry-api = ">=1.0.0,<3" -opentelemetry-sdk = ">=1.0.0,<3" +opentelemetry-api = ">=1.9.0,<3" +opentelemetry-sdk = ">=1.9.0,<3" packaging = "<25" protobuf = ">=3.12.0,<5" pytz = "<2025" @@ -2757,7 +2757,7 @@ extras = ["azureml-core (>=1.2.0)", "boto3", "botocore", "google-cloud-storage ( gateway = ["aiohttp (<4)", "boto3 (>=1.28.56,<2)", "fastapi (<1)", "pydantic (>=1.0,<3)", "slowapi (>=0.1.9,<1)", "tiktoken (<1)", "uvicorn[standard] (<1)", "watchfiles (<1)"] genai = ["aiohttp (<4)", "boto3 (>=1.28.56,<2)", "fastapi (<1)", "pydantic (>=1.0,<3)", "slowapi (>=0.1.9,<1)", "tiktoken (<1)", "uvicorn[standard] (<1)", "watchfiles (<1)"] jfrog = ["mlflow-jfrog-plugin"] -langchain = ["langchain (>=0.1.4,<=0.2.1)"] +langchain = ["langchain (>=0.1.0,<=0.2.3)"] sqlserver = ["mlflow-dbstore"] xethub = ["mlflow-xethub"] @@ -3097,39 +3097,56 @@ jupyter-server = ">=1.8,<3" [package.extras] test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] +[[package]] +name = "numalogic-prometheus" +version = "0.8.1a2" +description = "Numalogic Prometheus based tools" +optional = false +python-versions = "<3.13,>=3.9" +files = [ + {file = "numalogic_prometheus-0.8.1a2-py3-none-any.whl", hash = "sha256:d4b07ad03ae570d0b82f0aa652fe389b3712c8bdee17bdbb6c08a09d311c6b77"}, + {file = "numalogic_prometheus-0.8.1a2.tar.gz", hash = "sha256:7f5467e75c6fd4afedecad81158cd1a3951765375735531fb8739e736d67443a"}, +] + +[package.dependencies] +omegaconf = ">=2.3.0,<3.0.0" +orjson = ">=3.8.4,<4.0.0" +prometheus-client = ">=0.18,<0.19" +setuptools = ">=70.0.0,<71.0.0" + [[package]] name = "numba" -version = "0.59.1" +version = "0.60.0" description = "compiling Python code using LLVM" optional = false python-versions = ">=3.9" files = [ - {file = "numba-0.59.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:97385a7f12212c4f4bc28f648720a92514bee79d7063e40ef66c2d30600fd18e"}, - {file = "numba-0.59.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0b77aecf52040de2a1eb1d7e314497b9e56fba17466c80b457b971a25bb1576d"}, - {file = "numba-0.59.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3476a4f641bfd58f35ead42f4dcaf5f132569c4647c6f1360ccf18ee4cda3990"}, - {file = "numba-0.59.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:525ef3f820931bdae95ee5379c670d5c97289c6520726bc6937a4a7d4230ba24"}, - {file = "numba-0.59.1-cp310-cp310-win_amd64.whl", hash = "sha256:990e395e44d192a12105eca3083b61307db7da10e093972ca285c85bef0963d6"}, - {file = "numba-0.59.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:43727e7ad20b3ec23ee4fc642f5b61845c71f75dd2825b3c234390c6d8d64051"}, - {file = "numba-0.59.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:411df625372c77959570050e861981e9d196cc1da9aa62c3d6a836b5cc338966"}, - {file = "numba-0.59.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2801003caa263d1e8497fb84829a7ecfb61738a95f62bc05693fcf1733e978e4"}, - {file = "numba-0.59.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dd2842fac03be4e5324ebbbd4d2d0c8c0fc6e0df75c09477dd45b288a0777389"}, - {file = "numba-0.59.1-cp311-cp311-win_amd64.whl", hash = "sha256:0594b3dfb369fada1f8bb2e3045cd6c61a564c62e50cf1f86b4666bc721b3450"}, - {file = "numba-0.59.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1cce206a3b92836cdf26ef39d3a3242fec25e07f020cc4feec4c4a865e340569"}, - {file = "numba-0.59.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8c8b4477763cb1fbd86a3be7050500229417bf60867c93e131fd2626edb02238"}, - {file = "numba-0.59.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d80bce4ef7e65bf895c29e3889ca75a29ee01da80266a01d34815918e365835"}, - {file = "numba-0.59.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f7ad1d217773e89a9845886401eaaab0a156a90aa2f179fdc125261fd1105096"}, - {file = "numba-0.59.1-cp312-cp312-win_amd64.whl", hash = "sha256:5bf68f4d69dd3a9f26a9b23548fa23e3bcb9042e2935257b471d2a8d3c424b7f"}, - {file = "numba-0.59.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4e0318ae729de6e5dbe64c75ead1a95eb01fabfe0e2ebed81ebf0344d32db0ae"}, - {file = "numba-0.59.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0f68589740a8c38bb7dc1b938b55d1145244c8353078eea23895d4f82c8b9ec1"}, - {file = "numba-0.59.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:649913a3758891c77c32e2d2a3bcbedf4a69f5fea276d11f9119677c45a422e8"}, - {file = "numba-0.59.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9712808e4545270291d76b9a264839ac878c5eb7d8b6e02c970dc0ac29bc8187"}, - {file = "numba-0.59.1-cp39-cp39-win_amd64.whl", hash = "sha256:8d51ccd7008a83105ad6a0082b6a2b70f1142dc7cfd76deb8c5a862367eb8c86"}, - {file = "numba-0.59.1.tar.gz", hash = "sha256:76f69132b96028d2774ed20415e8c528a34e3299a40581bae178f0994a2f370b"}, + {file = "numba-0.60.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d761de835cd38fb400d2c26bb103a2726f548dc30368853121d66201672e651"}, + {file = "numba-0.60.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:159e618ef213fba758837f9837fb402bbe65326e60ba0633dbe6c7f274d42c1b"}, + {file = "numba-0.60.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1527dc578b95c7c4ff248792ec33d097ba6bef9eda466c948b68dfc995c25781"}, + {file = "numba-0.60.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe0b28abb8d70f8160798f4de9d486143200f34458d34c4a214114e445d7124e"}, + {file = "numba-0.60.0-cp310-cp310-win_amd64.whl", hash = "sha256:19407ced081d7e2e4b8d8c36aa57b7452e0283871c296e12d798852bc7d7f198"}, + {file = "numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8"}, + {file = "numba-0.60.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3fb02b344a2a80efa6f677aa5c40cd5dd452e1b35f8d1c2af0dfd9ada9978e4b"}, + {file = "numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703"}, + {file = "numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8"}, + {file = "numba-0.60.0-cp311-cp311-win_amd64.whl", hash = "sha256:cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2"}, + {file = "numba-0.60.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7da4098db31182fc5ffe4bc42c6f24cd7d1cb8a14b59fd755bfee32e34b8404"}, + {file = "numba-0.60.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38d6ea4c1f56417076ecf8fc327c831ae793282e0ff51080c5094cb726507b1c"}, + {file = "numba-0.60.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:62908d29fb6a3229c242e981ca27e32a6e606cc253fc9e8faeb0e48760de241e"}, + {file = "numba-0.60.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0ebaa91538e996f708f1ab30ef4d3ddc344b64b5227b67a57aa74f401bb68b9d"}, + {file = "numba-0.60.0-cp312-cp312-win_amd64.whl", hash = "sha256:f75262e8fe7fa96db1dca93d53a194a38c46da28b112b8a4aca168f0df860347"}, + {file = "numba-0.60.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:01ef4cd7d83abe087d644eaa3d95831b777aa21d441a23703d649e06b8e06b74"}, + {file = "numba-0.60.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:819a3dfd4630d95fd574036f99e47212a1af41cbcb019bf8afac63ff56834449"}, + {file = "numba-0.60.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0b983bd6ad82fe868493012487f34eae8bf7dd94654951404114f23c3466d34b"}, + {file = "numba-0.60.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c151748cd269ddeab66334bd754817ffc0cabd9433acb0f551697e5151917d25"}, + {file = "numba-0.60.0-cp39-cp39-win_amd64.whl", hash = "sha256:3031547a015710140e8c87226b4cfe927cac199835e5bf7d4fe5cb64e814e3ab"}, + {file = "numba-0.60.0.tar.gz", hash = "sha256:5df6158e5584eece5fc83294b949fd30b9f1125df7708862205217e068aabf16"}, ] [package.dependencies] -llvmlite = "==0.42.*" -numpy = ">=1.22,<1.27" +llvmlite = "==0.43.*" +numpy = ">=1.22,<2.1" [[package]] name = "numexpr" @@ -3435,57 +3452,57 @@ dev = ["black", "mypy", "pytest"] [[package]] name = "orjson" -version = "3.10.4" +version = "3.10.5" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" files = [ - {file = "orjson-3.10.4-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:afca963f19ca60c7aedadea9979f769139127288dd58ccf3f7c5e8e6dc62cabf"}, - {file = "orjson-3.10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b112eff36ba7ccc7a9d6b87e17b9d6bde4312d05e3ddf66bf5662481dee846"}, - {file = "orjson-3.10.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02b192eaba048b1039eca9a0cef67863bd5623042f5c441889a9957121d97e14"}, - {file = "orjson-3.10.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:827c3d0e4fc44242c82bfdb1a773235b8c0575afee99a9fa9a8ce920c14e440f"}, - {file = "orjson-3.10.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca8ec09724f10ec209244caeb1f9f428b6bb03f2eda9ed5e2c4dd7f2b7fabd44"}, - {file = "orjson-3.10.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8eaa5d531a8fde11993cbcb27e9acf7d9c457ba301adccb7fa3a021bfecab46c"}, - {file = "orjson-3.10.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e112aa7fc4ea67367ec5e86c39a6bb6c5719eddc8f999087b1759e765ddaf2d4"}, - {file = "orjson-3.10.4-cp310-none-win32.whl", hash = "sha256:1538844fb88446c42da3889f8c4ecce95a630b5a5ba18ecdfe5aea596f4dff21"}, - {file = "orjson-3.10.4-cp310-none-win_amd64.whl", hash = "sha256:de02811903a2e434127fba5389c3cc90f689542339a6e52e691ab7f693407b5a"}, - {file = "orjson-3.10.4-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:358afaec75de7237dfea08e6b1b25d226e33a1e3b6dc154fc99eb697f24a1ffa"}, - {file = "orjson-3.10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb4e292c3198ab3d93e5f877301d2746be4ca0ba2d9c513da5e10eb90e19ff52"}, - {file = "orjson-3.10.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c39e57cf6323a39238490092985d5d198a7da4a3be013cc891a33fef13a536e"}, - {file = "orjson-3.10.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f86df433fc01361ff9270ad27455ce1ad43cd05e46de7152ca6adb405a16b2f6"}, - {file = "orjson-3.10.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c9966276a2c97e93e6cbe8286537f88b2a071827514f0d9d47a0aefa77db458"}, - {file = "orjson-3.10.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c499a14155a1f5a1e16e0cd31f6cf6f93965ac60a0822bc8340e7e2d3dac1108"}, - {file = "orjson-3.10.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3087023ce904a327c29487eb7e1f2c060070e8dbb9a3991b8e7952a9c6e62f38"}, - {file = "orjson-3.10.4-cp311-none-win32.whl", hash = "sha256:f965893244fe348b59e5ce560693e6dd03368d577ce26849b5d261ce31c70101"}, - {file = "orjson-3.10.4-cp311-none-win_amd64.whl", hash = "sha256:c212f06fad6aa6ce85d5665e91a83b866579f29441a47d3865c57329c0857357"}, - {file = "orjson-3.10.4-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:d0965a8b0131959833ca8a65af60285995d57ced0de2fd8f16fc03235975d238"}, - {file = "orjson-3.10.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27b64695d9f2aef3ae15a0522e370ec95c946aaea7f2c97a1582a62b3bdd9169"}, - {file = "orjson-3.10.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:867d882ddee6a20be4c8b03ae3d2b0333894d53ad632d32bd9b8123649577171"}, - {file = "orjson-3.10.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a0667458f8a8ceb6dee5c08fec0b46195f92c474cbbec71dca2a6b7fd5b67b8d"}, - {file = "orjson-3.10.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3eac9befc4eaec1d1ff3bba6210576be4945332dde194525601c5ddb5c060d3"}, - {file = "orjson-3.10.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4343245443552eae240a33047a6d1bcac7a754ad4b1c57318173c54d7efb9aea"}, - {file = "orjson-3.10.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:30153e269eea43e98918d4d462a36a7065031d9246407dfff2579a4e457515c1"}, - {file = "orjson-3.10.4-cp312-none-win32.whl", hash = "sha256:1a7d092ee043abf3db19c2183115e80676495c9911843fdb3ebd48ca7b73079e"}, - {file = "orjson-3.10.4-cp312-none-win_amd64.whl", hash = "sha256:07a2adbeb8b9efe6d68fc557685954a1f19d9e33f5cc018ae1a89e96647c1b65"}, - {file = "orjson-3.10.4-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f5a746f3d908bce1a1e347b9ca89864047533bdfab5a450066a0315f6566527b"}, - {file = "orjson-3.10.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:465b4a8a3e459f8d304c19071b4badaa9b267c59207a005a7dd9dfe13d3a423f"}, - {file = "orjson-3.10.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:35858d260728c434a3d91b60685ab32418318567e8902039837e1c2af2719e0b"}, - {file = "orjson-3.10.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8a5ba090d40c4460312dd69c232b38c2ff67a823185cfe667e841c9dd5c06841"}, - {file = "orjson-3.10.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dde86755d064664e62e3612a166c28298aa8dfd35a991553faa58855ae739cc"}, - {file = "orjson-3.10.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:020a9e9001cfec85c156ef3b185ff758b62ef986cefdb8384c4579facd5ce126"}, - {file = "orjson-3.10.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3bf8e6e3388a2e83a86466c912387e0f0a765494c65caa7e865f99969b76ba0d"}, - {file = "orjson-3.10.4-cp38-none-win32.whl", hash = "sha256:c5a1cca6a4a3129db3da68a25dc0a459a62ae58e284e363b35ab304202d9ba9e"}, - {file = "orjson-3.10.4-cp38-none-win_amd64.whl", hash = "sha256:ecd97d98d7bee3e3d51d0b51c92c457f05db4993329eea7c69764f9820e27eb3"}, - {file = "orjson-3.10.4-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:71362daa330a2fc85553a1469185ac448547392a8f83d34e67779f8df3a52743"}, - {file = "orjson-3.10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d24b59d1fecb0fd080c177306118a143f7322335309640c55ed9580d2044e363"}, - {file = "orjson-3.10.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e906670aea5a605b083ebb58d575c35e88cf880fa372f7cedaac3d51e98ff164"}, - {file = "orjson-3.10.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ce32ed4bc4d632268e4978e595fe5ea07e026b751482b4a0feec48f66a90abc"}, - {file = "orjson-3.10.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1dcd34286246e0c5edd0e230d1da2daab2c1b465fcb6bac85b8d44057229d40a"}, - {file = "orjson-3.10.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c45d4b8c403e50beedb1d006a8916d9910ed56bceaf2035dc253618b44d0a161"}, - {file = "orjson-3.10.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:aaed3253041b5002a4f5bfdf6f7b5cce657d974472b0699a469d439beba40381"}, - {file = "orjson-3.10.4-cp39-none-win32.whl", hash = "sha256:9a4f41b7dbf7896f8dbf559b9b43dcd99e31e0d49ac1b59d74f52ce51ab10eb9"}, - {file = "orjson-3.10.4-cp39-none-win_amd64.whl", hash = "sha256:6c4eb7d867ed91cb61e6514cb4f457aa01d7b0fd663089df60a69f3d38b69d4c"}, - {file = "orjson-3.10.4.tar.gz", hash = "sha256:c912ed25b787c73fe994a5decd81c3f3b256599b8a87d410d799d5d52013af2a"}, + {file = "orjson-3.10.5-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:545d493c1f560d5ccfc134803ceb8955a14c3fcb47bbb4b2fee0232646d0b932"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4324929c2dd917598212bfd554757feca3e5e0fa60da08be11b4aa8b90013c1"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c13ca5e2ddded0ce6a927ea5a9f27cae77eee4c75547b4297252cb20c4d30e6"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6c8e30adfa52c025f042a87f450a6b9ea29649d828e0fec4858ed5e6caecf63"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:338fd4f071b242f26e9ca802f443edc588fa4ab60bfa81f38beaedf42eda226c"}, + {file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6970ed7a3126cfed873c5d21ece1cd5d6f83ca6c9afb71bbae21a0b034588d96"}, + {file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:235dadefb793ad12f7fa11e98a480db1f7c6469ff9e3da5e73c7809c700d746b"}, + {file = "orjson-3.10.5-cp310-none-win32.whl", hash = "sha256:be79e2393679eda6a590638abda16d167754393f5d0850dcbca2d0c3735cebe2"}, + {file = "orjson-3.10.5-cp310-none-win_amd64.whl", hash = "sha256:c4a65310ccb5c9910c47b078ba78e2787cb3878cdded1702ac3d0da71ddc5228"}, + {file = "orjson-3.10.5-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:cdf7365063e80899ae3a697def1277c17a7df7ccfc979990a403dfe77bb54d40"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b68742c469745d0e6ca5724506858f75e2f1e5b59a4315861f9e2b1df77775a"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d10cc1b594951522e35a3463da19e899abe6ca95f3c84c69e9e901e0bd93d38"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcbe82b35d1ac43b0d84072408330fd3295c2896973112d495e7234f7e3da2e1"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c0eb7e0c75e1e486c7563fe231b40fdd658a035ae125c6ba651ca3b07936f5"}, + {file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:53ed1c879b10de56f35daf06dbc4a0d9a5db98f6ee853c2dbd3ee9d13e6f302f"}, + {file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:099e81a5975237fda3100f918839af95f42f981447ba8f47adb7b6a3cdb078fa"}, + {file = "orjson-3.10.5-cp311-none-win32.whl", hash = "sha256:1146bf85ea37ac421594107195db8bc77104f74bc83e8ee21a2e58596bfb2f04"}, + {file = "orjson-3.10.5-cp311-none-win_amd64.whl", hash = "sha256:36a10f43c5f3a55c2f680efe07aa93ef4a342d2960dd2b1b7ea2dd764fe4a37c"}, + {file = "orjson-3.10.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:68f85ecae7af14a585a563ac741b0547a3f291de81cd1e20903e79f25170458f"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28afa96f496474ce60d3340fe8d9a263aa93ea01201cd2bad844c45cd21f5268"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cd684927af3e11b6e754df80b9ffafd9fb6adcaa9d3e8fdd5891be5a5cad51e"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d21b9983da032505f7050795e98b5d9eee0df903258951566ecc358f6696969"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ad1de7fef79736dde8c3554e75361ec351158a906d747bd901a52a5c9c8d24b"}, + {file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d97531cdfe9bdd76d492e69800afd97e5930cb0da6a825646667b2c6c6c0211"}, + {file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d69858c32f09c3e1ce44b617b3ebba1aba030e777000ebdf72b0d8e365d0b2b3"}, + {file = "orjson-3.10.5-cp312-none-win32.whl", hash = "sha256:64c9cc089f127e5875901ac05e5c25aa13cfa5dbbbd9602bda51e5c611d6e3e2"}, + {file = "orjson-3.10.5-cp312-none-win_amd64.whl", hash = "sha256:b2efbd67feff8c1f7728937c0d7f6ca8c25ec81373dc8db4ef394c1d93d13dc5"}, + {file = "orjson-3.10.5-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:03b565c3b93f5d6e001db48b747d31ea3819b89abf041ee10ac6988886d18e01"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:584c902ec19ab7928fd5add1783c909094cc53f31ac7acfada817b0847975f26"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a35455cc0b0b3a1eaf67224035f5388591ec72b9b6136d66b49a553ce9eb1e6"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1670fe88b116c2745a3a30b0f099b699a02bb3482c2591514baf5433819e4f4d"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185c394ef45b18b9a7d8e8f333606e2e8194a50c6e3c664215aae8cf42c5385e"}, + {file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ca0b3a94ac8d3886c9581b9f9de3ce858263865fdaa383fbc31c310b9eac07c9"}, + {file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dfc91d4720d48e2a709e9c368d5125b4b5899dced34b5400c3837dadc7d6271b"}, + {file = "orjson-3.10.5-cp38-none-win32.whl", hash = "sha256:c05f16701ab2a4ca146d0bca950af254cb7c02f3c01fca8efbbad82d23b3d9d4"}, + {file = "orjson-3.10.5-cp38-none-win_amd64.whl", hash = "sha256:8a11d459338f96a9aa7f232ba95679fc0c7cedbd1b990d736467894210205c09"}, + {file = "orjson-3.10.5-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:85c89131d7b3218db1b24c4abecea92fd6c7f9fab87441cfc342d3acc725d807"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66215277a230c456f9038d5e2d84778141643207f85336ef8d2a9da26bd7ca"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:51bbcdea96cdefa4a9b4461e690c75ad4e33796530d182bdd5c38980202c134a"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbead71dbe65f959b7bd8cf91e0e11d5338033eba34c114f69078d59827ee139"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df58d206e78c40da118a8c14fc189207fffdcb1f21b3b4c9c0c18e839b5a214"}, + {file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c4057c3b511bb8aef605616bd3f1f002a697c7e4da6adf095ca5b84c0fd43595"}, + {file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b39e006b00c57125ab974362e740c14a0c6a66ff695bff44615dcf4a70ce2b86"}, + {file = "orjson-3.10.5-cp39-none-win32.whl", hash = "sha256:eded5138cc565a9d618e111c6d5c2547bbdd951114eb822f7f6309e04db0fb47"}, + {file = "orjson-3.10.5-cp39-none-win_amd64.whl", hash = "sha256:cc28e90a7cae7fcba2493953cff61da5a52950e78dc2dacfe931a317ee3d8de7"}, + {file = "orjson-3.10.5.tar.gz", hash = "sha256:7a5baef8a4284405d96c90c7c62b755e9ef1ada84c2406c24a9ebec86b89f46d"}, ] [[package]] @@ -4104,13 +4121,13 @@ files = [ [[package]] name = "pytorch-lightning" -version = "2.2.5" +version = "2.3.0" description = "PyTorch Lightning is the lightweight PyTorch wrapper for ML researchers. Scale your models. Write less boilerplate." optional = false python-versions = ">=3.8" files = [ - {file = "pytorch-lightning-2.2.5.tar.gz", hash = "sha256:8d06d0166e2204f82864f5d2b53a367c2c375d9cd5a7f6174434b2dffeaef7e9"}, - {file = "pytorch_lightning-2.2.5-py3-none-any.whl", hash = "sha256:67a7800863326914f68f6afd68f427855ef2315b4f00d554be8ea4c0f0557fd8"}, + {file = "pytorch-lightning-2.3.0.tar.gz", hash = "sha256:89caf90e3543b314508493f26e0eca8d5e10e43e3d9e6c143acd8ddceb584ce2"}, + {file = "pytorch_lightning-2.3.0-py3-none-any.whl", hash = "sha256:b8eec361f4342ca628d0d8e6985511c9515435e4db62c5e982bb1c53a5a5140a"}, ] [package.dependencies] @@ -4119,17 +4136,17 @@ lightning-utilities = ">=0.8.0" numpy = ">=1.17.2" packaging = ">=20.0" PyYAML = ">=5.4" -torch = ">=1.13.0" +torch = ">=2.0.0" torchmetrics = ">=0.7.0" tqdm = ">=4.57.0" typing-extensions = ">=4.4.0" [package.extras] -all = ["bitsandbytes (==0.41.0)", "deepspeed (>=0.8.2,<=0.9.3)", "gym[classic-control] (>=0.17.0)", "hydra-core (>=1.0.5)", "ipython[all] (<8.15.0)", "jsonargparse[signatures] (>=4.27.7)", "lightning-utilities (>=0.8.0)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "requests (<2.32.0)", "rich (>=12.3.0)", "tensorboardX (>=2.2)", "torchmetrics (>=0.10.0)", "torchvision (>=0.14.0)"] +all = ["bitsandbytes (>=0.42.0)", "deepspeed (>=0.8.2,<=0.9.3)", "hydra-core (>=1.0.5)", "ipython[all] (<8.15.0)", "jsonargparse[signatures] (>=4.27.7)", "lightning-utilities (>=0.8.0)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "requests (<2.32.0)", "rich (>=12.3.0)", "tensorboardX (>=2.2)", "torchmetrics (>=0.10.0)", "torchvision (>=0.15.0)"] deepspeed = ["deepspeed (>=0.8.2,<=0.9.3)"] -dev = ["bitsandbytes (==0.41.0)", "cloudpickle (>=1.3)", "coverage (==7.3.1)", "deepspeed (>=0.8.2,<=0.9.3)", "fastapi", "gym[classic-control] (>=0.17.0)", "hydra-core (>=1.0.5)", "ipython[all] (<8.15.0)", "jsonargparse[signatures] (>=4.27.7)", "lightning-utilities (>=0.8.0)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "onnx (>=0.14.0)", "onnxruntime (>=0.15.0)", "pandas (>1.0)", "psutil (<5.9.6)", "pytest (==7.4.0)", "pytest-cov (==4.1.0)", "pytest-random-order (==1.1.0)", "pytest-rerunfailures (==12.0)", "pytest-timeout (==2.1.0)", "requests (<2.32.0)", "rich (>=12.3.0)", "scikit-learn (>0.22.1)", "tensorboard (>=2.9.1)", "tensorboardX (>=2.2)", "torchmetrics (>=0.10.0)", "torchvision (>=0.14.0)", "uvicorn"] -examples = ["gym[classic-control] (>=0.17.0)", "ipython[all] (<8.15.0)", "lightning-utilities (>=0.8.0)", "requests (<2.32.0)", "torchmetrics (>=0.10.0)", "torchvision (>=0.14.0)"] -extra = ["bitsandbytes (==0.41.0)", "hydra-core (>=1.0.5)", "jsonargparse[signatures] (>=4.27.7)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "rich (>=12.3.0)", "tensorboardX (>=2.2)"] +dev = ["bitsandbytes (>=0.42.0)", "cloudpickle (>=1.3)", "coverage (==7.3.1)", "deepspeed (>=0.8.2,<=0.9.3)", "fastapi", "hydra-core (>=1.0.5)", "ipython[all] (<8.15.0)", "jsonargparse[signatures] (>=4.27.7)", "lightning-utilities (>=0.8.0)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "onnx (>=0.14.0)", "onnxruntime (>=0.15.0)", "pandas (>1.0)", "psutil (<5.9.6)", "pytest (==7.4.0)", "pytest-cov (==4.1.0)", "pytest-random-order (==1.1.0)", "pytest-rerunfailures (==12.0)", "pytest-timeout (==2.1.0)", "requests (<2.32.0)", "rich (>=12.3.0)", "scikit-learn (>0.22.1)", "tensorboard (>=2.9.1)", "tensorboardX (>=2.2)", "torchmetrics (>=0.10.0)", "torchvision (>=0.15.0)", "uvicorn"] +examples = ["ipython[all] (<8.15.0)", "lightning-utilities (>=0.8.0)", "requests (<2.32.0)", "torchmetrics (>=0.10.0)", "torchvision (>=0.15.0)"] +extra = ["bitsandbytes (>=0.42.0)", "hydra-core (>=1.0.5)", "jsonargparse[signatures] (>=4.27.7)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "rich (>=12.3.0)", "tensorboardX (>=2.2)"] strategies = ["deepspeed (>=0.8.2,<=0.9.3)"] test = ["cloudpickle (>=1.3)", "coverage (==7.3.1)", "fastapi", "onnx (>=0.14.0)", "onnxruntime (>=0.15.0)", "pandas (>1.0)", "psutil (<5.9.6)", "pytest (==7.4.0)", "pytest-cov (==4.1.0)", "pytest-random-order (==1.1.0)", "pytest-rerunfailures (==12.0)", "pytest-timeout (==2.1.0)", "scikit-learn (>0.22.1)", "tensorboard (>=2.9.1)", "uvicorn"] @@ -4386,13 +4403,13 @@ test = ["pytest (>=6,!=7.0.0,!=7.0.1)", "pytest-cov (>=3.0.0)", "pytest-qt"] [[package]] name = "redis" -version = "5.0.5" +version = "5.0.6" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.7" files = [ - {file = "redis-5.0.5-py3-none-any.whl", hash = "sha256:30b47d4ebb6b7a0b9b40c1275a19b87bb6f46b3bed82a89012cf56dea4024ada"}, - {file = "redis-5.0.5.tar.gz", hash = "sha256:3417688621acf6ee368dec4a04dd95881be24efd34c79f00d31f62bb528800ae"}, + {file = "redis-5.0.6-py3-none-any.whl", hash = "sha256:c0d6d990850c627bbf7be01c5c4cbaadf67b48593e913bb71c9819c30df37eee"}, + {file = "redis-5.0.6.tar.gz", hash = "sha256:38473cd7c6389ad3e44a91f4c3eaf6bcb8a9f746007f29bf4fb20824ff0b2197"}, ] [package.dependencies] @@ -4441,13 +4458,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "responses" -version = "0.25.2" +version = "0.25.3" description = "A utility library for mocking out the `requests` Python library." optional = false python-versions = ">=3.8" files = [ - {file = "responses-0.25.2-py3-none-any.whl", hash = "sha256:b59707ea25de536d324670791ab073fafd41f3a351cec9c51cb6147089a9a30a"}, - {file = "responses-0.25.2.tar.gz", hash = "sha256:77a61ad7e6016ed2ac00739b7efa5f35c42351d5b9b5d26bb1be87f197632487"}, + {file = "responses-0.25.3-py3-none-any.whl", hash = "sha256:521efcbc82081ab8daa588e08f7e8a64ce79b91c39f6e62199b19159bea7dbcb"}, + {file = "responses-0.25.3.tar.gz", hash = "sha256:617b9247abd9ae28313d57a75880422d55ec63c29d33d629697590a034358dba"}, ] [package.dependencies] @@ -5181,13 +5198,13 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "1.26.18" +version = "1.26.19" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, - {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, + {file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, + {file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, ] [package.extras] @@ -5197,13 +5214,13 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "urllib3" -version = "2.2.1" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] @@ -5575,4 +5592,4 @@ redis = ["redis"] [metadata] lock-version = "2.0" python-versions = ">=3.9, <3.13" -content-hash = "6471efa7ff70a099ab40f9c5a4fb041c6f3e96be80d3a19cd5cf66836410edb3" +content-hash = "aed49d71c5346ecb8fbf16856f748205ca56816d1370cca38b37ddcee2e32731" diff --git a/pyproject.toml b/pyproject.toml index 6f517c66..d6232499 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "numalogic" -version = "0.11.1" +version = "0.12.0" description = "Collection of operational Machine Learning models and tools." authors = ["Numalogic Developers"] packages = [{ include = "numalogic" }] @@ -35,6 +35,7 @@ orjson = "^3.9" pynumaflow = "~0.7.2" prometheus_client = "^0.18.0" structlog = "^24.1.0" +numalogic-prometheus = { version = "^0.8", allow-prereleases = true } # extras mlflow-skinny = { version = "^2.0", optional = true } @@ -43,7 +44,6 @@ boto3 = { version = "^1.24.64", optional = true } pydruid = { version = "^0.6", optional = true } PyMySQL = { version = "^1.1.0", optional = true } - [tool.poetry.extras] mlflow = ["mlflow-skinny"] redis = ["redis"] diff --git a/tests/transforms/test_transforms.py b/tests/transforms/test_transforms.py index 8a44391f..a1c6dfaf 100644 --- a/tests/transforms/test_transforms.py +++ b/tests/transforms/test_transforms.py @@ -116,7 +116,6 @@ def test_dataclipper(): tx1 = DataClipper(upper=0.1) x_ = tx1.transform(x) - print(x_) assert x.shape == x_.shape assert_array_equal(np.asarray([0.1, 0.1], dtype=np.float32), np.max(x_, axis=0)) @@ -139,9 +138,6 @@ def test_dataclipper_2(): tx = DataClipper(lower=[1.0, "-inf", 0.0], upper=[1.0, "inf", 0.7]) x_ = tx.transform(x) - - print(x) - print(x_) assert x.shape == x_.shape assert_array_equal(np.asarray([1.0, 0, 0.7], dtype=np.float32), np.max(x_, axis=0)) @@ -156,6 +152,12 @@ def test_dataclipper_3(): DataClipper() +def test_dataclipper_4(): + np.ones((5, 2)) + with pytest.raises(ValueError): + DataClipper(upper=[0.8, 0.9, 0.1], lower=2.0) + + def test_difftx(): x = np.ones((5, 3)) x[1, :] = 0 diff --git a/tests/udfs/resources/numalogic_udf_metrics.yaml b/tests/udfs/resources/numalogic_udf_metrics.yaml new file mode 100644 index 00000000..21b98f2e --- /dev/null +++ b/tests/udfs/resources/numalogic_udf_metrics.yaml @@ -0,0 +1,141 @@ +numalogic_metrics: + - type: Gauge + metrics: + - name: RECORDED_DATA_GAUGE + description: Gauge metric to observe the mean value of the window + label_pairs: + source: "numalogic_udf_metrics" + metric_name: "" + vertex: "" + composite_key: "" + config_id: "" + pipeline_id: "" + - type: Info + metrics: + - name: MODEL_INFO + description: Model Info + label_pairs: + source: "numalogic_udf_metrics" + "composite_key" : "" + "config_id" : "" + "pipeline_id": "" + - type: Summary + metrics: + - name: FETCH_TIME_SUMMARY + description: Train Data Fetch time + label_pairs: + source: "numalogic_udf_metrics" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: NAN_SUMMARY + description: Summary of NaN values + label_pairs: + source: "numalogic_udf_metrics" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: INF_SUMMARY + description: Summary of Inf values + label_pairs: + source: "numalogic_udf_metrics" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: DATAFRAME_SHAPE_SUMMARY + description: Summary of Dataframe shape + label_pairs: + source: "numalogic_udf_metrics" + composite_key: "" + config_id: "" + pipeline_id: "" + - type: Counter + metrics: + - name: MSG_IN_COUNTER + description: Count msgs flowing in + label_pairs: + source: "numalogic_udf_metrics" + vertex: "" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: MSG_DROPPED_COUNTER + description: Count msgs dropped + label_pairs: + source: "numalogic_udf_metrics" + vertex: "" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: MSG_PROCESSED_COUNTER + description: Count msgs processed + label_pairs: + source: "numalogic_udf_metrics" + vertex: "" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: SOURCE_COUNTER + description: Count artifact source (registry or cache) calls + label_pairs: + source: "numalogic_udf_metrics" + artifact_source: "" + vertex: "" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: INSUFFICIENT_DATA_COUNTER + description: Count insufficient data while Training + label_pairs: + source: "numalogic_udf_metrics" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: MODEL_STATUS_COUNTER + description: Count model status + label_pairs: + source: "numalogic_udf_metrics" + status: "" + vertex: "" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: DATASHAPE_ERROR_COUNTER + description: Count datashape errors + label_pairs: + source: "numalogic_udf_metrics" + vertex: "" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: REDIS_ERROR_COUNTER + description: Count redis errors + label_pairs: + source: "numalogic_udf_metrics" + vertex: "" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: EXCEPTION_COUNTER + description: Count exceptions + label_pairs: + source: "numalogic_udf_metrics" + vertex: "" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: RUNTIME_ERROR_COUNTER + description: Count runtime errors + label_pairs: + source: "numalogic_udf_metrics" + vertex: "" + composite_key: "" + config_id: "" + pipeline_id: "" + - name: FETCH_EXCEPTION_COUNTER + description: Count exceptions during train data fetch calls + label_pairs: + source: "numalogic_udf_metrics" + composite_key: "" + config_id: "" + pipeline_id: "" diff --git a/tests/udfs/test_inference.py b/tests/udfs/test_inference.py index dc8eb0bd..88b13e52 100644 --- a/tests/udfs/test_inference.py +++ b/tests/udfs/test_inference.py @@ -7,6 +7,7 @@ from orjson import orjson from pynumaflow.mapper import Datum +from numalogic._constants import TESTS_DIR from numalogic.config import ( NumalogicConf, ModelInfo, @@ -18,9 +19,12 @@ from numalogic.models.autoencoder.variants import VanillaAE from numalogic.registry import RedisRegistry, ArtifactData from numalogic.tools.exceptions import RedisRegistryError -from numalogic.udfs import StreamConf, InferenceUDF, MLPipelineConf +from numalogic.udfs import StreamConf, InferenceUDF, MLPipelineConf, MetricsLoader from numalogic.udfs.entities import StreamPayload, Header, Status, TrainerPayload +MetricsLoader().load_metrics( + config_file_path=f"{TESTS_DIR}/udfs/resources/numalogic_udf_metrics.yaml" +) REDIS_CLIENT = FakeStrictRedis(server=FakeServer()) KEYS = ["service-mesh", "1", "2"] DATUM_KW = { diff --git a/tests/udfs/test_main.py b/tests/udfs/test_main.py index c7868412..137c9e2f 100644 --- a/tests/udfs/test_main.py +++ b/tests/udfs/test_main.py @@ -6,10 +6,14 @@ from numalogic._constants import TESTS_DIR from numalogic.tools.exceptions import ConfigNotFoundError +from numalogic.udfs import MetricsLoader BASE_CONFIG_PATH = f"{TESTS_DIR}/udfs/resources/_config3.yaml" APP_CONFIG_PATH = f"{TESTS_DIR}/udfs/resources/_config4.yaml" REDIS_AUTH = "123" +MetricsLoader().load_metrics( + config_file_path=f"{TESTS_DIR}/udfs/resources/numalogic_udf_metrics.yaml" +) class TestMainScript(unittest.TestCase): diff --git a/tests/udfs/test_pipeline.py b/tests/udfs/test_pipeline.py index e4e0ee5e..46db32e9 100644 --- a/tests/udfs/test_pipeline.py +++ b/tests/udfs/test_pipeline.py @@ -6,10 +6,13 @@ import pytest from numalogic._constants import TESTS_DIR -from numalogic.udfs import PipelineConf +from numalogic.udfs import PipelineConf, MetricsLoader from numalogic.udfs.payloadtx import PayloadTransformer from tests.udfs.utility import input_json_from_file +MetricsLoader().load_metrics( + config_file_path=f"{TESTS_DIR}/udfs/resources/numalogic_udf_metrics.yaml" +) logging.basicConfig(level=logging.DEBUG) KEYS = ["service-mesh", "1", "2"] DATUM = input_json_from_file(os.path.join(TESTS_DIR, "udfs", "resources", "data", "stream.json")) diff --git a/tests/udfs/test_postprocess.py b/tests/udfs/test_postprocess.py index e0b5e853..ad78f753 100644 --- a/tests/udfs/test_postprocess.py +++ b/tests/udfs/test_postprocess.py @@ -15,10 +15,13 @@ from numalogic.models.threshold import StdDevThreshold from numalogic.registry import RedisRegistry, ArtifactData from numalogic.transforms import TanhNorm -from numalogic.udfs import PipelineConf +from numalogic.udfs import PipelineConf, MetricsLoader from numalogic.udfs.entities import Header, TrainerPayload, Status, OutputPayload from numalogic.udfs.postprocess import PostprocessUDF +MetricsLoader().load_metrics( + config_file_path=f"{TESTS_DIR}/udfs/resources/numalogic_udf_metrics.yaml" +) logging.basicConfig(level=logging.DEBUG) REDIS_CLIENT = FakeStrictRedis(server=FakeServer()) KEYS = ["service-mesh", "1", "2"] diff --git a/tests/udfs/test_preprocess.py b/tests/udfs/test_preprocess.py index 2676670e..1aa6944a 100644 --- a/tests/udfs/test_preprocess.py +++ b/tests/udfs/test_preprocess.py @@ -13,6 +13,7 @@ from numalogic._constants import TESTS_DIR from numalogic.registry import RedisRegistry from numalogic.tools.exceptions import ModelKeyNotFound +from numalogic.udfs import MetricsLoader from numalogic.udfs._config import PipelineConf from numalogic.udfs.entities import Status, Header, StreamPayload, TrainerPayload from numalogic.udfs.preprocess import PreprocessUDF @@ -27,6 +28,9 @@ "event_time": datetime.now(), "watermark": datetime.now(), } +MetricsLoader().load_metrics( + config_file_path=f"{TESTS_DIR}/udfs/resources/numalogic_udf_metrics.yaml" +) @pytest.fixture diff --git a/tests/udfs/test_rds_trainer.py b/tests/udfs/test_rds_trainer.py index a9c520fb..d0be208a 100644 --- a/tests/udfs/test_rds_trainer.py +++ b/tests/udfs/test_rds_trainer.py @@ -21,13 +21,16 @@ from pynumaflow.mapper import Datum from orjson import orjson from omegaconf import OmegaConf -from numalogic.udfs import StreamConf, PipelineConf, MLPipelineConf +from numalogic.udfs import StreamConf, PipelineConf, MLPipelineConf, MetricsLoader from numalogic.config import NumalogicConf, ModelInfo from numalogic.config import TrainerConf, LightningTrainerConf import time from freezegun import freeze_time REDIS_CLIENT = FakeStrictRedis(server=FakeServer()) +MetricsLoader().load_metrics( + config_file_path=f"{TESTS_DIR}/udfs/resources/numalogic_udf_metrics.yaml" +) # @pytest.fixture diff --git a/tests/udfs/test_staticthresh.py b/tests/udfs/test_staticthresh.py index a5db196e..7b3c0b25 100644 --- a/tests/udfs/test_staticthresh.py +++ b/tests/udfs/test_staticthresh.py @@ -9,10 +9,13 @@ from pynumaflow.mapper import Datum from numalogic._constants import TESTS_DIR -from numalogic.udfs import PipelineConf +from numalogic.udfs import PipelineConf, MetricsLoader from numalogic.udfs.entities import Status, Header, OutputPayload from numalogic.udfs.staticthresh import StaticThresholdUDF +MetricsLoader().load_metrics( + config_file_path=f"{TESTS_DIR}/udfs/resources/numalogic_udf_metrics.yaml" +) logging.basicConfig(level=logging.DEBUG) KEYS = ["service-mesh", "1", "2"] DATUM_KW = {