From a8307e4e75c5c57a6d68f81c563ca7b7d0b38b11 Mon Sep 17 00:00:00 2001 From: Adrian Date: Thu, 19 Sep 2019 16:51:06 +0200 Subject: [PATCH 01/17] Custom logger every type of automation --- connect/logger/logger.py | 26 ++++++++------------- connect/resources/automation_engine.py | 3 ++- connect/resources/fulfillment_automation.py | 8 +++++++ connect/resources/tier_config_automation.py | 8 +++++++ connect/resources/usage_automation.py | 11 ++++++++- connect/resources/usage_file_automation.py | 9 +++++++ 6 files changed, 47 insertions(+), 18 deletions(-) diff --git a/connect/logger/logger.py b/connect/logger/logger.py index eaef84c..e271b17 100644 --- a/connect/logger/logger.py +++ b/connect/logger/logger.py @@ -14,29 +14,23 @@ config = json.load(config_file) dictConfig(config['logging']) -logger = logging.getLogger() -def log_request_data(args): - if len(args) and isinstance(args[0], BaseModel): - global logger - base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line"\ - "-%(lineno)d: %(message)s" - sformat = args[0].id + base - if isinstance(args[0], Fulfillment): - sformat = args[0].asset.id + " " + sformat - [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) - for handler in logger.handlers] +def function_log(func, custom_logger=None): + if not custom_logger: + custom_logger = logging.getLogger() + sformat = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ + "-%(lineno)d: %(message)s" + [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) + for handler in custom_logger.handlers] -def function_log(func): @wraps(func) def decorator(self, *args, **kwargs): - log_request_data(args) - logger.info('Entering: %s', func.__name__) - logger.debug('Function params: {} {}'.format(args, kwargs)) + custom_logger.info('Entering: %s', func.__name__) + custom_logger.debug('Function params: {} {}'.format(args, kwargs)) result = func(self, *args, **kwargs) - logger.debug( + custom_logger.debug( 'Function `{}.{}` return: {}'.format(self.__class__.__name__, func.__name__, result)) return result diff --git a/connect/resources/automation_engine.py b/connect/resources/automation_engine.py index 331f213..f9279c9 100644 --- a/connect/resources/automation_engine.py +++ b/connect/resources/automation_engine.py @@ -4,7 +4,7 @@ # Copyright (c) 2019 Ingram Micro. All Rights Reserved. from typing import Any, Dict - +import logging from connect.logger import function_log from connect.models import ActivationTileResponse, BaseModel from .base import BaseResource @@ -13,6 +13,7 @@ class AutomationEngine(BaseResource): limit = 1000 # type: int + logger = logging.getLogger() def filters(self, status='pending', **kwargs): # type: (str, Dict[str, Any]) -> Dict[str, Any] diff --git a/connect/resources/fulfillment_automation.py b/connect/resources/fulfillment_automation.py index f7a00da..d5d971b 100644 --- a/connect/resources/fulfillment_automation.py +++ b/connect/resources/fulfillment_automation.py @@ -3,6 +3,7 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. +import logging from abc import ABCMeta from deprecation import deprecated @@ -36,6 +37,7 @@ class FulfillmentAutomation(AutomationEngine): __metaclass__ = ABCMeta resource = 'requests' model_class = Fulfillment + logger = logging.getLogger('Fullfilment.logger') def filters(self, status='pending', **kwargs): """ Returns the default set of filters for Fulfillment request, plus any others that you @@ -72,6 +74,12 @@ def filters(self, status='pending', **kwargs): def dispatch(self, request): # type: (Fulfillment) -> str + base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ + "-%(lineno)d: %(message)s" + sformat = request.asset.id + " " + request.id + base + [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) + for handler in self.logger.handlers] + conversation = request.get_conversation(self.config) try: diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index ffc0e2f..5f57364 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -3,6 +3,7 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. +import logging from abc import ABCMeta from connect.exceptions import FailRequest, InquireRequest, SkipRequest @@ -33,11 +34,18 @@ class TierConfigAutomation(AutomationEngine): __metaclass__ = ABCMeta resource = 'tier/config-requests' model_class = TierConfigRequest + logger = logging.getLogger('UsageFile.logger') @function_log def dispatch(self, request): # type: (TierConfigRequest) -> str try: + base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ + "-%(lineno)d: %(message)s" + sformat = request.id + base + [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) + for handler in self.logger.handlers] + if self.config.products \ and request.configuration.product.id not in self.config.products: return 'Invalid product' diff --git a/connect/resources/usage_automation.py b/connect/resources/usage_automation.py index 7fd45e3..2edef6d 100644 --- a/connect/resources/usage_automation.py +++ b/connect/resources/usage_automation.py @@ -4,6 +4,7 @@ # Copyright (c) 2019 Ingram Micro. All Rights Reserved. import json +import logging from abc import ABCMeta from tempfile import NamedTemporaryFile @@ -26,6 +27,7 @@ class UsageAutomation(AutomationEngine): __metaclass__ = ABCMeta resource = 'listings' model_class = UsageFile + logger = logging.getLogger('Usage.logger') def filters(self, status='listed', **kwargs): """ @@ -42,7 +44,14 @@ def filters(self, status='listed', **kwargs): def dispatch(self, request): # type: (UsageListing) -> str - # TODO Shouldn't this raise an exception on ALL automation classes? + base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ + "-%(lineno)d: %(message)s" + sformat = request.contract.marketplace.id + " " + request.id + base + [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) + for handler in self.logger.handlers] + + + # TODO Shouldn't this raise an exception on ALL automation classes? if self.config.products \ and request.product.id not in self.config.products: return 'Listing not handled by this processor' diff --git a/connect/resources/usage_file_automation.py b/connect/resources/usage_file_automation.py index 415b02a..c5d085a 100644 --- a/connect/resources/usage_file_automation.py +++ b/connect/resources/usage_file_automation.py @@ -3,6 +3,7 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. +import logging from abc import ABCMeta from connect.exceptions import SkipRequest, UsageFileAction @@ -20,6 +21,7 @@ class UsageFileAutomation(AutomationEngine): __metaclass__ = ABCMeta resource = 'usage/files' model_class = UsageFile + logger = logging.getLogger('UsageFile.logger') def filters(self, status='ready', **kwargs): """ @@ -35,6 +37,13 @@ def filters(self, status='ready', **kwargs): def dispatch(self, request): # type: (UsageFile) -> str + + base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ + "-%(lineno)d: %(message)s" + sformat = request.marketplace.id + " " + request.id + base + [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) + for handler in self.logger.handlers] + try: # Validate product if self.config.products \ From c5db43d7d430ac96299a7b003956da102bb77f11 Mon Sep 17 00:00:00 2001 From: Adrian Date: Thu, 19 Sep 2019 17:48:09 +0200 Subject: [PATCH 02/17] Add call to self logger --- connect/logger/__init__.py | 2 +- connect/logger/logger.py | 1 - connect/resources/base.py | 5 +++-- connect/resources/fulfillment_automation.py | 8 ++++---- connect/resources/tier_config_automation.py | 6 +++--- connect/resources/usage_automation.py | 16 ++++++++-------- connect/resources/usage_file_automation.py | 6 +++--- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/connect/logger/__init__.py b/connect/logger/__init__.py index fff901a..365f498 100644 --- a/connect/logger/__init__.py +++ b/connect/logger/__init__.py @@ -3,7 +3,7 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. -from .logger import function_log, logger +from .logger import function_log # TODO add auto settings for cloud platforms diff --git a/connect/logger/logger.py b/connect/logger/logger.py index e271b17..f18821f 100644 --- a/connect/logger/logger.py +++ b/connect/logger/logger.py @@ -16,7 +16,6 @@ dictConfig(config['logging']) - def function_log(func, custom_logger=None): if not custom_logger: custom_logger = logging.getLogger() diff --git a/connect/resources/base.py b/connect/resources/base.py index d1dc043..400dd39 100644 --- a/connect/resources/base.py +++ b/connect/resources/base.py @@ -6,7 +6,7 @@ import functools from typing import Any, List, Dict, Tuple -import requests +import requests, logging from requests import compat from connect.config import Config @@ -122,6 +122,7 @@ class BaseResource(object): resource = None # type: str limit = 100 # type: int model_class = BaseModel + logger = logging.getLogger() def __init__(self, config=None): # Set client @@ -155,6 +156,6 @@ def filters(self, **kwargs): def list(self, filters=None): # type: (Dict[str, Any]) -> List[Any] filters = filters or self.filters() - logger.info('Get list request with filters - {}'.format(filters)) + self.logger.info('Get list request with filters - {}'.format(filters)) response, _ = self._api.get(params=filters) return self.model_class.deserialize(response) diff --git a/connect/resources/fulfillment_automation.py b/connect/resources/fulfillment_automation.py index d5d971b..761271c 100644 --- a/connect/resources/fulfillment_automation.py +++ b/connect/resources/fulfillment_automation.py @@ -87,11 +87,11 @@ def dispatch(self, request): and request.asset.product.id not in self.config.products: return 'Invalid product' - logger.info('Start request process / ID request - {}'.format(request.id)) + self.logger.info('Start request process / ID request - {}'.format(request.id)) process_result = self.process_request(request) if not process_result: - logger.info('Method `process_request` did not return result') + self.logger.info('Method `process_request` did not return result') return '' if isinstance(process_result, ActivationTileResponse): @@ -129,7 +129,7 @@ def dispatch(self, request): raise except Exception as ex: - logger.warning('Skipping request {} because an exception was raised: {}' + self.logger.warning('Skipping request {} because an exception was raised: {}' .format(request.id, ex)) return '' @@ -196,5 +196,5 @@ def _update_conversation_if_exists(conversation, request_id, obj): try: conversation.add_message(str(obj)) except TypeError as ex: - logger.error('Error updating conversation for request {}: {}' + self.logger.error('Error updating conversation for request {}: {}' .format(request_id, ex)) diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index 5f57364..0402397 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -50,12 +50,12 @@ def dispatch(self, request): and request.configuration.product.id not in self.config.products: return 'Invalid product' - logger.info( + self.logger.info( 'Start tier config request process / ID request - {}'.format(request.id)) result = self.process_request(request) if not result: - logger.info('Method `process_request` did not return result') + self.logger.info('Method `process_request` did not return result') return '' params = {} @@ -80,7 +80,7 @@ def dispatch(self, request): raise except Exception as ex: - logger.warning('Skipping request {} because an exception was raised: {}' + self.logger.warning('Skipping request {} because an exception was raised: {}' .format(request.id, ex)) return '' diff --git a/connect/resources/usage_automation.py b/connect/resources/usage_automation.py index 2edef6d..5b3efc1 100644 --- a/connect/resources/usage_automation.py +++ b/connect/resources/usage_automation.py @@ -56,7 +56,7 @@ def dispatch(self, request): and request.product.id not in self.config.products: return 'Listing not handled by this processor' - logger.info( + self.logger.info( 'Processing Usage for Product {} ({}) '.format(request.product.id, request.product.name) + 'on Contract {} '.format(request.contract.id) + @@ -65,14 +65,14 @@ def dispatch(self, request): try: result = self.process_request(request) except FileCreationError: - logger.info( + self.logger.info( 'Error processing Usage for Product {} ({}) '.format(request.product.id, request.product.name) + 'on Contract {} '.format(request.contract.id) + 'and provider {}({})'.format(request.provider.id, request.provider.name)) return 'failure' - logger.info('Processing result for usage on listing {}: {}' + self.logger.info('Processing result for usage on listing {}: {}' .format(request.product.id, result)) return 'success' @@ -87,13 +87,13 @@ def get_usage_template(self, product): location = self._get_usage_template_download_location(product.id) if not location: msg = 'Error obtaining template usage file location' - logger.error(msg) + self.logger.error(msg) raise FileRetrievalError(msg) contents = self._retrieve_usage_template(location) if location else None if not contents: msg = 'Error obtaining template usage file from `{}`'.format(location) - logger.error(msg) + self.logger.error(msg) raise FileRetrievalError(msg) return contents @@ -187,7 +187,7 @@ def _upload_spreadsheet(self, usage_file, spreadsheet): headers['Accept'] = 'application/json' del headers['Content-Type'] # This must NOT be set for multipart post requests multipart = {'usage_file': ('usage_file.xlsx', file_contents)} - logger.info('HTTP Request: {} - {} - {}'.format(url, headers, multipart)) + self.logger.info('HTTP Request: {} - {} - {}'.format(url, headers, multipart)) # Post request try: @@ -197,8 +197,8 @@ def _upload_spreadsheet(self, usage_file, spreadsheet): files=multipart) except requests.RequestException as ex: raise FileCreationError('Error uploading file: {}'.format(ex)) - logger.info('HTTP Code: {}'.format(status)) + self.logger.info('HTTP Code: {}'.format(status)) if status != 201: msg = 'Unexpected server response, returned code {}'.format(status) - logger.error('{} -- Raw response: {}'.format(msg, content)) + self.logger.error('{} -- Raw response: {}'.format(msg, content)) raise FileCreationError(msg) diff --git a/connect/resources/usage_file_automation.py b/connect/resources/usage_file_automation.py index c5d085a..67ab990 100644 --- a/connect/resources/usage_file_automation.py +++ b/connect/resources/usage_file_automation.py @@ -51,7 +51,7 @@ def dispatch(self, request): return 'Invalid product' # Process request - logger.info( + self.logger.info( 'Start usage file request process / ID request - {}'.format(request.id)) result = self.process_request(request) @@ -59,7 +59,7 @@ def dispatch(self, request): processing_result = 'UsageFileAutomation.process_request returned {} while ' \ 'is expected to raise UsageFileAction or SkipRequest exception' \ .format(str(result)) - logger.warning(processing_result) + self.logger.warning(processing_result) raise UserWarning(processing_result) # Catch action @@ -75,6 +75,6 @@ def dispatch(self, request): except SkipRequest: processing_result = 'skip' - logger.info('Finished processing of usage file with ID {} with result {}' + self.logger.info('Finished processing of usage file with ID {} with result {}' .format(request.id, processing_result)) return processing_result From 05caadaa1848398d1fd655b60d7d195effbf5aaa Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 20 Sep 2019 09:56:41 +0200 Subject: [PATCH 03/17] Decorator parameters and generic global loger (deprecated) --- connect/logger/logger.py | 25 ++++++++++++--------- connect/resources/automation_engine.py | 8 +++---- connect/resources/fulfillment_automation.py | 12 +++++----- connect/resources/tier_config_automation.py | 4 ++-- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/connect/logger/logger.py b/connect/logger/logger.py index f18821f..3e850a9 100644 --- a/connect/logger/logger.py +++ b/connect/logger/logger.py @@ -15,8 +15,10 @@ dictConfig(config['logging']) +logger = logging.getLogger("Generic.logger") -def function_log(func, custom_logger=None): + +def function_log(custom_logger=None): if not custom_logger: custom_logger = logging.getLogger() sformat = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ @@ -24,13 +26,14 @@ def function_log(func, custom_logger=None): [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) for handler in custom_logger.handlers] - @wraps(func) - def decorator(self, *args, **kwargs): - custom_logger.info('Entering: %s', func.__name__) - custom_logger.debug('Function params: {} {}'.format(args, kwargs)) - result = func(self, *args, **kwargs) - custom_logger.debug( - 'Function `{}.{}` return: {}'.format(self.__class__.__name__, func.__name__, result)) - return result - - return decorator + def real_function_log(func): + @wraps(func) + def decorator(self, *args, **kwargs): + custom_logger.info('Entering: %s', func.__name__) + custom_logger.debug('Function params: {} {}'.format(args, kwargs)) + result = func(self, *args, **kwargs) + custom_logger.debug( + 'Function `{}.{}` return: {}'.format(self.__class__.__name__, func.__name__, result)) + return result + + return decorator diff --git a/connect/resources/automation_engine.py b/connect/resources/automation_engine.py index f9279c9..5f8f2e4 100644 --- a/connect/resources/automation_engine.py +++ b/connect/resources/automation_engine.py @@ -33,22 +33,22 @@ def process_request(self, request): raise NotImplementedError('Please implement `{}.process_request` method' .format(self.__class__.__name__)) - @function_log + @function_log(custom_logger=logger) def approve(self, pk, data): # type: (str, dict) -> str return self._api.post(path=pk + '/approve/', json=data)[0] - @function_log + @function_log(custom_logger=logger) def inquire(self, pk): # type: (str) -> str return self._api.post(path=pk + '/inquire/', json={})[0] - @function_log + @function_log(custom_logger=logger) def fail(self, pk, reason): # type: (str, str) -> str return self._api.post(path=pk + '/fail/', json={'reason': reason})[0] - @function_log + @function_log(custom_logger=logger) def render_template(self, pk, template_id): # type: (str, str) -> ActivationTileResponse return TemplateResource(self.config).render(template_id, pk) diff --git a/connect/resources/fulfillment_automation.py b/connect/resources/fulfillment_automation.py index 761271c..dce3193 100644 --- a/connect/resources/fulfillment_automation.py +++ b/connect/resources/fulfillment_automation.py @@ -70,7 +70,7 @@ def filters(self, status='pending', **kwargs): filters['asset.product.id__in'] = ','.join(self.config.products) return filters - @function_log + @function_log(custom_logger=logger) def dispatch(self, request): # type: (Fulfillment) -> str @@ -130,7 +130,7 @@ def dispatch(self, request): except Exception as ex: self.logger.warning('Skipping request {} because an exception was raised: {}' - .format(request.id, ex)) + .format(request.id, ex)) return '' def create_request(self, request): @@ -171,7 +171,7 @@ def get_tier_config(self, tier_id, product_id): else: return None - @function_log + @function_log(custom_logger=logger) def update_parameters(self, pk, params): """ Sends a list of Param objects to Connect for updating. @@ -183,18 +183,16 @@ def update_parameters(self, pk, params): list_dict = [] for _ in params: list_dict.append(_.__dict__ if isinstance(_, Param) else _) - return self._api.put( path=pk, json={'asset': {'params': list_dict}}, )[0] - @staticmethod - def _update_conversation_if_exists(conversation, request_id, obj): + def _update_conversation_if_exists(self, conversation, request_id, obj): # type: (Optional[Conversation], str, object) -> None if conversation: try: conversation.add_message(str(obj)) except TypeError as ex: self.logger.error('Error updating conversation for request {}: {}' - .format(request_id, ex)) + .format(request_id, ex)) diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index 0402397..c33d37f 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -36,7 +36,7 @@ class TierConfigAutomation(AutomationEngine): model_class = TierConfigRequest logger = logging.getLogger('UsageFile.logger') - @function_log + @function_log(custom_logger=logger) def dispatch(self, request): # type: (TierConfigRequest) -> str try: @@ -86,7 +86,7 @@ def dispatch(self, request): return '' - @function_log + @function_log(custom_logger=logger) def update_parameters(self, pk, params): """ Sends a list of Param objects to Connect for updating. From 105ce2138dedd0fbae601afbb6fb9be079fe76da Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 20 Sep 2019 11:19:48 +0200 Subject: [PATCH 04/17] Remove unused imports --- connect/logger/logger.py | 1 - 1 file changed, 1 deletion(-) diff --git a/connect/logger/logger.py b/connect/logger/logger.py index 3e850a9..c3ff57e 100644 --- a/connect/logger/logger.py +++ b/connect/logger/logger.py @@ -8,7 +8,6 @@ import logging import os from logging.config import dictConfig -from connect.models import BaseModel, Fulfillment with open(os.path.join(os.path.dirname(__file__), 'config.json')) as config_file: config = json.load(config_file) From 531bd1ecd809fe3dd64b17d2d4978cb0e66ea403 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 20 Sep 2019 13:46:22 +0200 Subject: [PATCH 05/17] Pass arguments in correct way and preserve global log --- connect/logger/__init__.py | 2 +- connect/logger/logger.py | 8 ++++---- connect/resources/base.py | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/connect/logger/__init__.py b/connect/logger/__init__.py index 365f498..fff901a 100644 --- a/connect/logger/__init__.py +++ b/connect/logger/__init__.py @@ -3,7 +3,7 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. -from .logger import function_log +from .logger import function_log, logger # TODO add auto settings for cloud platforms diff --git a/connect/logger/logger.py b/connect/logger/logger.py index c3ff57e..4fef919 100644 --- a/connect/logger/logger.py +++ b/connect/logger/logger.py @@ -25,14 +25,14 @@ def function_log(custom_logger=None): [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) for handler in custom_logger.handlers] - def real_function_log(func): + def decorator(func,**kwargs): @wraps(func) - def decorator(self, *args, **kwargs): + def wrapper(self, *args, **kwargs): custom_logger.info('Entering: %s', func.__name__) custom_logger.debug('Function params: {} {}'.format(args, kwargs)) result = func(self, *args, **kwargs) custom_logger.debug( 'Function `{}.{}` return: {}'.format(self.__class__.__name__, func.__name__, result)) return result - - return decorator + return wrapper + return decorator diff --git a/connect/resources/base.py b/connect/resources/base.py index 400dd39..448231c 100644 --- a/connect/resources/base.py +++ b/connect/resources/base.py @@ -58,21 +58,21 @@ def urljoin(*args): lambda a, b: compat.urljoin(a + ('' if a.endswith('/') else '/'), b) if b else a, args) - @function_log + @function_log() def get(self, path='', **kwargs): # type: (str, Any) -> Tuple[str, int] kwargs = self._fix_request_kwargs(path, kwargs) response = requests.get(**kwargs) return self._check_and_pack_response(response) - @function_log + @function_log() def post(self, path='', **kwargs): # type: (str, Any) -> Tuple[str, int] kwargs = self._fix_request_kwargs(path, kwargs) response = requests.post(**kwargs) return self._check_and_pack_response(response) - @function_log + @function_log() def put(self, path='', **kwargs): # type: (str, Any) -> Tuple[str, int] kwargs = self._fix_request_kwargs(path, kwargs) From 6314f87b046edb75246089d9a3dd1985a51da025 Mon Sep 17 00:00:00 2001 From: Adrian Date: Tue, 24 Sep 2019 10:37:18 +0200 Subject: [PATCH 06/17] Get handlers from global log --- connect/resources/fulfillment_automation.py | 7 +++++-- connect/resources/tier_config_automation.py | 8 ++++++-- connect/resources/usage_automation.py | 10 ++++++---- connect/resources/usage_file_automation.py | 7 +++++-- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/connect/resources/fulfillment_automation.py b/connect/resources/fulfillment_automation.py index dce3193..8b8237b 100644 --- a/connect/resources/fulfillment_automation.py +++ b/connect/resources/fulfillment_automation.py @@ -10,7 +10,7 @@ from typing import Optional from connect.exceptions import FailRequest, InquireRequest, SkipRequest -from connect.logger import logger, function_log +from connect.logger import logger as global_logger, function_log from connect.models import ActivationTemplateResponse, ActivationTileResponse, Param, \ Fulfillment, TierConfigRequest, Conversation from .automation_engine import AutomationEngine @@ -73,7 +73,10 @@ def filters(self, status='pending', **kwargs): @function_log(custom_logger=logger) def dispatch(self, request): # type: (Fulfillment) -> str - + handlers = global_logger.handlers + log_level = global_logger.level + self.__class__.logger.setLevel(log_level) + [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" sformat = request.asset.id + " " + request.id + base diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index c33d37f..55e42c2 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -7,7 +7,7 @@ from abc import ABCMeta from connect.exceptions import FailRequest, InquireRequest, SkipRequest -from connect.logger import logger, function_log +from connect.logger import logger as global_logger, function_log from connect.models import ActivationTemplateResponse, ActivationTileResponse, Param, \ TierConfigRequest from .automation_engine import AutomationEngine @@ -40,6 +40,10 @@ class TierConfigAutomation(AutomationEngine): def dispatch(self, request): # type: (TierConfigRequest) -> str try: + handlers = global_logger.handlers + log_level = global_logger.level + self.__class__.logger.setLevel(log_level) + [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" sformat = request.id + base @@ -81,7 +85,7 @@ def dispatch(self, request): except Exception as ex: self.logger.warning('Skipping request {} because an exception was raised: {}' - .format(request.id, ex)) + .format(request.id, ex)) return '' return '' diff --git a/connect/resources/usage_automation.py b/connect/resources/usage_automation.py index 5b3efc1..4175206 100644 --- a/connect/resources/usage_automation.py +++ b/connect/resources/usage_automation.py @@ -13,7 +13,7 @@ from typing import List, Optional from connect.exceptions import FileCreationError, FileRetrievalError -from connect.logger import logger +from connect.logger import logger as global_logger from connect.models import UsageListing, UsageFile, UsageRecord from .automation_engine import AutomationEngine @@ -43,15 +43,17 @@ def filters(self, status='listed', **kwargs): def dispatch(self, request): # type: (UsageListing) -> str - + handlers = global_logger.handlers + log_level = global_logger.level + self.__class__.logger.setLevel(log_level) + [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" sformat = request.contract.marketplace.id + " " + request.id + base [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) for handler in self.logger.handlers] - - # TODO Shouldn't this raise an exception on ALL automation classes? + # TODO Shouldn't this raise an exception on ALL automation classes? if self.config.products \ and request.product.id not in self.config.products: return 'Listing not handled by this processor' diff --git a/connect/resources/usage_file_automation.py b/connect/resources/usage_file_automation.py index 67ab990..a919713 100644 --- a/connect/resources/usage_file_automation.py +++ b/connect/resources/usage_file_automation.py @@ -7,7 +7,7 @@ from abc import ABCMeta from connect.exceptions import SkipRequest, UsageFileAction -from connect.logger import logger +from connect.logger import logger as global_logger from connect.models import BaseModel, UsageFile from .automation_engine import AutomationEngine @@ -37,7 +37,10 @@ def filters(self, status='ready', **kwargs): def dispatch(self, request): # type: (UsageFile) -> str - + handlers = global_logger.handlers + log_level = global_logger.level + self.__class__.logger.setLevel(log_level) + [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" sformat = request.marketplace.id + " " + request.id + base From 98f1ad008798371481de6e3a6cc8f9aa4cf16580 Mon Sep 17 00:00:00 2001 From: Adrian Date: Tue, 24 Sep 2019 11:27:27 +0200 Subject: [PATCH 07/17] Add stdout as handler for logging --- connect/resources/fulfillment_automation.py | 2 ++ connect/resources/tier_config_automation.py | 2 ++ connect/resources/usage_automation.py | 4 +++- connect/resources/usage_file_automation.py | 4 +++- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/connect/resources/fulfillment_automation.py b/connect/resources/fulfillment_automation.py index 8b8237b..c91a39e 100644 --- a/connect/resources/fulfillment_automation.py +++ b/connect/resources/fulfillment_automation.py @@ -3,6 +3,7 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. +import sys import logging from abc import ABCMeta @@ -74,6 +75,7 @@ def filters(self, status='pending', **kwargs): def dispatch(self, request): # type: (Fulfillment) -> str handlers = global_logger.handlers + handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level self.__class__.logger.setLevel(log_level) [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index 55e42c2..40fc6f6 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -3,6 +3,7 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. +import sys import logging from abc import ABCMeta @@ -41,6 +42,7 @@ def dispatch(self, request): # type: (TierConfigRequest) -> str try: handlers = global_logger.handlers + handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level self.__class__.logger.setLevel(log_level) [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] diff --git a/connect/resources/usage_automation.py b/connect/resources/usage_automation.py index 4175206..e3446a2 100644 --- a/connect/resources/usage_automation.py +++ b/connect/resources/usage_automation.py @@ -3,6 +3,7 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. +import sys import json import logging from abc import ABCMeta @@ -44,6 +45,7 @@ def filters(self, status='listed', **kwargs): def dispatch(self, request): # type: (UsageListing) -> str handlers = global_logger.handlers + handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level self.__class__.logger.setLevel(log_level) [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] @@ -75,7 +77,7 @@ def dispatch(self, request): return 'failure' self.logger.info('Processing result for usage on listing {}: {}' - .format(request.product.id, result)) + .format(request.product.id, result)) return 'success' def get_usage_template(self, product): diff --git a/connect/resources/usage_file_automation.py b/connect/resources/usage_file_automation.py index a919713..d496177 100644 --- a/connect/resources/usage_file_automation.py +++ b/connect/resources/usage_file_automation.py @@ -3,6 +3,7 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. +import sys import logging from abc import ABCMeta @@ -38,6 +39,7 @@ def filters(self, status='ready', **kwargs): def dispatch(self, request): # type: (UsageFile) -> str handlers = global_logger.handlers + handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level self.__class__.logger.setLevel(log_level) [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] @@ -79,5 +81,5 @@ def dispatch(self, request): processing_result = 'skip' self.logger.info('Finished processing of usage file with ID {} with result {}' - .format(request.id, processing_result)) + .format(request.id, processing_result)) return processing_result From dcf6f6fc71079995a09bbcb638186c2f208451fe Mon Sep 17 00:00:00 2001 From: Adrian Date: Tue, 24 Sep 2019 14:59:32 +0200 Subject: [PATCH 08/17] Copy handler objects --- connect/resources/fulfillment_automation.py | 3 ++- connect/resources/tier_config_automation.py | 5 +++-- connect/resources/usage_automation.py | 3 ++- connect/resources/usage_file_automation.py | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/connect/resources/fulfillment_automation.py b/connect/resources/fulfillment_automation.py index c91a39e..75e1dd2 100644 --- a/connect/resources/fulfillment_automation.py +++ b/connect/resources/fulfillment_automation.py @@ -5,6 +5,7 @@ import sys import logging +import copy from abc import ABCMeta from deprecation import deprecated @@ -74,7 +75,7 @@ def filters(self, status='pending', **kwargs): @function_log(custom_logger=logger) def dispatch(self, request): # type: (Fulfillment) -> str - handlers = global_logger.handlers + handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level self.__class__.logger.setLevel(log_level) diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index 40fc6f6..9211bbd 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -5,6 +5,7 @@ import sys import logging +import copy from abc import ABCMeta from connect.exceptions import FailRequest, InquireRequest, SkipRequest @@ -35,13 +36,13 @@ class TierConfigAutomation(AutomationEngine): __metaclass__ = ABCMeta resource = 'tier/config-requests' model_class = TierConfigRequest - logger = logging.getLogger('UsageFile.logger') + logger = logging.getLogger('Tier.logger') @function_log(custom_logger=logger) def dispatch(self, request): # type: (TierConfigRequest) -> str try: - handlers = global_logger.handlers + handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level self.__class__.logger.setLevel(log_level) diff --git a/connect/resources/usage_automation.py b/connect/resources/usage_automation.py index e3446a2..145b066 100644 --- a/connect/resources/usage_automation.py +++ b/connect/resources/usage_automation.py @@ -5,6 +5,7 @@ import sys import json +import copy import logging from abc import ABCMeta from tempfile import NamedTemporaryFile @@ -44,7 +45,7 @@ def filters(self, status='listed', **kwargs): def dispatch(self, request): # type: (UsageListing) -> str - handlers = global_logger.handlers + handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level self.__class__.logger.setLevel(log_level) diff --git a/connect/resources/usage_file_automation.py b/connect/resources/usage_file_automation.py index d496177..d2ca674 100644 --- a/connect/resources/usage_file_automation.py +++ b/connect/resources/usage_file_automation.py @@ -5,6 +5,7 @@ import sys import logging +import copy from abc import ABCMeta from connect.exceptions import SkipRequest, UsageFileAction @@ -38,7 +39,7 @@ def filters(self, status='ready', **kwargs): def dispatch(self, request): # type: (UsageFile) -> str - handlers = global_logger.handlers + handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level self.__class__.logger.setLevel(log_level) From ae2314538af2de3d9df88b4f7855a439b57da0ca Mon Sep 17 00:00:00 2001 From: Adrian Date: Tue, 24 Sep 2019 16:58:53 +0200 Subject: [PATCH 09/17] Add Parent root logger and avoid to propagate info to this root logger --- connect/logger/logger.py | 2 +- connect/resources/fulfillment_automation.py | 5 ++--- connect/resources/tier_config_automation.py | 5 ++--- connect/resources/usage_automation.py | 5 ++--- connect/resources/usage_file_automation.py | 5 ++--- 5 files changed, 9 insertions(+), 13 deletions(-) diff --git a/connect/logger/logger.py b/connect/logger/logger.py index 4fef919..dc537f8 100644 --- a/connect/logger/logger.py +++ b/connect/logger/logger.py @@ -14,7 +14,7 @@ dictConfig(config['logging']) -logger = logging.getLogger("Generic.logger") +logger = logging.getLogger() def function_log(custom_logger=None): diff --git a/connect/resources/fulfillment_automation.py b/connect/resources/fulfillment_automation.py index 75e1dd2..25dd03f 100644 --- a/connect/resources/fulfillment_automation.py +++ b/connect/resources/fulfillment_automation.py @@ -3,7 +3,6 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. -import sys import logging import copy from abc import ABCMeta @@ -76,15 +75,15 @@ def filters(self, status='pending', **kwargs): def dispatch(self, request): # type: (Fulfillment) -> str handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] - handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level + self.__class__.logger.propagate = False self.__class__.logger.setLevel(log_level) [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" sformat = request.asset.id + " " + request.id + base [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) - for handler in self.logger.handlers] + for handler in self.__class__.logger.handlers] conversation = request.get_conversation(self.config) diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index 9211bbd..f1bfe48 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -3,7 +3,6 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. -import sys import logging import copy from abc import ABCMeta @@ -43,15 +42,15 @@ def dispatch(self, request): # type: (TierConfigRequest) -> str try: handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] - handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level + self.__class__.logger.propagate = False self.__class__.logger.setLevel(log_level) [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" sformat = request.id + base [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) - for handler in self.logger.handlers] + for handler in self.__class__.logger.handlers] if self.config.products \ and request.configuration.product.id not in self.config.products: diff --git a/connect/resources/usage_automation.py b/connect/resources/usage_automation.py index 145b066..64f32c4 100644 --- a/connect/resources/usage_automation.py +++ b/connect/resources/usage_automation.py @@ -3,7 +3,6 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. -import sys import json import copy import logging @@ -46,15 +45,15 @@ def filters(self, status='listed', **kwargs): def dispatch(self, request): # type: (UsageListing) -> str handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] - handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level + self.__class__.logger.propagate = False self.__class__.logger.setLevel(log_level) [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" sformat = request.contract.marketplace.id + " " + request.id + base [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) - for handler in self.logger.handlers] + for handler in self.__class__.logger.handlers] # TODO Shouldn't this raise an exception on ALL automation classes? if self.config.products \ diff --git a/connect/resources/usage_file_automation.py b/connect/resources/usage_file_automation.py index d2ca674..582e8d1 100644 --- a/connect/resources/usage_file_automation.py +++ b/connect/resources/usage_file_automation.py @@ -3,7 +3,6 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. -import sys import logging import copy from abc import ABCMeta @@ -40,15 +39,15 @@ def filters(self, status='ready', **kwargs): def dispatch(self, request): # type: (UsageFile) -> str handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] - handlers.append(logging.StreamHandler(sys.stdout)) log_level = global_logger.level + self.__class__.logger.propagate = False self.__class__.logger.setLevel(log_level) [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" sformat = request.marketplace.id + " " + request.id + base [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) - for handler in self.logger.handlers] + for handler in self.__class__.logger.handlers] try: # Validate product From d6002a6d7b1573e2a548e6a5fa79019a4b74f50f Mon Sep 17 00:00:00 2001 From: Adrian Date: Thu, 26 Sep 2019 12:24:42 +0200 Subject: [PATCH 10/17] Code format --- connect/logger/logger.py | 4 +++- connect/models/base.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/connect/logger/logger.py b/connect/logger/logger.py index dc537f8..3c4719e 100644 --- a/connect/logger/logger.py +++ b/connect/logger/logger.py @@ -25,7 +25,7 @@ def function_log(custom_logger=None): [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) for handler in custom_logger.handlers] - def decorator(func,**kwargs): + def decorator(func, **kwargs): @wraps(func) def wrapper(self, *args, **kwargs): custom_logger.info('Entering: %s', func.__name__) @@ -34,5 +34,7 @@ def wrapper(self, *args, **kwargs): custom_logger.debug( 'Function `{}.{}` return: {}'.format(self.__class__.__name__, func.__name__, result)) return result + return wrapper + return decorator diff --git a/connect/models/base.py b/connect/models/base.py index 5ef6b07..89b1795 100644 --- a/connect/models/base.py +++ b/connect/models/base.py @@ -58,7 +58,7 @@ def deserialize_json(cls, json_data): raise TypeError( 'Invalid structure for initialization of `{type}`. \n' 'Error: {error}. \nJSON data: {data}' - .format( + .format( type=cls.__name__, error=error, data=json_data), From 6d1f61070173bf7ebcf340ec605d73ad235510af Mon Sep 17 00:00:00 2001 From: Adrian Date: Thu, 26 Sep 2019 16:09:24 +0200 Subject: [PATCH 11/17] Add correct id's to formatters --- connect/resources/tier_config_automation.py | 2 +- connect/resources/usage_automation.py | 2 +- connect/resources/usage_file_automation.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index f1bfe48..908b3e4 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -48,7 +48,7 @@ def dispatch(self, request): [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" - sformat = request.id + base + sformat = request.id + " " + request.configuration.id + " " + request.account.id + base [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) for handler in self.__class__.logger.handlers] diff --git a/connect/resources/usage_automation.py b/connect/resources/usage_automation.py index 64f32c4..9cf0fca 100644 --- a/connect/resources/usage_automation.py +++ b/connect/resources/usage_automation.py @@ -51,7 +51,7 @@ def dispatch(self, request): [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" - sformat = request.contract.marketplace.id + " " + request.id + base + sformat = request.id + " " + request.contract.marketplace.id + base [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) for handler in self.__class__.logger.handlers] diff --git a/connect/resources/usage_file_automation.py b/connect/resources/usage_file_automation.py index 582e8d1..036d111 100644 --- a/connect/resources/usage_file_automation.py +++ b/connect/resources/usage_file_automation.py @@ -45,7 +45,7 @@ def dispatch(self, request): [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ "-%(lineno)d: %(message)s" - sformat = request.marketplace.id + " " + request.id + base + sformat = request.id + " " + request.name + base [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) for handler in self.__class__.logger.handlers] From fed7f5d26cbd0cdd658385700e02460a713e0f71 Mon Sep 17 00:00:00 2001 From: Javier San Juan Cervera Date: Thu, 26 Sep 2019 16:42:32 +0200 Subject: [PATCH 12/17] Test & flake8 fixes. --- connect/logger/logger.py | 5 ++++- connect/models/base.py | 3 +-- connect/resources/base.py | 5 +++-- tests/test_tier_config.py | 8 -------- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/connect/logger/logger.py b/connect/logger/logger.py index 3c4719e..83ecabf 100644 --- a/connect/logger/logger.py +++ b/connect/logger/logger.py @@ -25,14 +25,17 @@ def function_log(custom_logger=None): [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) for handler in custom_logger.handlers] + # noinspection PyUnusedLocal def decorator(func, **kwargs): + # noinspection PyShadowingNames @wraps(func) def wrapper(self, *args, **kwargs): custom_logger.info('Entering: %s', func.__name__) custom_logger.debug('Function params: {} {}'.format(args, kwargs)) result = func(self, *args, **kwargs) custom_logger.debug( - 'Function `{}.{}` return: {}'.format(self.__class__.__name__, func.__name__, result)) + 'Function `{}.{}` return: {}'.format( + self.__class__.__name__, func.__name__, result)) return result return wrapper diff --git a/connect/models/base.py b/connect/models/base.py index 89b1795..696c1c2 100644 --- a/connect/models/base.py +++ b/connect/models/base.py @@ -57,8 +57,7 @@ def deserialize_json(cls, json_data): if error: raise TypeError( 'Invalid structure for initialization of `{type}`. \n' - 'Error: {error}. \nJSON data: {data}' - .format( + 'Error: {error}. \nJSON data: {data}'.format( type=cls.__name__, error=error, data=json_data), diff --git a/connect/resources/base.py b/connect/resources/base.py index 448231c..be6dc49 100644 --- a/connect/resources/base.py +++ b/connect/resources/base.py @@ -6,12 +6,13 @@ import functools from typing import Any, List, Dict, Tuple -import requests, logging +import logging +import requests from requests import compat from connect.config import Config from connect.exceptions import ServerError -from connect.logger import function_log, logger +from connect.logger import function_log from connect.models import BaseModel, ServerErrorResponse diff --git a/tests/test_tier_config.py b/tests/test_tier_config.py index f1cd124..7d55fb2 100644 --- a/tests/test_tier_config.py +++ b/tests/test_tier_config.py @@ -6,7 +6,6 @@ import os from datetime import datetime -import pytest from mock import MagicMock, patch from typing import Union @@ -164,13 +163,6 @@ def test_process_no_result(): automation.process() -@patch('requests.get', MagicMock(return_value=_get_response_ok())) -def test_process_not_implemented(): - with pytest.raises(NotImplementedError): - automation = TierConfigAutomation() - automation.process() - - @patch('requests.get', MagicMock(return_value=_get_response_ok_invalid_product())) def test_process_invalid_product(): automation = TierConfigAutomationHelper() From 7ccdb8bb63c4e98d9cb091fb6023a31e47523471 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Sep 2019 11:49:10 +0200 Subject: [PATCH 13/17] Add common customizator to logger --- connect/resources/automation_engine.py | 15 ++++++++++++++- connect/resources/fulfillment_automation.py | 11 +---------- connect/resources/tier_config_automation.py | 11 +---------- connect/resources/usage_automation.py | 12 ++---------- connect/resources/usage_file_automation.py | 12 ++---------- 5 files changed, 20 insertions(+), 41 deletions(-) diff --git a/connect/resources/automation_engine.py b/connect/resources/automation_engine.py index 5f8f2e4..c309e81 100644 --- a/connect/resources/automation_engine.py +++ b/connect/resources/automation_engine.py @@ -4,8 +4,9 @@ # Copyright (c) 2019 Ingram Micro. All Rights Reserved. from typing import Any, Dict +import copy import logging -from connect.logger import function_log +from connect.logger import function_log, logger as global_logger from connect.models import ActivationTileResponse, BaseModel from .base import BaseResource from .template import TemplateResource @@ -52,3 +53,15 @@ def fail(self, pk, reason): def render_template(self, pk, template_id): # type: (str, str) -> ActivationTileResponse return TemplateResource(self.config).render(template_id, pk) + + def _set_custom_logger(self, *args): + handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] + log_level = global_logger.level + self.__class__.logger.setLevel(log_level) + self.__class__.logger.propagate = False + [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] + base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ + "-%(lineno)d: %(message)s" + sformat = " ".join(args) + base + [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) + for handler in self.__class__.logger.handlers] diff --git a/connect/resources/fulfillment_automation.py b/connect/resources/fulfillment_automation.py index 25dd03f..6969090 100644 --- a/connect/resources/fulfillment_automation.py +++ b/connect/resources/fulfillment_automation.py @@ -74,16 +74,7 @@ def filters(self, status='pending', **kwargs): @function_log(custom_logger=logger) def dispatch(self, request): # type: (Fulfillment) -> str - handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] - log_level = global_logger.level - self.__class__.logger.propagate = False - self.__class__.logger.setLevel(log_level) - [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] - base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ - "-%(lineno)d: %(message)s" - sformat = request.asset.id + " " + request.id + base - [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) - for handler in self.__class__.logger.handlers] + self._set_custom_logger(request.asset.id, request.id) conversation = request.get_conversation(self.config) diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index 908b3e4..c590526 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -41,16 +41,7 @@ class TierConfigAutomation(AutomationEngine): def dispatch(self, request): # type: (TierConfigRequest) -> str try: - handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] - log_level = global_logger.level - self.__class__.logger.propagate = False - self.__class__.logger.setLevel(log_level) - [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] - base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ - "-%(lineno)d: %(message)s" - sformat = request.id + " " + request.configuration.id + " " + request.account.id + base - [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) - for handler in self.__class__.logger.handlers] + self._set_custom_logger(request.id, request.configuration.id, request.account.id) if self.config.products \ and request.configuration.product.id not in self.config.products: diff --git a/connect/resources/usage_automation.py b/connect/resources/usage_automation.py index 9cf0fca..4bf6aae 100644 --- a/connect/resources/usage_automation.py +++ b/connect/resources/usage_automation.py @@ -44,16 +44,8 @@ def filters(self, status='listed', **kwargs): def dispatch(self, request): # type: (UsageListing) -> str - handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] - log_level = global_logger.level - self.__class__.logger.propagate = False - self.__class__.logger.setLevel(log_level) - [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] - base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ - "-%(lineno)d: %(message)s" - sformat = request.id + " " + request.contract.marketplace.id + base - [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) - for handler in self.__class__.logger.handlers] + + self._set_custom_logger(request.id, request.contract.marketplace.id) # TODO Shouldn't this raise an exception on ALL automation classes? if self.config.products \ diff --git a/connect/resources/usage_file_automation.py b/connect/resources/usage_file_automation.py index 036d111..1909d9a 100644 --- a/connect/resources/usage_file_automation.py +++ b/connect/resources/usage_file_automation.py @@ -38,16 +38,8 @@ def filters(self, status='ready', **kwargs): def dispatch(self, request): # type: (UsageFile) -> str - handlers = [copy.copy(hdlr) for hdlr in global_logger.handlers] - log_level = global_logger.level - self.__class__.logger.propagate = False - self.__class__.logger.setLevel(log_level) - [self.__class__.logger.addHandler(hdlr) for hdlr in handlers] - base = " %(levelname)-6s; %(asctime)s; %(name)-6s; %(module)s:%(funcName)s:line" \ - "-%(lineno)d: %(message)s" - sformat = request.id + " " + request.name + base - [handler.setFormatter(logging.Formatter(sformat, "%I:%M:%S")) - for handler in self.__class__.logger.handlers] + + self._set_custom_logger(request.id, request.name) try: # Validate product From 11f657cfd43bcdaa71efb60fc59a9574a0a7ee33 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Sep 2019 12:27:02 +0200 Subject: [PATCH 14/17] Fix tier id to get TA --- connect/resources/tier_config_automation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index c590526..27c60b5 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -41,7 +41,7 @@ class TierConfigAutomation(AutomationEngine): def dispatch(self, request): # type: (TierConfigRequest) -> str try: - self._set_custom_logger(request.id, request.configuration.id, request.account.id) + self._set_custom_logger(request.id, request.configuration.id, request.configuration.account.id) if self.config.products \ and request.configuration.product.id not in self.config.products: From c82afc9d24e1d0f43428bad013577b9733ded9f4 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Sep 2019 12:31:36 +0200 Subject: [PATCH 15/17] Remove unused imports --- connect/resources/fulfillment_automation.py | 3 +-- connect/resources/tier_config_automation.py | 3 +-- connect/resources/usage_automation.py | 2 -- connect/resources/usage_file_automation.py | 1 - 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/connect/resources/fulfillment_automation.py b/connect/resources/fulfillment_automation.py index 6969090..ff3089b 100644 --- a/connect/resources/fulfillment_automation.py +++ b/connect/resources/fulfillment_automation.py @@ -4,14 +4,13 @@ # Copyright (c) 2019 Ingram Micro. All Rights Reserved. import logging -import copy from abc import ABCMeta from deprecation import deprecated from typing import Optional from connect.exceptions import FailRequest, InquireRequest, SkipRequest -from connect.logger import logger as global_logger, function_log +from connect.logger import function_log from connect.models import ActivationTemplateResponse, ActivationTileResponse, Param, \ Fulfillment, TierConfigRequest, Conversation from .automation_engine import AutomationEngine diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index 27c60b5..d7d9ac1 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -4,11 +4,10 @@ # Copyright (c) 2019 Ingram Micro. All Rights Reserved. import logging -import copy from abc import ABCMeta from connect.exceptions import FailRequest, InquireRequest, SkipRequest -from connect.logger import logger as global_logger, function_log +from connect.logger import function_log from connect.models import ActivationTemplateResponse, ActivationTileResponse, Param, \ TierConfigRequest from .automation_engine import AutomationEngine diff --git a/connect/resources/usage_automation.py b/connect/resources/usage_automation.py index 4bf6aae..42f5c4e 100644 --- a/connect/resources/usage_automation.py +++ b/connect/resources/usage_automation.py @@ -4,7 +4,6 @@ # Copyright (c) 2019 Ingram Micro. All Rights Reserved. import json -import copy import logging from abc import ABCMeta from tempfile import NamedTemporaryFile @@ -14,7 +13,6 @@ from typing import List, Optional from connect.exceptions import FileCreationError, FileRetrievalError -from connect.logger import logger as global_logger from connect.models import UsageListing, UsageFile, UsageRecord from .automation_engine import AutomationEngine diff --git a/connect/resources/usage_file_automation.py b/connect/resources/usage_file_automation.py index 1909d9a..729d430 100644 --- a/connect/resources/usage_file_automation.py +++ b/connect/resources/usage_file_automation.py @@ -8,7 +8,6 @@ from abc import ABCMeta from connect.exceptions import SkipRequest, UsageFileAction -from connect.logger import logger as global_logger from connect.models import BaseModel, UsageFile from .automation_engine import AutomationEngine From 240e2f87f5937b226dc40e30351f0e8eceefc6c1 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Sep 2019 12:36:38 +0200 Subject: [PATCH 16/17] Remove unused imports --- connect/resources/usage_file_automation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/connect/resources/usage_file_automation.py b/connect/resources/usage_file_automation.py index 729d430..13f1aea 100644 --- a/connect/resources/usage_file_automation.py +++ b/connect/resources/usage_file_automation.py @@ -4,7 +4,6 @@ # Copyright (c) 2019 Ingram Micro. All Rights Reserved. import logging -import copy from abc import ABCMeta from connect.exceptions import SkipRequest, UsageFileAction From d669d97a85f7ab688374cbe486e6506faf96b99a Mon Sep 17 00:00:00 2001 From: Javier San Juan Cervera Date: Wed, 2 Oct 2019 17:19:12 +0200 Subject: [PATCH 17/17] Flake8 fixes --- connect/resources/tier_config_automation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connect/resources/tier_config_automation.py b/connect/resources/tier_config_automation.py index 8a33194..38ba623 100644 --- a/connect/resources/tier_config_automation.py +++ b/connect/resources/tier_config_automation.py @@ -42,7 +42,8 @@ class TierConfigAutomation(AutomationEngine): def dispatch(self, request): # type: (TierConfigRequest) -> str try: - self._set_custom_logger(request.id, request.configuration.id, request.configuration.account.id) + self._set_custom_logger(request.id, request.configuration.id, + request.configuration.account.id) if self.config.products \ and request.configuration.product.id not in self.config.products: