##// END OF EJS Templates
core: re-implemented the way how configuration can be made...
super-admin -
r1021:a797b226 default
parent child Browse files
Show More
@@ -0,0 +1,53 b''
1 ; #####################
2 ; LOGGING CONFIGURATION
3 ; #####################
4 ; Logging template, used for configure the logging
5 ; some variables here are replaced by RhodeCode to default values
6
7 [loggers]
8 keys = root, vcsserver
9
10 [handlers]
11 keys = console
12
13 [formatters]
14 keys = generic, json
15
16 ; #######
17 ; LOGGERS
18 ; #######
19 [logger_root]
20 level = NOTSET
21 handlers = console
22
23 [logger_vcsserver]
24 level = $RC_LOGGING_LEVEL
25 handlers =
26 qualname = vcsserver
27 propagate = 1
28
29 ; ########
30 ; HANDLERS
31 ; ########
32
33 [handler_console]
34 class = StreamHandler
35 args = (sys.stderr, )
36 level = $RC_LOGGING_LEVEL
37 ; To enable JSON formatted logs replace generic with json
38 ; This allows sending properly formatted logs to grafana loki or elasticsearch
39 #formatter = json
40 #formatter = generic
41 formatter = $RC_LOGGING_FORMATTER
42
43 ; ##########
44 ; FORMATTERS
45 ; ##########
46
47 [formatter_generic]
48 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
49 datefmt = %Y-%m-%d %H:%M:%S
50
51 [formatter_json]
52 format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
53 class = vcsserver.lib._vendor.jsonlogger.JsonFormatter
1 NO CONTENT: new file 100644
@@ -0,0 +1,177 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import os
22 import textwrap
23 import string
24 import functools
25 import logging
26 import tempfile
27 import logging.config
28 log = logging.getLogger(__name__)
29
30
31 def str2bool(_str):
32 """
33 returns True/False value from given string, it tries to translate the
34 string into boolean
35
36 :param _str: string value to translate into boolean
37 :rtype: boolean
38 :returns: boolean from given string
39 """
40 if _str is None:
41 return False
42 if _str in (True, False):
43 return _str
44 _str = str(_str).strip().lower()
45 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
46
47
48 def aslist(obj, sep=None, strip=True):
49 """
50 Returns given string separated by sep as list
51
52 :param obj:
53 :param sep:
54 :param strip:
55 """
56 if isinstance(obj, (basestring,)):
57 lst = obj.split(sep)
58 if strip:
59 lst = [v.strip() for v in lst]
60 return lst
61 elif isinstance(obj, (list, tuple)):
62 return obj
63 elif obj is None:
64 return []
65 else:
66 return [obj]
67
68
69 class SettingsMaker(object):
70
71 def __init__(self, app_settings):
72 self.settings = app_settings
73
74 @classmethod
75 def _bool_func(cls, input_val):
76 if isinstance(input_val, unicode):
77 input_val = input_val.encode('utf8')
78 return str2bool(input_val)
79
80 @classmethod
81 def _int_func(cls, input_val):
82 return int(input_val)
83
84 @classmethod
85 def _list_func(cls, input_val, sep=','):
86 return aslist(input_val, sep=sep)
87
88 @classmethod
89 def _string_func(cls, input_val, lower=True):
90 if lower:
91 input_val = input_val.lower()
92 return input_val
93
94 @classmethod
95 def _float_func(cls, input_val):
96 return float(input_val)
97
98 @classmethod
99 def _dir_func(cls, input_val, ensure_dir=False, mode=0o755):
100
101 # ensure we have our dir created
102 if not os.path.isdir(input_val) and ensure_dir:
103 os.makedirs(input_val, mode=mode)
104
105 if not os.path.isdir(input_val):
106 raise Exception('Dir at {} does not exist'.format(input_val))
107 return input_val
108
109 @classmethod
110 def _file_path_func(cls, input_val, ensure_dir=False, mode=0o755):
111 dirname = os.path.dirname(input_val)
112 cls._dir_func(dirname, ensure_dir=ensure_dir)
113 return input_val
114
115 @classmethod
116 def _key_transformator(cls, key):
117 return "{}_{}".format('RC'.upper(), key.upper().replace('.', '_').replace('-', '_'))
118
119 def enable_logging(self, logging_conf=None):
120 """
121 Helper to enable debug on running instance
122 :return:
123 """
124 if not str2bool(self.settings.get('logging.autoconfigure')):
125 log.info('logging configuration based on main .ini file')
126 return
127
128 if logging_conf is None:
129 logging_conf = self.settings.get('logging.logging_conf_file') or ''
130
131 if not os.path.isfile(logging_conf):
132 log.error('Unable to setup logging based on %s, file does not exist...', logging_conf)
133 return
134
135 with open(logging_conf, 'rb') as f:
136 ini_template = textwrap.dedent(f.read())
137 ini_template = string.Template(ini_template).safe_substitute(
138 RC_LOGGING_LEVEL=os.environ.get('RC_LOGGING_LEVEL', '') or 'INFO',
139 RC_LOGGING_FORMATTER=os.environ.get('RC_LOGGING_FORMATTER', '') or 'generic'
140 )
141
142 with tempfile.NamedTemporaryFile(prefix='rc_logging_', suffix='.ini', delete=False) as f:
143 log.info('Saved Temporary LOGGING config at %s', f.name)
144 f.write(ini_template)
145
146 logging.config.fileConfig(f.name)
147 os.remove(f.name)
148
149 def make_setting(self, key, default, lower=False, default_when_empty=False, parser=None):
150
151 input_val = self.settings.get(key, default)
152
153 if default_when_empty and not input_val:
154 # use default value when value is set in the config but it is empty
155 input_val = default
156
157 parser_func = {
158 'bool': self._bool_func,
159 'int': self._int_func,
160 'list': self._list_func,
161 'list:newline': functools.partial(self._list_func, sep='/n'),
162 'string': functools.partial(self._string_func, lower=lower),
163 'dir': self._dir_func,
164 'dir:ensured': functools.partial(self._dir_func, ensure_dir=True),
165 'file': self._file_path_func,
166 'file:ensured': functools.partial(self._file_path_func, ensure_dir=True),
167 None: lambda i: i
168 }[parser]
169
170 # now maybe we have this KEY in env, search and use the value with higher priority.
171 transformed_key = self._key_transformator(key)
172 envvar_value = os.environ.get(transformed_key)
173 if envvar_value:
174 log.debug('using `%s` key instead of `%s` key for config', transformed_key, key)
175 input_val = envvar_value
176 self.settings[key] = parser_func(input_val)
177 return self.settings[key]
@@ -31,7 +31,7 b' asyncore_use_poll = true'
31 31 ; GUNICORN APPLICATION SERVER
32 32 ; ###########################
33 33
34 ; run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
34 ; run with gunicorn --paste rhodecode.ini
35 35
36 36 ; Module to use, this setting shouldn't be changed
37 37 #use = egg:gunicorn#main
@@ -86,7 +86,7 b' asyncore_use_poll = true'
86 86 ; serving requests. Workers still alive after the timeout (starting from the
87 87 ; receipt of the restart signal) are force killed.
88 88 ; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
89 #graceful_timeout = 3600
89 #graceful_timeout = 21600
90 90
91 91 # The number of seconds to wait for requests on a Keep-Alive connection.
92 92 # Generally set in the 1-5 seconds range.
@@ -110,6 +110,17 b' asyncore_use_poll = true'
110 110 [app:main]
111 111 ; The %(here)s variable will be replaced with the absolute path of parent directory
112 112 ; of this file
113 ; Each option in the app:main can be override by an environmental variable
114 ;
115 ;To override an option:
116 ;
117 ;RC_<KeyName>
118 ;Everything should be uppercase, . and - should be replaced by _.
119 ;For example, if you have these configuration settings:
120 ;rc_cache.repo_object.backend = foo
121 ;can be overridden by
122 ;export RC_CACHE_REPO_OBJECT_BACKEND=foo
123
113 124 use = egg:rhodecode-vcsserver
114 125
115 126
@@ -133,13 +144,13 b' debugtoolbar.exclude_prefixes ='
133 144 ; #################
134 145
135 146 ; Pyramid default locales, we need this to be set
136 pyramid.default_locale_name = en
147 #pyramid.default_locale_name = en
137 148
138 149 ; default locale used by VCS systems
139 locale = en_US.UTF-8
150 #locale = en_US.UTF-8
140 151
141 152 ; path to binaries for vcsserver, it should be set by the installer
142 ; at installation time, e.g /home/user/vcsserver-1/profile/bin
153 ; at installation time, e.g /home/user/.rccontrol/vcsserver-1/profile/bin
143 154 ; it can also be a path to nix-build output in case of development
144 155 core.binary_dir = ""
145 156
@@ -153,21 +164,21 b' core.binary_dir = ""'
153 164
154 165 ; Default cache dir for caches. Putting this into a ramdisk can boost performance.
155 166 ; eg. /tmpfs/data_ramdisk, however this directory might require large amount of space
156 cache_dir = %(here)s/data
167 #cache_dir = %(here)s/data
157 168
158 169 ; ***************************************
159 170 ; `repo_object` cache, default file based
160 171 ; ***************************************
161 172
162 173 ; `repo_object` cache settings for vcs methods for repositories
163 rc_cache.repo_object.backend = dogpile.cache.rc.file_namespace
174 #rc_cache.repo_object.backend = dogpile.cache.rc.file_namespace
164 175
165 176 ; cache auto-expires after N seconds
166 177 ; Examples: 86400 (1Day), 604800 (7Days), 1209600 (14Days), 2592000 (30days), 7776000 (90Days)
167 rc_cache.repo_object.expiration_time = 2592000
178 #rc_cache.repo_object.expiration_time = 2592000
168 179
169 180 ; file cache store path. Defaults to `cache_dir =` value or tempdir if both values are not set
170 #rc_cache.repo_object.arguments.filename = /tmp/vcsserver_cache.db
181 #rc_cache.repo_object.arguments.filename = /tmp/vcsserver_cache_repo_object.db
171 182
172 183 ; ***********************************************************
173 184 ; `repo_object` cache with redis backend
@@ -202,55 +213,59 b' rc_cache.repo_object.expiration_time = 2'
202 213 #statsd.statsd_prefix =
203 214 #statsd.statsd_ipv6 = false
204 215
216 ; configure logging automatically at server startup set to false
217 ; to use the below custom logging config.
218 #logging.autoconfigure = true
219
220 ; specify your own custom logging config file to configure logging
221 #logging.logging_conf_file = /path/to/custom_logging.ini
222
205 223 ; #####################
206 224 ; LOGGING CONFIGURATION
207 225 ; #####################
208 [loggers]
209 keys = root, vcsserver
226 #[loggers]
227 #keys = root, vcsserver
210 228
211 [handlers]
212 keys = console
229 #[handlers]
230 #keys = console
213 231
214 [formatters]
215 keys = generic
232 #[formatters]
233 #keys = generic
216 234
217 235 ; #######
218 236 ; LOGGERS
219 237 ; #######
220 [logger_root]
221 level = NOTSET
222 handlers = console
238 #[logger_root]
239 #level = NOTSET
240 #handlers = console
223 241
224 [logger_vcsserver]
225 level = DEBUG
226 handlers =
227 qualname = vcsserver
228 propagate = 1
229
242 #[logger_vcsserver]
243 #level = INFO
244 #handlers =
245 #qualname = vcsserver
246 #propagate = 1
230 247
231 248 ; ########
232 249 ; HANDLERS
233 250 ; ########
234 251
235 [handler_console]
236 class = StreamHandler
237 args = (sys.stderr, )
238 level = DEBUG
239 formatter = generic
252 #[handler_console]
253 #class = StreamHandler
254 #args = (sys.stderr, )
255 #level = INFO
240 256 ; To enable JSON formatted logs replace generic with json
241 257 ; This allows sending properly formatted logs to grafana loki or elasticsearch
242 258 #formatter = json
243
259 #formatter = generic
244 260
245 261 ; ##########
246 262 ; FORMATTERS
247 263 ; ##########
248 264
249 [formatter_generic]
250 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
251 datefmt = %Y-%m-%d %H:%M:%S
265 #[formatter_generic]
266 #format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
267 #datefmt = %Y-%m-%d %H:%M:%S
252 268
253 [formatter_json]
254 format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
255 class = vcsserver.lib._vendor.jsonlogger.JsonFormatter
256
269 #[formatter_json]
270 #format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
271 #class = vcsserver.lib._vendor.jsonlogger.JsonFormatter
@@ -30,12 +30,12 b' worker_tmp_dir = None'
30 30 tmp_upload_dir = None
31 31
32 32 # Custom log format
33 access_log_format = (
34 '%(t)s %(p)s INFO [GNCRN] %(h)-15s rqt:%(L)s %(s)s %(b)-6s "%(m)s:%(U)s %(q)s" usr:%(u)s "%(f)s" "%(a)s"')
33 #access_log_format = (
34 # '%(t)s %(p)s INFO [GNCRN] %(h)-15s rqt:%(L)s %(s)s %(b)-6s "%(m)s:%(U)s %(q)s" usr:%(u)s "%(f)s" "%(a)s"')
35 35
36 36 # loki format for easier parsing in grafana
37 #access_log_format = (
38 # 'time="%(t)s" pid=%(p)s level="INFO" type="[GNCRN]" ip="%(h)-15s" rqt="%(L)s" response_code="%(s)s" response_bytes="%(b)-6s" uri="%(m)s:%(U)s %(q)s" user=":%(u)s" user_agent="%(a)s"')
37 access_log_format = (
38 'time="%(t)s" pid=%(p)s level="INFO" type="[GNCRN]" ip="%(h)-15s" rqt="%(L)s" response_code="%(s)s" response_bytes="%(b)-6s" uri="%(m)s:%(U)s %(q)s" user=":%(u)s" user_agent="%(a)s"')
39 39
40 40 # self adjust workers based on CPU count
41 41 # workers = get_workers()
@@ -97,9 +97,12 b' def post_fork(server, worker):'
97 97 if conf.has_option(section, 'memory_usage_recovery_threshold'):
98 98 _memory_usage_recovery_threshold = conf.getfloat(section, 'memory_usage_recovery_threshold')
99 99
100 worker._memory_max_usage = _memory_max_usage
101 worker._memory_usage_check_interval = _memory_usage_check_interval
102 worker._memory_usage_recovery_threshold = _memory_usage_recovery_threshold
100 worker._memory_max_usage = int(os.environ.get('RC_GUNICORN_MEMORY_MAX_USAGE', '')
101 or _memory_max_usage)
102 worker._memory_usage_check_interval = int(os.environ.get('RC_GUNICORN_MEMORY_USAGE_CHECK_INTERVAL', '')
103 or _memory_usage_check_interval)
104 worker._memory_usage_recovery_threshold = float(os.environ.get('RC_GUNICORN_MEMORY_USAGE_RECOVERY_THRESHOLD', '')
105 or _memory_usage_recovery_threshold)
103 106
104 107 # register memory last check time, with some random offset so we don't recycle all
105 108 # at once
@@ -14,7 +14,7 b' port = 9900'
14 14 ; GUNICORN APPLICATION SERVER
15 15 ; ###########################
16 16
17 ; run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
17 ; run with gunicorn --paste rhodecode.ini
18 18
19 19 ; Module to use, this setting shouldn't be changed
20 20 use = egg:gunicorn#main
@@ -69,7 +69,7 b' limit_request_field_size = 0'
69 69 ; serving requests. Workers still alive after the timeout (starting from the
70 70 ; receipt of the restart signal) are force killed.
71 71 ; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
72 graceful_timeout = 3600
72 graceful_timeout = 21600
73 73
74 74 # The number of seconds to wait for requests on a Keep-Alive connection.
75 75 # Generally set in the 1-5 seconds range.
@@ -93,16 +93,27 b' memory_usage_recovery_threshold = 0.8'
93 93 [app:main]
94 94 ; The %(here)s variable will be replaced with the absolute path of parent directory
95 95 ; of this file
96 ; Each option in the app:main can be override by an environmental variable
97 ;
98 ;To override an option:
99 ;
100 ;RC_<KeyName>
101 ;Everything should be uppercase, . and - should be replaced by _.
102 ;For example, if you have these configuration settings:
103 ;rc_cache.repo_object.backend = foo
104 ;can be overridden by
105 ;export RC_CACHE_REPO_OBJECT_BACKEND=foo
106
96 107 use = egg:rhodecode-vcsserver
97 108
98 109 ; Pyramid default locales, we need this to be set
99 pyramid.default_locale_name = en
110 #pyramid.default_locale_name = en
100 111
101 112 ; default locale used by VCS systems
102 locale = en_US.UTF-8
113 #locale = en_US.UTF-8
103 114
104 115 ; path to binaries for vcsserver, it should be set by the installer
105 ; at installation time, e.g /home/user/vcsserver-1/profile/bin
116 ; at installation time, e.g /home/user/.rccontrol/vcsserver-1/profile/bin
106 117 ; it can also be a path to nix-build output in case of development
107 118 core.binary_dir = ""
108 119
@@ -116,21 +127,21 b' core.binary_dir = ""'
116 127
117 128 ; Default cache dir for caches. Putting this into a ramdisk can boost performance.
118 129 ; eg. /tmpfs/data_ramdisk, however this directory might require large amount of space
119 cache_dir = %(here)s/data
130 #cache_dir = %(here)s/data
120 131
121 132 ; ***************************************
122 133 ; `repo_object` cache, default file based
123 134 ; ***************************************
124 135
125 136 ; `repo_object` cache settings for vcs methods for repositories
126 rc_cache.repo_object.backend = dogpile.cache.rc.file_namespace
137 #rc_cache.repo_object.backend = dogpile.cache.rc.file_namespace
127 138
128 139 ; cache auto-expires after N seconds
129 140 ; Examples: 86400 (1Day), 604800 (7Days), 1209600 (14Days), 2592000 (30days), 7776000 (90Days)
130 rc_cache.repo_object.expiration_time = 2592000
141 #rc_cache.repo_object.expiration_time = 2592000
131 142
132 143 ; file cache store path. Defaults to `cache_dir =` value or tempdir if both values are not set
133 #rc_cache.repo_object.arguments.filename = /tmp/vcsserver_cache.db
144 #rc_cache.repo_object.arguments.filename = /tmp/vcsserver_cache_repo_object.db
134 145
135 146 ; ***********************************************************
136 147 ; `repo_object` cache with redis backend
@@ -165,55 +176,59 b' rc_cache.repo_object.expiration_time = 2'
165 176 #statsd.statsd_prefix =
166 177 #statsd.statsd_ipv6 = false
167 178
179 ; configure logging automatically at server startup set to false
180 ; to use the below custom logging config.
181 #logging.autoconfigure = true
182
183 ; specify your own custom logging config file to configure logging
184 #logging.logging_conf_file = /path/to/custom_logging.ini
185
168 186 ; #####################
169 187 ; LOGGING CONFIGURATION
170 188 ; #####################
171 [loggers]
172 keys = root, vcsserver
189 #[loggers]
190 #keys = root, vcsserver
173 191
174 [handlers]
175 keys = console
192 #[handlers]
193 #keys = console
176 194
177 [formatters]
178 keys = generic
195 #[formatters]
196 #keys = generic
179 197
180 198 ; #######
181 199 ; LOGGERS
182 200 ; #######
183 [logger_root]
184 level = NOTSET
185 handlers = console
201 #[logger_root]
202 #level = NOTSET
203 #handlers = console
186 204
187 [logger_vcsserver]
188 level = DEBUG
189 handlers =
190 qualname = vcsserver
191 propagate = 1
192
205 #[logger_vcsserver]
206 #level = INFO
207 #handlers =
208 #qualname = vcsserver
209 #propagate = 1
193 210
194 211 ; ########
195 212 ; HANDLERS
196 213 ; ########
197 214
198 [handler_console]
199 class = StreamHandler
200 args = (sys.stderr, )
201 level = INFO
202 formatter = generic
215 #[handler_console]
216 #class = StreamHandler
217 #args = (sys.stderr, )
218 #level = INFO
203 219 ; To enable JSON formatted logs replace generic with json
204 220 ; This allows sending properly formatted logs to grafana loki or elasticsearch
205 221 #formatter = json
206
222 #formatter = generic
207 223
208 224 ; ##########
209 225 ; FORMATTERS
210 226 ; ##########
211 227
212 [formatter_generic]
213 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
214 datefmt = %Y-%m-%d %H:%M:%S
228 #[formatter_generic]
229 #format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
230 #datefmt = %Y-%m-%d %H:%M:%S
215 231
216 [formatter_json]
217 format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
218 class = vcsserver.lib._vendor.jsonlogger.JsonFormatter
219
232 #[formatter_json]
233 #format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
234 #class = vcsserver.lib._vendor.jsonlogger.JsonFormatter
@@ -21,21 +21,22 b' import base64'
21 21 import locale
22 22 import logging
23 23 import uuid
24 import time
24 25 import wsgiref.util
25 26 import traceback
26 27 import tempfile
27 28 import psutil
29
28 30 from itertools import chain
29 31 from cStringIO import StringIO
30 32
31 33 import simplejson as json
32 34 import msgpack
33 35 from pyramid.config import Configurator
34 from pyramid.settings import asbool, aslist
35 36 from pyramid.wsgi import wsgiapp
36 37 from pyramid.compat import configparser
37 38 from pyramid.response import Response
38
39 from vcsserver.config.settings_maker import SettingsMaker
39 40 from vcsserver.utils import safe_int
40 41 from vcsserver.lib.statsd_client import StatsdClient
41 42
@@ -51,6 +52,7 b' except locale.Error as e:'
51 52 'LOCALE ERROR: failed to set LC_ALL, fallback to LC_ALL=C, org error: %s', e)
52 53 os.environ['LC_ALL'] = 'C'
53 54
55
54 56 import vcsserver
55 57 from vcsserver import remote_wsgi, scm_app, settings, hgpatches
56 58 from vcsserver.git_lfs.app import GIT_LFS_CONTENT_TYPE, GIT_LFS_PROTO_PAT
@@ -84,40 +86,6 b' def _is_request_chunked(environ):'
84 86 return stream
85 87
86 88
87 def _int_setting(settings, name, default):
88 settings[name] = int(settings.get(name, default))
89 return settings[name]
90
91
92 def _bool_setting(settings, name, default):
93 input_val = settings.get(name, default)
94 if isinstance(input_val, unicode):
95 input_val = input_val.encode('utf8')
96 settings[name] = asbool(input_val)
97 return settings[name]
98
99
100 def _list_setting(settings, name, default):
101 raw_value = settings.get(name, default)
102
103 # Otherwise we assume it uses pyramids space/newline separation.
104 settings[name] = aslist(raw_value)
105 return settings[name]
106
107
108 def _string_setting(settings, name, default, lower=True, default_when_empty=False):
109 value = settings.get(name, default)
110
111 if default_when_empty and not value:
112 # use default value when value is empty
113 value = default
114
115 if lower:
116 value = value.lower()
117 settings[name] = value
118 return settings[name]
119
120
121 89 def log_max_fd():
122 90 try:
123 91 maxfd = psutil.Process().rlimit(psutil.RLIMIT_NOFILE)[1]
@@ -241,7 +209,6 b' class HTTPApplication(object):'
241 209 _use_echo_app = False
242 210
243 211 def __init__(self, settings=None, global_config=None):
244 self._sanitize_settings_and_apply_defaults(settings)
245 212
246 213 self.config = Configurator(settings=settings)
247 214 # Init our statsd at very start
@@ -285,40 +252,6 b' class HTTPApplication(object):'
285 252 vcsserver.PYRAMID_SETTINGS = settings_merged
286 253 vcsserver.CONFIG = settings_merged
287 254
288 def _sanitize_settings_and_apply_defaults(self, settings):
289 temp_store = tempfile.gettempdir()
290 default_cache_dir = os.path.join(temp_store, 'rc_cache')
291
292 # save default, cache dir, and use it for all backends later.
293 default_cache_dir = _string_setting(
294 settings,
295 'cache_dir',
296 default_cache_dir, lower=False, default_when_empty=True)
297
298 # ensure we have our dir created
299 if not os.path.isdir(default_cache_dir):
300 os.makedirs(default_cache_dir, mode=0o755)
301
302 # exception store cache
303 _string_setting(
304 settings,
305 'exception_tracker.store_path',
306 temp_store, lower=False, default_when_empty=True)
307
308 # repo_object cache
309 _string_setting(
310 settings,
311 'rc_cache.repo_object.backend',
312 'dogpile.cache.rc.file_namespace', lower=False)
313 _int_setting(
314 settings,
315 'rc_cache.repo_object.expiration_time',
316 30 * 24 * 60 * 60)
317 _string_setting(
318 settings,
319 'rc_cache.repo_object.arguments.filename',
320 os.path.join(default_cache_dir, 'vcsserver_cache_1'), lower=False)
321
322 255 def _configure(self):
323 256 self.config.add_renderer(name='msgpack', factory=self._msgpack_renderer_factory)
324 257
@@ -708,13 +641,110 b' class ResponseFilter(object):'
708 641 return self._start_response(status, headers, exc_info)
709 642
710 643
644 def sanitize_settings_and_apply_defaults(global_config, settings):
645 global_settings_maker = SettingsMaker(global_config)
646 settings_maker = SettingsMaker(settings)
647
648 settings_maker.make_setting(
649 'logging.autoconfigure',
650 default=True,
651 parser='bool')
652
653 logging_conf = os.path.join(os.path.dirname(global_config.get('__file__')), 'logging.ini')
654 settings_maker.enable_logging(logging_conf)
655
656 # Default includes, possible to change as a user
657 pyramid_includes = settings_maker.make_setting('pyramid.includes', [], parser='list:newline')
658 log.debug(
659 "Using the following pyramid.includes: %s",
660 pyramid_includes)
661
662 settings_maker.make_setting('__file__', global_config.get('__file__'))
663
664 settings_maker.make_setting(
665 'pyramid.default_locale_name',
666 default='en',
667 parser='string')
668 settings_maker.make_setting(
669 'locale',
670 default='en_US.UTF-8',
671 parser='string')
672
673 settings_maker.make_setting(
674 'core.binary_dir',
675 default='',
676 parser='string')
677
678 temp_store = tempfile.gettempdir()
679 default_cache_dir = os.path.join(temp_store, 'rc_cache')
680 # save default, cache dir, and use it for all backends later.
681 default_cache_dir = settings_maker.make_setting(
682 'cache_dir',
683 default=default_cache_dir, default_when_empty=True,
684 parser='dir:ensured')
685
686 # exception store cache
687 settings_maker.make_setting(
688 'exception_tracker.store_path',
689 default=os.path.join(default_cache_dir, 'exc_store'), default_when_empty=True,
690 parser='dir:ensured'
691 )
692
693 # repo_object cache defaults
694 settings_maker.make_setting(
695 'rc_cache.repo_object.backend',
696 default='dogpile.cache.rc.file_namespace',
697 parser='string')
698 settings_maker.make_setting(
699 'rc_cache.repo_object.expiration_time',
700 default=30 * 24 * 60 * 60, # 30days
701 parser='int')
702 settings_maker. make_setting(
703 'rc_cache.repo_object.arguments.filename',
704 default=os.path.join(default_cache_dir, 'vcsserver_cache_repo_object.db'),
705 parser='string')
706
707 # statsd
708 settings_maker. make_setting(
709 'statsd.enabled',
710 default=False,
711 parser='bool')
712 settings_maker. make_setting(
713 'statsd.statsd_host',
714 default='statsd-exporter',
715 parser='string')
716 settings_maker. make_setting(
717 'statsd.statsd_port',
718 default=9125,
719 parser='int')
720 settings_maker. make_setting(
721 'statsd.statsd_prefix',
722 default='',
723 parser='string')
724 settings_maker. make_setting(
725 'statsd.statsd_ipv6',
726 default=False,
727 parser='bool')
728
729
711 730 def main(global_config, **settings):
731 start_time = time.time()
732 log.info('Pyramid app config starting')
733
712 734 if MercurialFactory:
713 735 hgpatches.patch_largefiles_capabilities()
714 736 hgpatches.patch_subrepo_type_mapping()
715 737
738 # Fill in and sanitize the defaults & do ENV expansion
739 sanitize_settings_and_apply_defaults(global_config, settings)
740
716 741 # init and bootstrap StatsdClient
717 742 StatsdClient.setup(settings)
718 743
719 app = HTTPApplication(settings=settings, global_config=global_config)
720 return app.wsgi_app()
744 pyramid_app = HTTPApplication(settings=settings, global_config=global_config).wsgi_app()
745 total_time = time.time() - start_time
746 log.info('Pyramid app `%s` created and configured in %.2fs',
747 getattr(pyramid_app, 'func_name', 'pyramid_app'), total_time)
748 return pyramid_app
749
750
General Comments 0
You need to be logged in to leave comments. Login now