github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/sawtooth_validator/concurrent/threadpool.py (about) 1 # Copyright 2017 Intel Corporation 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 # ------------------------------------------------------------------------------ 15 16 import logging 17 import os 18 19 from concurrent.futures import ThreadPoolExecutor 20 21 from sawtooth_validator import metrics 22 23 24 LOGGER = logging.getLogger(__name__) 25 COLLECTOR = metrics.get_collector(__name__) 26 27 28 class InstrumentedThreadPoolExecutor(ThreadPoolExecutor): 29 def __init__(self, max_workers=None, name='', trace=None): 30 if trace is None: 31 self._trace = 'SAWTOOTH_TRACE_LOGGING' in os.environ 32 else: 33 self._trace = trace 34 35 self._name = name 36 if name == '': 37 self._name = 'Instrumented' 38 39 LOGGER.debug('Creating thread pool executor %s', self._name) 40 41 super().__init__(max_workers) 42 43 self._workers_in_use = COLLECTOR.counter( 44 "workers_in_use", 45 instance=self, 46 tags={"name": self._name}) 47 # Tracks how long tasks take to run 48 self._task_run_timer = COLLECTOR.timer( 49 "task_run_time", 50 instance=self, 51 tags={"name": self._name}) 52 # Tracks how long tasks wait in the queue 53 self._task_time_in_queue_timer = COLLECTOR.timer( 54 "task_time_in_queue", 55 instance=self, 56 tags={"name": self._name}) 57 58 def submit(self, fn, *args, **kwargs): 59 time_in_queue_ctx = self._task_time_in_queue_timer.time() 60 61 try: 62 task_name = fn.__qualname__ 63 except AttributeError: 64 task_name = str(fn) 65 66 if self._trace: 67 task_details = '{}[{},{}]'.format(fn, args, kwargs) 68 else: 69 task_details = task_name 70 71 def wrapper(): 72 time_in_queue_ctx.stop() 73 74 self._workers_in_use.inc() 75 76 if self._trace: 77 LOGGER.debug( 78 '(%s) Executing task %s', self._name, task_details) 79 80 with self._task_run_timer.time(): 81 return_value = None 82 try: 83 return_value = fn(*args, **kwargs) 84 # pylint: disable=broad-except 85 except Exception: 86 LOGGER.exception( 87 '(%s) Unhandled exception during execution of task %s', 88 self._name, 89 task_details) 90 91 self._workers_in_use.dec() 92 93 if self._trace: 94 LOGGER.debug( 95 '(%s) Finished task %s', self._name, task_details) 96 97 return return_value 98 99 return super().submit(wrapper)