~gandelman-a/ubuntu/precise/keystone/UCA_2012.2.1

« back to all changes in this revision

Viewing changes to keystone/contrib/stats/core.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-07-06 10:37:01 UTC
  • mfrom: (1.1.20)
  • Revision ID: package-import@ubuntu.com-20120706103701-rswdykm7fqypbavg
Tags: 2012.2~f2-0ubuntu1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2012 OpenStack LLC
 
4
#
 
5
# Licensed under the Apache License, Version 2.0 (the "License"); you may
 
6
# not use this file except in compliance with the License. You may obtain
 
7
# a copy of the License at
 
8
#
 
9
#      http://www.apache.org/licenses/LICENSE-2.0
 
10
#
 
11
# Unless required by applicable law or agreed to in writing, software
 
12
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
13
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
14
# License for the specific language governing permissions and limitations
 
15
# under the License.
 
16
 
 
17
from keystone import config
 
18
from keystone import exception
 
19
from keystone import identity
 
20
from keystone import policy
 
21
from keystone import token
 
22
from keystone.common import logging
 
23
from keystone.common import manager
 
24
from keystone.common import wsgi
 
25
 
 
26
 
 
27
CONF = config.CONF
 
28
LOG = logging.getLogger(__name__)
 
29
 
 
30
 
 
31
class Manager(manager.Manager):
 
32
    """Default pivot point for the Stats backend.
 
33
 
 
34
    See :mod:`keystone.common.manager.Manager` for more details on how this
 
35
    dynamically calls the backend.
 
36
 
 
37
    """
 
38
 
 
39
    def __init__(self):
 
40
        super(Manager, self).__init__(CONF.stats.driver)
 
41
 
 
42
 
 
43
class Driver(object):
 
44
    """Interface description for a Stats driver."""
 
45
 
 
46
    def get_stats(self, api):
 
47
        """Retrieve all previously-captured statistics for an interface."""
 
48
        raise exception.NotImplemented()
 
49
 
 
50
    def set_stats(self, api, stats_ref):
 
51
        """Update statistics for an interface."""
 
52
        raise exception.NotImplemented()
 
53
 
 
54
    def increment_stat(self, api, category, value):
 
55
        """Increment the counter for an individual statistic."""
 
56
        raise exception.NotImplemented()
 
57
 
 
58
 
 
59
class StatsExtension(wsgi.ExtensionRouter):
 
60
    """Reports on previously-collected request/response statistics."""
 
61
 
 
62
    def add_routes(self, mapper):
 
63
        stats_controller = StatsController()
 
64
 
 
65
        mapper.connect(
 
66
            '/OS-STATS/stats',
 
67
            controller=stats_controller,
 
68
            action='get_stats',
 
69
            conditions=dict(method=['GET']))
 
70
        mapper.connect(
 
71
            '/OS-STATS/stats',
 
72
            controller=stats_controller,
 
73
            action='reset_stats',
 
74
            conditions=dict(method=['DELETE']))
 
75
 
 
76
 
 
77
class StatsController(wsgi.Application):
 
78
    def __init__(self):
 
79
        self.identity_api = identity.Manager()
 
80
        self.policy_api = policy.Manager()
 
81
        self.stats_api = Manager()
 
82
        self.token_api = token.Manager()
 
83
        super(StatsController, self).__init__()
 
84
 
 
85
    def get_stats(self, context):
 
86
        self.assert_admin(context)
 
87
        return {
 
88
            'OS-STATS:stats': [
 
89
                {
 
90
                    'type': 'identity',
 
91
                    'api': 'admin',
 
92
                    'extra': self.stats_api.get_stats(context, 'admin'),
 
93
                },
 
94
                {
 
95
                    'type': 'identity',
 
96
                    'api': 'public',
 
97
                    'extra': self.stats_api.get_stats(context, 'public'),
 
98
                },
 
99
            ]
 
100
        }
 
101
 
 
102
    def reset_stats(self, context):
 
103
        self.assert_admin(context)
 
104
        self.stats_api.set_stats(context, 'public', dict())
 
105
        self.stats_api.set_stats(context, 'admin', dict())
 
106
 
 
107
 
 
108
class StatsMiddleware(wsgi.Middleware):
 
109
    """Monitors various request/response attribute statistics."""
 
110
 
 
111
    request_attributes = ['application_url',
 
112
                          'method',
 
113
                          'path',
 
114
                          'path_qs',
 
115
                          'remote_addr']
 
116
 
 
117
    response_attributes = ['status_int']
 
118
 
 
119
    def __init__(self, *args, **kwargs):
 
120
        self.stats_api = Manager()
 
121
        return super(StatsMiddleware, self).__init__(*args, **kwargs)
 
122
 
 
123
    def _resolve_api(self, host):
 
124
        if str(CONF.admin_port) in host:
 
125
            return 'admin'
 
126
        elif str(CONF.public_port) in host:
 
127
            return 'public'
 
128
        else:
 
129
            # NOTE(dolph): I don't think this is actually reachable, but hey
 
130
            msg = 'Unable to resolve API as either public or admin: %s' % host
 
131
            LOG.warning(msg)
 
132
            return host
 
133
 
 
134
    def capture_stats(self, host, obj, attributes):
 
135
        """Collect each attribute from the given object."""
 
136
        for attribute in attributes:
 
137
            self.stats_api.increment_stat(None,
 
138
                                          self._resolve_api(host),
 
139
                                          attribute,
 
140
                                          getattr(obj, attribute))
 
141
 
 
142
    def process_request(self, request):
 
143
        """Monitor incoming request attributes."""
 
144
        self.capture_stats(request.host, request, self.request_attributes)
 
145
 
 
146
    def process_response(self, request, response):
 
147
        """Monitor outgoing response attributes."""
 
148
        self.capture_stats(request.host, response, self.response_attributes)
 
149
        return response