Skip to content

Commit f66eb9b

Browse files
committed
Added mlmonitoring directory in mlflow-ubuntu22.04-py312-cpu-inference environment
1 parent 65acc57 commit f66eb9b

File tree

20 files changed

+1287
-0
lines changed

20 files changed

+1287
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"""For init."""
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
5+
from .collector import Collector
6+
7+
__all__ = ["Collector"]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""For collector."""
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
5+
from typing import Callable, Any
6+
7+
from .collector_json import JsonCollector
8+
from .context import CorrelationContext
9+
10+
11+
class Collector:
12+
"""For collector class."""
13+
14+
def __init__(
15+
self,
16+
*,
17+
name: str,
18+
on_error: Callable[[Exception], Any] = None
19+
):
20+
"""For init."""
21+
self._impl = JsonCollector(name=name, on_error=on_error)
22+
23+
def collect(
24+
self,
25+
data, # supported type: Union[pd.DataFrame]
26+
correlation_context: CorrelationContext = None) -> CorrelationContext:
27+
"""For collect."""
28+
return self._impl.collect(data, correlation_context)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""For Collector base."""
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
5+
import logging
6+
7+
from .init import init, is_sdk_ready
8+
from .config import get_config
9+
from .context import CorrelationContext, get_context_wrapper
10+
11+
12+
class CollectorBase:
13+
"""For CollectorBase."""
14+
15+
def __init__(
16+
self,
17+
model_version: str):
18+
"""For init."""
19+
if not is_sdk_ready():
20+
init(model_version)
21+
22+
self.logger = logging.getLogger("mdc.collector")
23+
self.config = get_config()
24+
25+
def _response(
26+
self,
27+
context: CorrelationContext,
28+
success: bool,
29+
message: str) -> CorrelationContext:
30+
"""For response."""
31+
if self.config.is_debug():
32+
return get_context_wrapper(context, success, message)
33+
34+
return context
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
"""For collector json."""
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
5+
import sys
6+
import random
7+
from typing import Callable, Any
8+
9+
from .payload import PandasFrameData
10+
from .payload.payload import build_payload
11+
from .queue import get_queue
12+
13+
from .collector_base import CollectorBase
14+
from .context import CorrelationContext, get_context
15+
16+
try:
17+
import pandas as pd
18+
except ImportError:
19+
pass
20+
21+
22+
def _build_log_data_by_type(data):
23+
"""For build log data by type."""
24+
if 'pandas' in sys.modules and isinstance(data, pd.DataFrame):
25+
return PandasFrameData(data)
26+
27+
raise TypeError("data type (%s) not supported, "
28+
"supported types: pandas.DataFrame"
29+
% type(data).__name__)
30+
31+
32+
def _raise_if_exception(e: Exception):
33+
"""For raise if exception."""
34+
raise e
35+
36+
37+
class JsonCollector(CollectorBase):
38+
"""For JsonCollector."""
39+
40+
def __init__(
41+
self,
42+
*,
43+
name: str,
44+
on_error: Callable[[Exception], Any] = None
45+
):
46+
"""For init."""
47+
super().__init__("default")
48+
self.name = name
49+
if on_error:
50+
self.on_error = on_error
51+
else:
52+
self.on_error = _raise_if_exception
53+
54+
self._validate_mdc_config()
55+
56+
def _validate_mdc_config(self):
57+
"""For validate mdc config."""
58+
if not self.name or len(self.name) <= 0:
59+
# unexpected drop
60+
msg = "collection name is not provided"
61+
self.on_error(Exception(msg))
62+
return False, msg
63+
64+
config = self.config
65+
if config is None:
66+
# unexpected drop
67+
msg = "data collector is not initialized"
68+
self.on_error(Exception(msg))
69+
return False, msg
70+
71+
if not config.enabled():
72+
# unexpected drop
73+
msg = "custom logging is not enabled, drop the data"
74+
self.on_error(Exception(msg))
75+
return False, msg
76+
77+
if not config.collection_enabled(self.name):
78+
# unexpected drop
79+
msg = "collection {} is not enabled, drop the data".format(self.name)
80+
self.on_error(Exception(msg))
81+
return False, msg
82+
83+
return True, None
84+
85+
def collect(
86+
self,
87+
data, # supported type: Union[pd.DataFrame]
88+
correlation_context: CorrelationContext = None) -> CorrelationContext:
89+
"""For collect."""
90+
if correlation_context is None:
91+
correlation_context = get_context()
92+
93+
success, msg = self._validate_mdc_config()
94+
95+
if not success:
96+
return self._response(correlation_context, False, msg)
97+
98+
config = self.config
99+
100+
percentage = config.collection_sample_rate_percentage(self.name)
101+
102+
if percentage < 100:
103+
if percentage <= random.random() * 100.0:
104+
# expected drop
105+
self.logger.debug("sampling not hit, drop the data")
106+
# TBD: send empty message to mdc to collect metrics of dropped messages?
107+
return self._response(correlation_context, False, "dropped_sampling")
108+
109+
try:
110+
# build payload and put into payload queue
111+
log_data = _build_log_data_by_type(data)
112+
except TypeError as e:
113+
# unexpected drop
114+
self.on_error(e)
115+
return self._response(correlation_context, False, e.args[0])
116+
117+
payload = build_payload(
118+
self.name,
119+
data=log_data,
120+
model_version=config.model_version(),
121+
context=correlation_context)
122+
123+
success, msg = get_queue().enqueue(payload)
124+
125+
if not success:
126+
# unexpected drop
127+
self.on_error(Exception(msg))
128+
return self._response(correlation_context, success, msg)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""For init."""
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
5+
__version__ = "0.1.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"""For init."""
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
5+
from .config import init_config, teardown_config, is_debug, get_config
6+
7+
__all__ = ["init_config", "teardown_config", "is_debug", "get_config"]

0 commit comments

Comments
 (0)