##// END OF EJS Templates
logging: added better cached/uncached functions logs
marcink -
r750:cbb81f7e default
parent child Browse files
Show More
@@ -1,150 +1,151 b''
1 # RhodeCode VCSServer provides access to different vcs backends via network.
1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 # Copyright (C) 2014-2019 RhodeCode GmbH
2 # Copyright (C) 2014-2019 RhodeCode GmbH
3 #
3 #
4 # This program is free software; you can redistribute it and/or modify
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
7 # (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
18 import os
18 import os
19 import logging
19 import logging
20 import functools
20 import functools
21
21
22 from dogpile.cache import CacheRegion
22 from dogpile.cache import CacheRegion
23 from dogpile.cache.util import compat
23 from dogpile.cache.util import compat
24
24
25 from vcsserver.utils import safe_str, sha1
25 from vcsserver.utils import safe_str, sha1
26
26
27
27
28 log = logging.getLogger(__name__)
28 log = logging.getLogger(__name__)
29
29
30
30
31 class RhodeCodeCacheRegion(CacheRegion):
31 class RhodeCodeCacheRegion(CacheRegion):
32
32
33 def conditional_cache_on_arguments(
33 def conditional_cache_on_arguments(
34 self, namespace=None,
34 self, namespace=None,
35 expiration_time=None,
35 expiration_time=None,
36 should_cache_fn=None,
36 should_cache_fn=None,
37 to_str=compat.string_type,
37 to_str=compat.string_type,
38 function_key_generator=None,
38 function_key_generator=None,
39 condition=True):
39 condition=True):
40 """
40 """
41 Custom conditional decorator, that will not touch any dogpile internals if
41 Custom conditional decorator, that will not touch any dogpile internals if
42 condition isn't meet. This works a bit different than should_cache_fn
42 condition isn't meet. This works a bit different than should_cache_fn
43 And it's faster in cases we don't ever want to compute cached values
43 And it's faster in cases we don't ever want to compute cached values
44 """
44 """
45 expiration_time_is_callable = compat.callable(expiration_time)
45 expiration_time_is_callable = compat.callable(expiration_time)
46
46
47 if function_key_generator is None:
47 if function_key_generator is None:
48 function_key_generator = self.function_key_generator
48 function_key_generator = self.function_key_generator
49
49
50 def decorator(fn):
50 def decorator(fn):
51 if to_str is compat.string_type:
51 if to_str is compat.string_type:
52 # backwards compatible
52 # backwards compatible
53 key_generator = function_key_generator(namespace, fn)
53 key_generator = function_key_generator(namespace, fn)
54 else:
54 else:
55 key_generator = function_key_generator(namespace, fn, to_str=to_str)
55 key_generator = function_key_generator(namespace, fn, to_str=to_str)
56
56
57 @functools.wraps(fn)
57 @functools.wraps(fn)
58 def decorate(*arg, **kw):
58 def decorate(*arg, **kw):
59 key = key_generator(*arg, **kw)
59 key = key_generator(*arg, **kw)
60
60
61 @functools.wraps(fn)
61 @functools.wraps(fn)
62 def creator():
62 def creator():
63 log.debug('Calling cached fn:%s', fn)
64 return fn(*arg, **kw)
63 return fn(*arg, **kw)
65
64
66 if not condition:
65 if not condition:
66 log.debug('Calling un-cached func:%s', fn)
67 return creator()
67 return creator()
68
68
69 timeout = expiration_time() if expiration_time_is_callable \
69 timeout = expiration_time() if expiration_time_is_callable \
70 else expiration_time
70 else expiration_time
71
71
72 log.debug('Calling cached fn:%s', fn)
72 return self.get_or_create(key, creator, timeout, should_cache_fn)
73 return self.get_or_create(key, creator, timeout, should_cache_fn)
73
74
74 def invalidate(*arg, **kw):
75 def invalidate(*arg, **kw):
75 key = key_generator(*arg, **kw)
76 key = key_generator(*arg, **kw)
76 self.delete(key)
77 self.delete(key)
77
78
78 def set_(value, *arg, **kw):
79 def set_(value, *arg, **kw):
79 key = key_generator(*arg, **kw)
80 key = key_generator(*arg, **kw)
80 self.set(key, value)
81 self.set(key, value)
81
82
82 def get(*arg, **kw):
83 def get(*arg, **kw):
83 key = key_generator(*arg, **kw)
84 key = key_generator(*arg, **kw)
84 return self.get(key)
85 return self.get(key)
85
86
86 def refresh(*arg, **kw):
87 def refresh(*arg, **kw):
87 key = key_generator(*arg, **kw)
88 key = key_generator(*arg, **kw)
88 value = fn(*arg, **kw)
89 value = fn(*arg, **kw)
89 self.set(key, value)
90 self.set(key, value)
90 return value
91 return value
91
92
92 decorate.set = set_
93 decorate.set = set_
93 decorate.invalidate = invalidate
94 decorate.invalidate = invalidate
94 decorate.refresh = refresh
95 decorate.refresh = refresh
95 decorate.get = get
96 decorate.get = get
96 decorate.original = fn
97 decorate.original = fn
97 decorate.key_generator = key_generator
98 decorate.key_generator = key_generator
98 decorate.__wrapped__ = fn
99 decorate.__wrapped__ = fn
99
100
100 return decorate
101 return decorate
101
102
102 return decorator
103 return decorator
103
104
104
105
105 def make_region(*arg, **kw):
106 def make_region(*arg, **kw):
106 return RhodeCodeCacheRegion(*arg, **kw)
107 return RhodeCodeCacheRegion(*arg, **kw)
107
108
108
109
109 def get_default_cache_settings(settings, prefixes=None):
110 def get_default_cache_settings(settings, prefixes=None):
110 prefixes = prefixes or []
111 prefixes = prefixes or []
111 cache_settings = {}
112 cache_settings = {}
112 for key in settings.keys():
113 for key in settings.keys():
113 for prefix in prefixes:
114 for prefix in prefixes:
114 if key.startswith(prefix):
115 if key.startswith(prefix):
115 name = key.split(prefix)[1].strip()
116 name = key.split(prefix)[1].strip()
116 val = settings[key]
117 val = settings[key]
117 if isinstance(val, compat.string_types):
118 if isinstance(val, compat.string_types):
118 val = val.strip()
119 val = val.strip()
119 cache_settings[name] = val
120 cache_settings[name] = val
120 return cache_settings
121 return cache_settings
121
122
122
123
123 def compute_key_from_params(*args):
124 def compute_key_from_params(*args):
124 """
125 """
125 Helper to compute key from given params to be used in cache manager
126 Helper to compute key from given params to be used in cache manager
126 """
127 """
127 return sha1("_".join(map(safe_str, args)))
128 return sha1("_".join(map(safe_str, args)))
128
129
129
130
130 def backend_key_generator(backend):
131 def backend_key_generator(backend):
131 """
132 """
132 Special wrapper that also sends over the backend to the key generator
133 Special wrapper that also sends over the backend to the key generator
133 """
134 """
134 def wrapper(namespace, fn):
135 def wrapper(namespace, fn):
135 return key_generator(backend, namespace, fn)
136 return key_generator(backend, namespace, fn)
136 return wrapper
137 return wrapper
137
138
138
139
139 def key_generator(backend, namespace, fn):
140 def key_generator(backend, namespace, fn):
140 fname = fn.__name__
141 fname = fn.__name__
141
142
142 def generate_key(*args):
143 def generate_key(*args):
143 backend_prefix = getattr(backend, 'key_prefix', None) or 'backend_prefix'
144 backend_prefix = getattr(backend, 'key_prefix', None) or 'backend_prefix'
144 namespace_pref = namespace or 'default_namespace'
145 namespace_pref = namespace or 'default_namespace'
145 arg_key = compute_key_from_params(*args)
146 arg_key = compute_key_from_params(*args)
146 final_key = "{}:{}:{}_{}".format(backend_prefix, namespace_pref, fname, arg_key)
147 final_key = "{}:{}:{}_{}".format(backend_prefix, namespace_pref, fname, arg_key)
147
148
148 return final_key
149 return final_key
149
150
150 return generate_key
151 return generate_key
General Comments 0
You need to be logged in to leave comments. Login now