Skip to content

Commit

Permalink
Merge pull request #90 from jeronimoalbi/develop
Browse files Browse the repository at this point in the history
Version update to 1.3.0
  • Loading branch information
jeronimoalbi authored Dec 1, 2017
2 parents f1a33ef + e92f43d commit 92cb248
Show file tree
Hide file tree
Showing 26 changed files with 309 additions and 64 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## [1.3.0] - 2017-11-01
### Added
- Support for action tags defined in the configuration.
- Request ID to logs.
- Component and framework info was added to log prefix.

### Fixed
- Error payload handling during runtime calls

### Changed
- Runtime call default timeout to 10000.
- Parameter schema default value getter now returns None by default.

### Fixed
- Component.log() now includes the date and [SDK] prefix.

## [1.2.1] - 2017-10-01
## Changed
- Running a service with an action input payload now flushes the output
Expand Down
2 changes: 1 addition & 1 deletion katana/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@

__license__ = "MIT"
__copyright__ = "Copyright (c) 2016-2017 KUSANAGI S.L. (http://kusanagi.io)"
__version__ = '1.2.1'
__version__ = '1.3.0'
15 changes: 10 additions & 5 deletions katana/api/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import zmq

from ..logging import RequestLogger
from ..payload import CommandPayload
from ..payload import ErrorPayload
from ..payload import get_path
Expand Down Expand Up @@ -198,7 +199,7 @@ def runtime_call(address, transport, action, callee, **kwargs):

command = CommandPayload.new('runtime-call', 'service', args=args)

timeout = kwargs.get('timeout') or 1000
timeout = kwargs.get('timeout') or 10000
channel = ipc(address)
socket = CONTEXT.socket(zmq.REQ)
try:
Expand Down Expand Up @@ -229,6 +230,8 @@ def runtime_call(address, transport, action, callee, **kwargs):

if payload.path_exists('error'):
raise ApiError(payload.get('error/message'))
elif payload.path_exists('command_reply/result/error'):
raise ApiError(payload.get('command_reply/result/error/message'))

result = payload.get('command_reply/result')
return (get_path(result, 'transport'), get_path(result, 'return'))
Expand All @@ -247,6 +250,11 @@ def __init__(self, action, params, transport, *args, **kwargs):
for param in params
}

# Logging is only enabled when debug is True
if self.is_debug():
rid = transport.get('meta/id')
self._logger = RequestLogger(rid, 'katana.api')

service = self.get_name()
version = self.get_version()
action_name = self.get_action_name()
Expand Down Expand Up @@ -1019,12 +1027,9 @@ def remote_call(self, address, service, version, action, **kwargs):
'version': version,
'action': action,
'caller': self.get_action_name(),
'timeout': kwargs.get('timeout') or 1000,
})

timeout = kwargs.get('timeout')
if timeout:
payload.set('timeout', timeout)

params = kwargs.get('params')
if params:
payload.set('params', parse_params(params))
Expand Down
12 changes: 4 additions & 8 deletions katana/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,8 @@ def __init__(self, component, path, name, version, framework_version, **kw):
self.__debug = kw.get('debug', False)
self._schema = get_schema_registry()
self._component = component

# Logging is only enabled when debug is True
if self.__debug:
self.__logger = logging.getLogger('katana.api')
else:
self.__logger = None
# Logger must be initialized by child classes
self._logger = None

def is_debug(self):
"""Determine if component is running in debug mode.
Expand Down Expand Up @@ -213,8 +209,8 @@ def log(self, value):
"""

if self.__logger:
self.__logger.debug(value_to_log_string(value))
if self._logger:
self._logger.debug(value_to_log_string(value))

def done(self):
"""This method does nothing and returns False.
Expand Down
4 changes: 0 additions & 4 deletions katana/api/param.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,12 @@
file that was distributed with this source code.
"""
import logging

from ..payload import get_path
from ..payload import Payload

__license__ = "MIT"
__copyright__ = "Copyright (c) 2016-2017 KUSANAGI S.L. (http://kusanagi.io)"

LOG = logging.getLogger(__name__)

EMPTY = object()

# Supported parameter types
Expand Down
12 changes: 9 additions & 3 deletions katana/api/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@
file that was distributed with this source code.
"""
from .. import urn
from ..logging import RequestLogger
from ..payload import get_path
from ..payload import Payload

from .base import Api
from .http.request import HttpRequest
from .param import Param
from .param import param_to_payload
from .param import payload_to_param
from .response import Response
from .transport import Transport
from .. import urn
from ..payload import get_path
from ..payload import Payload

__license__ = "MIT"
__copyright__ = "Copyright (c) 2016-2017 KUSANAGI S.L. (http://kusanagi.io)"
Expand All @@ -37,6 +39,10 @@ def __init__(self, *args, **kwargs):
self.__gateway_protocol = kwargs.get('gateway_protocol')
self.__gateway_addresses = kwargs.get('gateway_addresses')

# Logging is only enabled when debug is True
if self.is_debug():
self._logger = RequestLogger(self.__request_id, 'katana.api')

http_request = kwargs.get('http_request')
if http_request:
self.__http_request = HttpRequest(**http_request)
Expand Down
10 changes: 8 additions & 2 deletions katana/api/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
file that was distributed with this source code.
"""
from ..errors import KatanaError
from ..logging import RequestLogger

from .base import Api
from .base import ApiError
from .http.request import HttpRequest
from .http.response import HttpResponse
from ..errors import KatanaError

__license__ = "MIT"
__copyright__ = "Copyright (c) 2016-2017 KUSANAGI S.L. (http://kusanagi.io)"
Expand All @@ -38,6 +39,11 @@ def __init__(self, transport, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__attributes = kwargs['attributes']

# Logging is only enabled when debug is True
if self.is_debug():
rid = transport.get_request_id()
self._logger = RequestLogger(rid, 'katana.api')

self.__gateway_protocol = kwargs.get('gateway_protocol')
self.__gateway_addresses = kwargs.get('gateway_addresses')

Expand Down
24 changes: 24 additions & 0 deletions katana/api/schema/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ def __init__(self, name, payload):
self.__payload = Payload(payload)
self.__params = self.__payload.get('params', {})
self.__files = self.__payload.get('files', {})
self.__tags = self.__payload.get('tags', [])

def is_deprecated(self):
"""Check if action has been deprecated.
Expand Down Expand Up @@ -473,6 +474,29 @@ def get_file_schema(self, name):

return FileSchema(name, self.__files[name])

def has_tag(self, name):
"""Check that a tag is defined for the action.
The tag name is case sensitive.
:param name: Tag name.
:type name: str
:rtype: bool
"""

return name in self.__tags

def get_tags(self):
"""Get the tags defined for the action.
:rtype: list
"""

return list(self.__tags)

def get_http_schema(self):
"""Get HTTP action schema.
Expand Down
3 changes: 0 additions & 3 deletions katana/api/schema/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@
file that was distributed with this source code.
"""
import logging
import sys

from ...payload import Payload

__license__ = "MIT"
__copyright__ = "Copyright (c) 2016-2017 KUSANAGI S.L. (http://kusanagi.io)"

LOG = logging.getLogger(__name__)


class FileSchema(object):
"""File parameter schema in the framework."""
Expand Down
7 changes: 2 additions & 5 deletions katana/api/schema/param.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@
file that was distributed with this source code.
"""
import logging
import sys

from ...payload import Payload

__license__ = "MIT"
__copyright__ = "Copyright (c) 2016-2017 KUSANAGI S.L. (http://kusanagi.io)"

LOG = logging.getLogger(__name__)


class ParamSchema(object):
"""Parameter schema in the framework."""
Expand Down Expand Up @@ -101,11 +98,11 @@ def has_default_value(self):
def get_default_value(self):
"""Get default value for parameter.
:rtype: str
:rtype: object
"""

return self.__payload.get('default_value', '')
return self.__payload.get('default_value', None)

def is_required(self):
"""Check if parameter is required.
Expand Down
61 changes: 58 additions & 3 deletions katana/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,55 @@
__copyright__ = "Copyright (c) 2016-2017 KUSANAGI S.L. (http://kusanagi.io)"


class RequestLogger(object):
"""
Logger for requests.
It appends the request ID to all logging messages.
"""

def __init__(self, rid, name):
self.rid = rid
self.log = logging.getLogger(name)

def debug(self, msg, *args, **kw):
if self.rid:
self.log.debug(msg + ' |{}|'.format(self.rid), *args, **kw)
else:
self.log.debug(msg, *args, **kw)

def info(self, msg, *args, **kw):
if self.rid:
self.log.info(msg + ' |{}|'.format(self.rid), *args, **kw)
else:
self.log.info(msg, *args, **kw)

def warning(self, msg, *args, **kw):
if self.rid:
self.log.warning(msg + ' |{}|'.format(self.rid), *args, **kw)
else:
self.log.warning(msg, *args, **kw)

def error(self, msg, *args, **kw):
if self.rid:
self.log.error(msg + ' |{}|'.format(self.rid), *args, **kw)
else:
self.log.error(msg, *args, **kw)

def critical(self, msg, *args, **kw):
if self.rid:
self.log.critical(msg + ' |{}|'.format(self.rid), *args, **kw)
else:
self.log.critical(msg, *args, **kw)

def exception(self, msg, *args, **kw):
if self.rid:
self.log.exception(msg + ' |{}|'.format(self.rid), *args, **kw)
else:
self.log.exception(msg, *args, **kw)


class KatanaFormatter(logging.Formatter):
"""Default KATANA logging formatter."""

Expand Down Expand Up @@ -75,14 +124,20 @@ def get_output_buffer():
return sys.stdout


def setup_katana_logging(level=logging.INFO):
def setup_katana_logging(type, name, version, framework, level=logging.INFO):
"""Initialize logging defaults for KATANA.
:param type: Component type.
:param name: Component name.
:param version: Component version.
:param framework: KATANA framework version.
:param level: Logging level. Default: INFO.
"""

format = "%(asctime)sZ [%(levelname)s] [SDK] %(message)s"
format = "%(asctime)sZ {} [%(levelname)s] [SDK] %(message)s".format(
"{} {}/{} ({})".format(type, name, version, framework)
)

output = get_output_buffer()

Expand All @@ -107,7 +162,7 @@ def setup_katana_logging(level=logging.INFO):
logger.setLevel(logging.DEBUG)
if not logger.handlers:
handler = logging.StreamHandler(stream=output)
handler.setFormatter(logging.Formatter()) # No format is applied
handler.setFormatter(KatanaFormatter(format))
logger.addHandler(handler)
logger.propagate = False

Expand Down
4 changes: 4 additions & 0 deletions katana/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__component = get_component()

@staticmethod
def get_type():
return 'middleware'

@staticmethod
def http_request_from_payload(payload):
if not payload.path_exists('request'):
Expand Down
Loading

0 comments on commit 92cb248

Please sign in to comment.