Skip to content
Snippets Groups Projects
Commit eee23b46 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Performance Evaluation Method Wrapper

- Initial version (not functional)
parent feea6f16
No related branches found
No related tags found
2 merge requests!54Release 2.0.0,!36Performance Evaluation Framework + Helper Tools
# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
#
# 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 threading
from enum import Enum
from typing import Dict, Tuple
from prometheus_client import Counter, Histogram
from prometheus_client.metrics import MetricWrapperBase, INF
class MetricTypeEnum(Enum):
COUNTER_STARTED = '{:s}_counter_requests_started'
COUNTER_COMPLETED = '{:s}_counter_requests_completed'
COUNTER_FAILED = '{:s}_counter_requests_failed'
HISTOGRAM_DURATION = '{:s}_histogram_duration'
METRIC_TO_CLASS_PARAMS = {
MetricTypeEnum.COUNTER_STARTED : (Counter, {}),
MetricTypeEnum.COUNTER_COMPLETED : (Counter, {}),
MetricTypeEnum.COUNTER_FAILED : (Counter, {}),
MetricTypeEnum.HISTOGRAM_DURATION: (Histogram, {
'buckets': (.005, .01, .025, .05, .075, .1, .25, .5, .75, 1.0, INF)
})
}
class MetricsPool:
def __init__(self) -> None:
self._metrics : Dict[str, MetricWrapperBase] = dict()
self._lock = threading.Lock()
def get_or_create(self, function_name : str, metric_type : MetricTypeEnum, **metric_params) -> MetricWrapperBase:
metric_name = str(metric_type.value).format(function_name).upper()
with self._lock:
if metric_name not in self._metrics:
metric_tuple : Tuple[MetricWrapperBase, Dict] = METRIC_TO_CLASS_PARAMS.get(metric_type)
metric_class, default_metric_params = metric_tuple
if len(metric_params) == 0: metric_params = default_metric_params
self._metrics[metric_name] = metric_class(metric_name, '', **metric_params)
return self._metrics[metric_name]
def meter_method(metrics_pool : MetricsPool):
def outer_wrapper(func):
func_name = func.__name__
histogram_duration : Histogram = metrics_pool.get_or_create(func_name, MetricTypeEnum.HISTOGRAM_DURATION)
counter_started : Counter = metrics_pool.get_or_create(func_name, MetricTypeEnum.COUNTER_STARTED)
counter_completed : Counter = metrics_pool.get_or_create(func_name, MetricTypeEnum.COUNTER_COMPLETED)
counter_failed : Counter = metrics_pool.get_or_create(func_name, MetricTypeEnum.COUNTER_FAILED)
@histogram_duration.time()
def inner_wrapper(self, *args, **kwargs):
counter_started.inc()
try:
reply = func(self, *args, **kwargs)
counter_completed.inc()
return reply
except KeyboardInterrupt: # pylint: disable=try-except-raise
raise
except Exception: # pylint: disable=broad-except
counter_failed.inc()
return inner_wrapper
return outer_wrapper
# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
#
# 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.
# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
#
# 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 random, time
from common.perf_eval_method_wrapper.Decorator import MetricsPool, meter_method
EXCEPTION_RATIO = 0.05
METRICS_POOL = MetricsPool()
class DummyDeviceDriver:
def __init__(self) -> None:
pass
@meter_method(METRICS_POOL)
def get_config(self):
if random.random() < EXCEPTION_RATIO: raise Exception()
time.sleep(random.random())
@meter_method(METRICS_POOL)
def set_config(self):
if random.random() < EXCEPTION_RATIO: raise Exception()
time.sleep(random.random())
@meter_method(METRICS_POOL)
def del_config(self):
if random.random() < EXCEPTION_RATIO: raise Exception()
time.sleep(random.random())
# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
#
# 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.
#!/bin/bash
# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
#
# 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.
docker create -it --name=prometheus -p 9090:9090 \
-v /home/tfs/tfs-ctrl/test-prom-cli/prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheus
docker create -it --name=grafana -p 3000:3000 \
grafana/grafana
# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
#
# 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.
global:
scrape_interval: 15s # when Prometheus is pulling data from exporters etc
evaluation_interval: 30s # time between each evaluation of Prometheus' alerting rules
scrape_configs:
- job_name: ddd # your project name
static_configs:
- targets:
- 172.17.0.1:8000
# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
#
# 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 grpc, logging, time
from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method
logging.basicConfig(level=logging.DEBUG)
LOGGER = logging.getLogger(__name__)
def test_database_instantiation():
SERVICE_NAME = 'Context'
METHOD_NAMES = [
'ListContextIds', 'ListContexts', 'GetContext', 'SetContext', 'RemoveContext', 'GetContextEvents',
'ListTopologyIds', 'ListTopologies', 'GetTopology', 'SetTopology', 'RemoveTopology', 'GetTopologyEvents',
'ListDeviceIds', 'ListDevices', 'GetDevice', 'SetDevice', 'RemoveDevice', 'GetDeviceEvents',
'ListLinkIds', 'ListLinks', 'GetLink', 'SetLink', 'RemoveLink', 'GetLinkEvents',
'ListServiceIds', 'ListServices', 'GetService', 'SetService', 'RemoveService', 'GetServiceEvents',
]
METRICS = create_metrics(SERVICE_NAME, METHOD_NAMES)
class TestServiceServicerImpl:
@safe_and_metered_rpc_method(METRICS, LOGGER)
def GetTopology(self, request, grpc_context : grpc.ServicerContext):
print('doing funny things')
time.sleep(0.1)
return 'done'
tssi = TestServiceServicerImpl()
tssi.GetTopology(1, 2)
for metric_name,metric in METRICS.items():
if 'GETTOPOLOGY_' not in metric_name: continue
print(metric_name, metric._child_samples()) # pylint: disable=protected-access
import random
from prometheus_client import start_http_server
from DummyDeviceDriver import DummyDeviceDriver
def main():
# Start up the server to expose the metrics
start_http_server(8000)
ddd = DummyDeviceDriver()
while True:
func = random.choice([ddd.get_config, ddd.set_config, ddd.del_config])
func()
if __name__ == '__main__':
main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment