Skip to content

Commit

Permalink
Merge pull request #16 from BenjamenMeyer/enhancement_session_data
Browse files Browse the repository at this point in the history
Enhancement session data
  • Loading branch information
BenjamenMeyer authored Jul 14, 2016
2 parents 8efd1c9 + 17a20d2 commit c175dda
Show file tree
Hide file tree
Showing 5 changed files with 429 additions and 20 deletions.
112 changes: 108 additions & 4 deletions stackinawsgi/admin/admin.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
"""
Stack-In-A-WSGI: StackInAWsgiAdmin
"""
import json
import logging
import re

from stackinabox.services.service import StackInABoxService

from stackinawsgi.exceptions import InvalidSessionId
from stackinawsgi.session.service import (
global_sessions,
session_regex
)


logger = logging.getLogger(__name__)
Expand All @@ -29,6 +35,12 @@ def __init__(self, session_manager, base_uri):
self.manager = session_manager
self.base_uri = base_uri

self.register(
StackInABoxService.GET,
re.compile('^{0}$'.format(session_regex)),
StackInAWsgiAdmin.get_session_info
)

self.register(
StackInABoxService.DELETE, '/', StackInAWsgiAdmin.remove_session
)
Expand All @@ -39,7 +51,7 @@ def __init__(self, session_manager, base_uri):
StackInABoxService.PUT, '/', StackInAWsgiAdmin.reset_session
)
self.register(
StackInABoxService.GET, '/', StackInAWsgiAdmin.get_session_info
StackInABoxService.GET, '/', StackInAWsgiAdmin.get_sessions
)

@property
Expand Down Expand Up @@ -84,6 +96,30 @@ def helper_get_session_id(self, headers):
logger.debug('Found Session Id: {0}'.format(session_id))
return session_id

def helper_get_session_id_from_uri(self, uri):
"""
Helper to retrieve the Session-ID FROM a URI
:param text_type uri: complete URI
:returns: text_type with the session-id
"""
matcher = re.compile(session_regex)
try:
matched_groups = matcher.match(uri)
session_id = matched_groups.group(0)[1:]
logger.debug(
'Helper Get Session From URI - URI: "{0}", '
'Session ID: "{1}"'.format(
uri,
session_id
)
)

except Exception:
logger.exception('Failed to find session-id')
session_id = None
return session_id

def helper_get_uri(self, session_id):
"""
Helper to build the session URL
Expand Down Expand Up @@ -214,10 +250,78 @@ def get_session_info(self, request, uri, headers):
:returns: tuple for StackInABox HTTP Response
HTTP Request:
GET /admin/
GET /admin/{X-Session-ID}
X-Session-ID: (Required) Session-ID to reset
HTTP Responses:
500 - Not Implemented
200 - Session Data in JSON format
"""
requested_session_id = self.helper_get_session_id_from_uri(
uri
)

session_info = {
'session_valid': requested_session_id in global_sessions,
'created-time': None,
'accessed-time': None,
'accessed-count': 0,
'http-status': {}
}

if session_info['session_valid']:
session = global_sessions[requested_session_id]
session_info['created-time'] = session.created_at.isoformat()
session_info['accessed-time'] = (
session.last_accessed_at.isoformat()
)
session_info['accessed-count'] = session.access_count
session_info['http-status'] = session.status_tracker

data = {
'base_url': self.base_uri,
'services': {
svc().name: svc.__name__
for svc in self.manager.services
},
'trackers': {
'created-time': session_info['created-time'],
'accessed': {
'time': session_info['accessed-time'],
'count': session_info['accessed-count']
},
'status': session_info['http-status']
},
'session_valid': session_info['session_valid']
}

return (200, headers, json.dumps(data))

def get_sessions(self, request, uri, headers):
"""
Get Session List - TBD
:param :obj:`Request` request: object containing the HTTP Request
:param text_type uri: the URI for the request per StackInABox
:param dict headers: case insensitive header dictionary
:returns: tuple for StackInABox HTTP Response
HTTP Request:
GET /admin/
HTTP Responses:
200 - Session List in JSON format
"""
return (500, headers, 'Not Implemented')
data = {
'base_url': self.base_uri,
'services': {
svc().name: svc.__name__
for svc in self.manager.services
},
'sessions': [
requested_session_id
for requested_session_id in global_sessions
]
}

return (200, headers, json.dumps(data))
8 changes: 7 additions & 1 deletion stackinawsgi/session/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
# must be able to be pickled, which we can't guarantee. So
# we're stuck with threading.
global_sessions = dict()
session_regex = '^\/([\w-]+)'
session_regex_instance = '{0}\/.*'.format(session_regex)


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -66,7 +68,7 @@ def extract_session_id(uri):
uri
)
)
matcher = re.compile('^\/([\w-]+)\/.*')
matcher = re.compile(session_regex_instance)

matches = matcher.match(uri)
if matches:
Expand Down Expand Up @@ -128,6 +130,8 @@ def create_session(self, session_id=None):
:returns: text_type with the session id
"""
global global_sessions

logger.debug(
'Requesting creation of session. Optional Session Id: {0}'.format(
session_id
Expand Down Expand Up @@ -199,6 +203,8 @@ def remove_session(self, session_id):
:raises: InvalidSessionId if session id is not found
"""
global global_sessions

if session_id in global_sessions:
del global_sessions[session_id]
else:
Expand Down
69 changes: 65 additions & 4 deletions stackinawsgi/session/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
from __future__ import absolute_import

import datetime
import logging
from threading import Lock

Expand Down Expand Up @@ -58,6 +59,52 @@ def __init__(self, session_id, services):
self.stack = StackInABox()
self.stack.base_url = self.session_id
self.init_services()
self.created_at = datetime.datetime.utcnow()
self._last_accessed_time = self.created_at
self._access_count = 0
self._http_status_dict = {}

def _update_trackers(self):
"""
Update the session trackers
"""
self._access_count = self._access_count + 1
self._last_accessed_time = datetime.datetime.utcnow()

def _track_result(self, result):
"""
Track the results from StackInABox
"""
status, _, _ = result
if status not in self._http_status_dict:
self._http_status_dict[status] = 0

self._http_status_dict[status] = (
self._http_status_dict[status] + 1
)

return result

@property
def last_accessed_at(self):
"""
Return the time the session was last accessed
"""
return self._last_accessed_time

@property
def access_count(self):
"""
Return the number of times the session has been called
"""
return self._access_count

@property
def status_tracker(self):
"""
Return the current copy of HTTP Status Code Trackers
"""
return self._http_status_dict

def init_services(self):
"""
Expand All @@ -72,6 +119,7 @@ def init_services(self):
)
)
self.stack.register(svc)
self._http_status_dict = {}

@property
def base_url(self):
Expand Down Expand Up @@ -104,6 +152,7 @@ def reset(self):
Reset the StackInABox instance to the initial state by
resetting the instance then re-registering all the services.
"""
self._update_trackers()
logger.debug(
'Session {0}: Waiting for lock'.format(
self.session_id
Expand All @@ -123,6 +172,7 @@ def call(self, *args, **kwargs):
"""
Wrapper to same in the StackInABox instance
"""
self._update_trackers()
logger.debug(
'Session {0}: Waiting for lock'.format(
self.session_id
Expand All @@ -135,12 +185,15 @@ def call(self, *args, **kwargs):
)
)

return self.stack.call(*args, **kwargs)
return self._track_result(
self.stack.call(*args, **kwargs)
)

def try_handle_route(self, *args, **kwargs):
"""
Wrapper to same in the StackInABox instance
"""
self._update_trackers()
logger.debug(
'Session {0}: Waiting for lock'.format(
self.session_id
Expand All @@ -153,12 +206,15 @@ def try_handle_route(self, *args, **kwargs):
)
)

return self.stack.try_handle_route(*args, **kwargs)
return self._track_result(
self.stack.try_handle_route(*args, **kwargs)
)

def request(self, *args, **kwargs):
"""
Wrapper to same in the StackInABox instance
"""
self._update_trackers()
logger.debug(
'Session {0}: Waiting for lock'.format(
self.session_id
Expand All @@ -171,12 +227,15 @@ def request(self, *args, **kwargs):
)
)

return self.stack.request(*args, **kwargs)
return self._track_result(
self.stack.request(*args, **kwargs)
)

def sub_request(self, *args, **kwargs):
"""
Pass-thru to the StackInABox instance's sub_request
"""
self._update_trackers()
logger.debug(
'Session {0}: Waiting for lock'.format(
self.session_id
Expand All @@ -189,4 +248,6 @@ def sub_request(self, *args, **kwargs):
)
)

return self.stack.sub_request(*args, **kwargs)
return self._track_result(
self.stack.sub_request(*args, **kwargs)
)
Loading

0 comments on commit c175dda

Please sign in to comment.