##// 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
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 ; GUNICORN APPLICATION SERVER
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 ; Module to use, this setting shouldn't be changed
36 ; Module to use, this setting shouldn't be changed
37 #use = egg:gunicorn#main
37 #use = egg:gunicorn#main
@@ -86,7 +86,7 b' asyncore_use_poll = true'
86 ; serving requests. Workers still alive after the timeout (starting from the
86 ; serving requests. Workers still alive after the timeout (starting from the
87 ; receipt of the restart signal) are force killed.
87 ; receipt of the restart signal) are force killed.
88 ; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
88 ; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
89 #graceful_timeout = 3600
89 #graceful_timeout = 21600
90
90
91 # The number of seconds to wait for requests on a Keep-Alive connection.
91 # The number of seconds to wait for requests on a Keep-Alive connection.
92 # Generally set in the 1-5 seconds range.
92 # Generally set in the 1-5 seconds range.
@@ -110,6 +110,17 b' asyncore_use_poll = true'
110 [app:main]
110 [app:main]
111 ; The %(here)s variable will be replaced with the absolute path of parent directory
111 ; The %(here)s variable will be replaced with the absolute path of parent directory
112 ; of this file
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 use = egg:rhodecode-vcsserver
124 use = egg:rhodecode-vcsserver
114
125
115
126
@@ -133,13 +144,13 b' debugtoolbar.exclude_prefixes ='
133 ; #################
144 ; #################
134
145
135 ; Pyramid default locales, we need this to be set
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 ; default locale used by VCS systems
149 ; default locale used by VCS systems
139 locale = en_US.UTF-8
150 #locale = en_US.UTF-8
140
151
141 ; path to binaries for vcsserver, it should be set by the installer
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 ; it can also be a path to nix-build output in case of development
154 ; it can also be a path to nix-build output in case of development
144 core.binary_dir = ""
155 core.binary_dir = ""
145
156
@@ -153,21 +164,21 b' core.binary_dir = ""'
153
164
154 ; Default cache dir for caches. Putting this into a ramdisk can boost performance.
165 ; Default cache dir for caches. Putting this into a ramdisk can boost performance.
155 ; eg. /tmpfs/data_ramdisk, however this directory might require large amount of space
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 ; `repo_object` cache, default file based
170 ; `repo_object` cache, default file based
160 ; ***************************************
171 ; ***************************************
161
172
162 ; `repo_object` cache settings for vcs methods for repositories
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 ; cache auto-expires after N seconds
176 ; cache auto-expires after N seconds
166 ; Examples: 86400 (1Day), 604800 (7Days), 1209600 (14Days), 2592000 (30days), 7776000 (90Days)
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 ; file cache store path. Defaults to `cache_dir =` value or tempdir if both values are not set
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 ; `repo_object` cache with redis backend
184 ; `repo_object` cache with redis backend
@@ -202,55 +213,59 b' rc_cache.repo_object.expiration_time = 2'
202 #statsd.statsd_prefix =
213 #statsd.statsd_prefix =
203 #statsd.statsd_ipv6 = false
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 ; LOGGING CONFIGURATION
224 ; LOGGING CONFIGURATION
207 ; #####################
225 ; #####################
208 [loggers]
226 #[loggers]
209 keys = root, vcsserver
227 #keys = root, vcsserver
210
228
211 [handlers]
229 #[handlers]
212 keys = console
230 #keys = console
213
231
214 [formatters]
232 #[formatters]
215 keys = generic
233 #keys = generic
216
234
217 ; #######
235 ; #######
218 ; LOGGERS
236 ; LOGGERS
219 ; #######
237 ; #######
220 [logger_root]
238 #[logger_root]
221 level = NOTSET
239 #level = NOTSET
222 handlers = console
240 #handlers = console
223
241
224 [logger_vcsserver]
242 #[logger_vcsserver]
225 level = DEBUG
243 #level = INFO
226 handlers =
244 #handlers =
227 qualname = vcsserver
245 #qualname = vcsserver
228 propagate = 1
246 #propagate = 1
229
230
247
231 ; ########
248 ; ########
232 ; HANDLERS
249 ; HANDLERS
233 ; ########
250 ; ########
234
251
235 [handler_console]
252 #[handler_console]
236 class = StreamHandler
253 #class = StreamHandler
237 args = (sys.stderr, )
254 #args = (sys.stderr, )
238 level = DEBUG
255 #level = INFO
239 formatter = generic
240 ; To enable JSON formatted logs replace generic with json
256 ; To enable JSON formatted logs replace generic with json
241 ; This allows sending properly formatted logs to grafana loki or elasticsearch
257 ; This allows sending properly formatted logs to grafana loki or elasticsearch
242 #formatter = json
258 #formatter = json
243
259 #formatter = generic
244
260
245 ; ##########
261 ; ##########
246 ; FORMATTERS
262 ; FORMATTERS
247 ; ##########
263 ; ##########
248
264
249 [formatter_generic]
265 #[formatter_generic]
250 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
266 #format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
251 datefmt = %Y-%m-%d %H:%M:%S
267 #datefmt = %Y-%m-%d %H:%M:%S
252
268
253 [formatter_json]
269 #[formatter_json]
254 format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
270 #format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
255 class = vcsserver.lib._vendor.jsonlogger.JsonFormatter
271 #class = vcsserver.lib._vendor.jsonlogger.JsonFormatter
256
@@ -30,12 +30,12 b' worker_tmp_dir = None'
30 tmp_upload_dir = None
30 tmp_upload_dir = None
31
31
32 # Custom log format
32 # Custom log format
33 access_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"')
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 # loki format for easier parsing in grafana
36 # loki format for easier parsing in grafana
37 #access_log_format = (
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"')
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 # self adjust workers based on CPU count
40 # self adjust workers based on CPU count
41 # workers = get_workers()
41 # workers = get_workers()
@@ -97,9 +97,12 b' def post_fork(server, worker):'
97 if conf.has_option(section, 'memory_usage_recovery_threshold'):
97 if conf.has_option(section, 'memory_usage_recovery_threshold'):
98 _memory_usage_recovery_threshold = conf.getfloat(section, 'memory_usage_recovery_threshold')
98 _memory_usage_recovery_threshold = conf.getfloat(section, 'memory_usage_recovery_threshold')
99
99
100 worker._memory_max_usage = _memory_max_usage
100 worker._memory_max_usage = int(os.environ.get('RC_GUNICORN_MEMORY_MAX_USAGE', '')
101 worker._memory_usage_check_interval = _memory_usage_check_interval
101 or _memory_max_usage)
102 worker._memory_usage_recovery_threshold = _memory_usage_recovery_threshold
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 # register memory last check time, with some random offset so we don't recycle all
107 # register memory last check time, with some random offset so we don't recycle all
105 # at once
108 # at once
@@ -14,7 +14,7 b' port = 9900'
14 ; GUNICORN APPLICATION SERVER
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 ; Module to use, this setting shouldn't be changed
19 ; Module to use, this setting shouldn't be changed
20 use = egg:gunicorn#main
20 use = egg:gunicorn#main
@@ -69,7 +69,7 b' limit_request_field_size = 0'
69 ; serving requests. Workers still alive after the timeout (starting from the
69 ; serving requests. Workers still alive after the timeout (starting from the
70 ; receipt of the restart signal) are force killed.
70 ; receipt of the restart signal) are force killed.
71 ; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
71 ; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
72 graceful_timeout = 3600
72 graceful_timeout = 21600
73
73
74 # The number of seconds to wait for requests on a Keep-Alive connection.
74 # The number of seconds to wait for requests on a Keep-Alive connection.
75 # Generally set in the 1-5 seconds range.
75 # Generally set in the 1-5 seconds range.
@@ -93,16 +93,27 b' memory_usage_recovery_threshold = 0.8'
93 [app:main]
93 [app:main]
94 ; The %(here)s variable will be replaced with the absolute path of parent directory
94 ; The %(here)s variable will be replaced with the absolute path of parent directory
95 ; of this file
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 use = egg:rhodecode-vcsserver
107 use = egg:rhodecode-vcsserver
97
108
98 ; Pyramid default locales, we need this to be set
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 ; default locale used by VCS systems
112 ; default locale used by VCS systems
102 locale = en_US.UTF-8
113 #locale = en_US.UTF-8
103
114
104 ; path to binaries for vcsserver, it should be set by the installer
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 ; it can also be a path to nix-build output in case of development
117 ; it can also be a path to nix-build output in case of development
107 core.binary_dir = ""
118 core.binary_dir = ""
108
119
@@ -116,21 +127,21 b' core.binary_dir = ""'
116
127
117 ; Default cache dir for caches. Putting this into a ramdisk can boost performance.
128 ; Default cache dir for caches. Putting this into a ramdisk can boost performance.
118 ; eg. /tmpfs/data_ramdisk, however this directory might require large amount of space
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 ; `repo_object` cache, default file based
133 ; `repo_object` cache, default file based
123 ; ***************************************
134 ; ***************************************
124
135
125 ; `repo_object` cache settings for vcs methods for repositories
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 ; cache auto-expires after N seconds
139 ; cache auto-expires after N seconds
129 ; Examples: 86400 (1Day), 604800 (7Days), 1209600 (14Days), 2592000 (30days), 7776000 (90Days)
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 ; file cache store path. Defaults to `cache_dir =` value or tempdir if both values are not set
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 ; `repo_object` cache with redis backend
147 ; `repo_object` cache with redis backend
@@ -165,55 +176,59 b' rc_cache.repo_object.expiration_time = 2'
165 #statsd.statsd_prefix =
176 #statsd.statsd_prefix =
166 #statsd.statsd_ipv6 = false
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 ; LOGGING CONFIGURATION
187 ; LOGGING CONFIGURATION
170 ; #####################
188 ; #####################
171 [loggers]
189 #[loggers]
172 keys = root, vcsserver
190 #keys = root, vcsserver
173
191
174 [handlers]
192 #[handlers]
175 keys = console
193 #keys = console
176
194
177 [formatters]
195 #[formatters]
178 keys = generic
196 #keys = generic
179
197
180 ; #######
198 ; #######
181 ; LOGGERS
199 ; LOGGERS
182 ; #######
200 ; #######
183 [logger_root]
201 #[logger_root]
184 level = NOTSET
202 #level = NOTSET
185 handlers = console
203 #handlers = console
186
204
187 [logger_vcsserver]
205 #[logger_vcsserver]
188 level = DEBUG
206 #level = INFO
189 handlers =
207 #handlers =
190 qualname = vcsserver
208 #qualname = vcsserver
191 propagate = 1
209 #propagate = 1
192
193
210
194 ; ########
211 ; ########
195 ; HANDLERS
212 ; HANDLERS
196 ; ########
213 ; ########
197
214
198 [handler_console]
215 #[handler_console]
199 class = StreamHandler
216 #class = StreamHandler
200 args = (sys.stderr, )
217 #args = (sys.stderr, )
201 level = INFO
218 #level = INFO
202 formatter = generic
203 ; To enable JSON formatted logs replace generic with json
219 ; To enable JSON formatted logs replace generic with json
204 ; This allows sending properly formatted logs to grafana loki or elasticsearch
220 ; This allows sending properly formatted logs to grafana loki or elasticsearch
205 #formatter = json
221 #formatter = json
206
222 #formatter = generic
207
223
208 ; ##########
224 ; ##########
209 ; FORMATTERS
225 ; FORMATTERS
210 ; ##########
226 ; ##########
211
227
212 [formatter_generic]
228 #[formatter_generic]
213 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
229 #format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
214 datefmt = %Y-%m-%d %H:%M:%S
230 #datefmt = %Y-%m-%d %H:%M:%S
215
231
216 [formatter_json]
232 #[formatter_json]
217 format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
233 #format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
218 class = vcsserver.lib._vendor.jsonlogger.JsonFormatter
234 #class = vcsserver.lib._vendor.jsonlogger.JsonFormatter
219
@@ -21,21 +21,22 b' import base64'
21 import locale
21 import locale
22 import logging
22 import logging
23 import uuid
23 import uuid
24 import time
24 import wsgiref.util
25 import wsgiref.util
25 import traceback
26 import traceback
26 import tempfile
27 import tempfile
27 import psutil
28 import psutil
29
28 from itertools import chain
30 from itertools import chain
29 from cStringIO import StringIO
31 from cStringIO import StringIO
30
32
31 import simplejson as json
33 import simplejson as json
32 import msgpack
34 import msgpack
33 from pyramid.config import Configurator
35 from pyramid.config import Configurator
34 from pyramid.settings import asbool, aslist
35 from pyramid.wsgi import wsgiapp
36 from pyramid.wsgi import wsgiapp
36 from pyramid.compat import configparser
37 from pyramid.compat import configparser
37 from pyramid.response import Response
38 from pyramid.response import Response
38
39 from vcsserver.config.settings_maker import SettingsMaker
39 from vcsserver.utils import safe_int
40 from vcsserver.utils import safe_int
40 from vcsserver.lib.statsd_client import StatsdClient
41 from vcsserver.lib.statsd_client import StatsdClient
41
42
@@ -51,6 +52,7 b' except locale.Error as e:'
51 'LOCALE ERROR: failed to set LC_ALL, fallback to LC_ALL=C, org error: %s', e)
52 'LOCALE ERROR: failed to set LC_ALL, fallback to LC_ALL=C, org error: %s', e)
52 os.environ['LC_ALL'] = 'C'
53 os.environ['LC_ALL'] = 'C'
53
54
55
54 import vcsserver
56 import vcsserver
55 from vcsserver import remote_wsgi, scm_app, settings, hgpatches
57 from vcsserver import remote_wsgi, scm_app, settings, hgpatches
56 from vcsserver.git_lfs.app import GIT_LFS_CONTENT_TYPE, GIT_LFS_PROTO_PAT
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 return stream
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 def log_max_fd():
89 def log_max_fd():
122 try:
90 try:
123 maxfd = psutil.Process().rlimit(psutil.RLIMIT_NOFILE)[1]
91 maxfd = psutil.Process().rlimit(psutil.RLIMIT_NOFILE)[1]
@@ -241,7 +209,6 b' class HTTPApplication(object):'
241 _use_echo_app = False
209 _use_echo_app = False
242
210
243 def __init__(self, settings=None, global_config=None):
211 def __init__(self, settings=None, global_config=None):
244 self._sanitize_settings_and_apply_defaults(settings)
245
212
246 self.config = Configurator(settings=settings)
213 self.config = Configurator(settings=settings)
247 # Init our statsd at very start
214 # Init our statsd at very start
@@ -285,40 +252,6 b' class HTTPApplication(object):'
285 vcsserver.PYRAMID_SETTINGS = settings_merged
252 vcsserver.PYRAMID_SETTINGS = settings_merged
286 vcsserver.CONFIG = settings_merged
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 def _configure(self):
255 def _configure(self):
323 self.config.add_renderer(name='msgpack', factory=self._msgpack_renderer_factory)
256 self.config.add_renderer(name='msgpack', factory=self._msgpack_renderer_factory)
324
257
@@ -708,13 +641,110 b' class ResponseFilter(object):'
708 return self._start_response(status, headers, exc_info)
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 def main(global_config, **settings):
730 def main(global_config, **settings):
731 start_time = time.time()
732 log.info('Pyramid app config starting')
733
712 if MercurialFactory:
734 if MercurialFactory:
713 hgpatches.patch_largefiles_capabilities()
735 hgpatches.patch_largefiles_capabilities()
714 hgpatches.patch_subrepo_type_mapping()
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 # init and bootstrap StatsdClient
741 # init and bootstrap StatsdClient
717 StatsdClient.setup(settings)
742 StatsdClient.setup(settings)
718
743
719 app = HTTPApplication(settings=settings, global_config=global_config)
744 pyramid_app = HTTPApplication(settings=settings, global_config=global_config).wsgi_app()
720 return app.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