1"""Copyright 2008 Orbitz WorldWide
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7   http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License."""
14# Django settings for graphite project.
15# DO NOT MODIFY THIS FILE DIRECTLY - use local_settings.py instead
16from __future__ import print_function
17import os
18import sys
19from os.path import abspath, dirname, join
20from warnings import warn
21from importlib import import_module
22
23from django import VERSION as DJANGO_VERSION
24try:
25    from django.urls import reverse_lazy
26except ImportError:  # Django < 1.10
27    from django.core.urlresolvers import reverse_lazy
28
29
30GRAPHITE_WEB_APP_SETTINGS_LOADED = False
31WEBAPP_VERSION = '1.1.8'
32DEBUG = False
33JAVASCRIPT_DEBUG = False
34
35DATE_FORMAT = '%m/%d'
36
37# Allow UTF-8 metrics' names (can cause performance issues)
38UTF8_METRICS = False
39
40# Filesystem layout
41WEB_DIR = dirname( abspath(__file__) )
42WEBAPP_DIR = dirname(WEB_DIR)
43GRAPHITE_ROOT = dirname(WEBAPP_DIR)
44# Initialize additional path variables
45# Defaults for these are set after local_settings is imported
46STATIC_ROOT = ''
47STATIC_URL = '/static/'
48URL_PREFIX = ''
49CONF_DIR = ''
50DASHBOARD_CONF = ''
51GRAPHTEMPLATES_CONF = ''
52STORAGE_DIR = ''
53WHITELIST_FILE = ''
54INDEX_FILE = ''
55LOG_DIR = ''
56CERES_DIR = ''
57WHISPER_DIR = ''
58RRD_DIR = ''
59STANDARD_DIRS = []
60
61# Timeout settings
62FIND_TIMEOUT = None  # default 3.0 see below
63FETCH_TIMEOUT = None  # default 6.0 see below
64
65# Cluster settings
66CLUSTER_SERVERS = []
67
68# Worker Pool
69USE_WORKER_POOL = True
70POOL_MAX_WORKERS = 10
71
72# This settings control whether https is used to communicate between cluster members
73INTRACLUSTER_HTTPS = False
74REMOTE_FIND_TIMEOUT = None  # Replaced by FIND_TIMEOUT
75REMOTE_FETCH_TIMEOUT = None  # Replaced by FETCH_TIMEOUT
76REMOTE_RETRY_DELAY = 60.0
77REMOTE_EXCLUDE_LOCAL = False
78STORE_FAIL_ON_ERROR = False
79REMOTE_STORE_MERGE_RESULTS = True
80REMOTE_STORE_FORWARD_HEADERS = []
81REMOTE_STORE_USE_POST = False
82REMOTE_BUFFER_SIZE = 1024 * 1024 # Set to 0 to prevent streaming deserialization
83
84# Carbonlink settings
85CARBON_METRIC_PREFIX='carbon'
86CARBONLINK_HOSTS = ["127.0.0.1:7002"]
87CARBONLINK_TIMEOUT = 1.0
88CARBONLINK_HASHING_KEYFUNC = None
89CARBONLINK_HASHING_TYPE = 'carbon_ch'
90CARBONLINK_RETRY_DELAY = 15
91CARBONLINK_PICKLE_PROTOCOL = -1
92REPLICATION_FACTOR = 1
93
94# Cache settings.
95MEMCACHE_HOSTS = []
96MEMCACHE_KEY_PREFIX = ''
97MEMCACHE_OPTIONS = {}
98CACHES={}
99FIND_CACHE_DURATION = 300
100FIND_TOLERANCE = 2 * FIND_CACHE_DURATION
101DEFAULT_CACHE_DURATION = 60 #metric data and graphs are cached for one minute by default
102DEFAULT_CACHE_POLICY = []
103
104# this setting controls the default xFilesFactor used for query-time aggregration
105DEFAULT_XFILES_FACTOR = 0
106
107# These can also be configured using:
108# https://docs.djangoproject.com/en/1.11/topics/logging/
109LOG_RENDERING_PERFORMANCE = False
110LOG_CACHE_PERFORMANCE = False
111LOG_INFO_PERFORMANCE = True
112LOG_ROTATION = True
113LOG_ROTATION_COUNT = 1
114
115LOG_FILE_INFO = 'info.log'
116LOG_FILE_EXCEPTION = 'exception.log'
117LOG_FILE_CACHE = 'cache.log'
118LOG_FILE_RENDERING = 'rendering.log'
119
120MAX_FETCH_RETRIES = 2
121
122# This settings limit metrics find to prevent from too large query
123METRICS_FIND_WARNING_THRESHOLD = float('Inf') # Print a warning if more than X metrics are returned
124METRICS_FIND_FAILURE_THRESHOLD = float('Inf') # Fail if more than X metrics are returned
125
126#Local rendering settings
127RENDER_TRIM_RECENT_IN_AGGREGATE = False #if True, set most recent datapoints to None if prior datapoint was not None
128
129#Remote rendering settings
130REMOTE_RENDERING = False #if True, rendering is delegated to RENDERING_HOSTS
131RENDERING_HOSTS = []
132REMOTE_RENDER_CONNECT_TIMEOUT = 1.0
133
134#Miscellaneous settings
135DOCUMENTATION_VERSION = 'latest' if 'dev' in WEBAPP_VERSION else WEBAPP_VERSION
136DOCUMENTATION_URL = 'https://graphite.readthedocs.io/en/{}/'.format(DOCUMENTATION_VERSION)
137ALLOW_ANONYMOUS_CLI = True
138LEGEND_MAX_ITEMS = 10
139RRD_CF = 'AVERAGE'
140STORAGE_FINDERS = (
141    'graphite.finders.remote.RemoteFinder',
142    'graphite.finders.standard.StandardFinder',
143)
144
145# TagDB settings
146TAGDB = 'graphite.tags.localdatabase.LocalDatabaseTagDB'
147
148TAGDB_CACHE_DURATION = 60
149
150TAGDB_AUTOCOMPLETE_LIMIT = 100
151
152TAGDB_REDIS_HOST = 'localhost'
153TAGDB_REDIS_PORT = 6379
154TAGDB_REDIS_DB = 0
155TAGDB_REDIS_PASSWORD = ''
156
157TAGDB_HTTP_URL = ''
158TAGDB_HTTP_USER = ''
159TAGDB_HTTP_PASSWORD = ''
160TAGDB_HTTP_AUTOCOMPLETE = False
161
162# Function plugins
163FUNCTION_PLUGINS = []
164
165
166MIDDLEWARE = ()
167if DJANGO_VERSION < (1, 10):
168    MIDDLEWARE_CLASSES = MIDDLEWARE
169MAX_TAG_LENGTH = 50
170AUTO_REFRESH_INTERVAL = 60
171
172#Authentication settings
173USE_LDAP_AUTH = False
174LDAP_SERVER = "" # "ldapserver.mydomain.com"
175LDAP_PORT = 389
176LDAP_USE_TLS = False
177LDAP_SEARCH_BASE = "" # "OU=users,DC=mydomain,DC=com"
178LDAP_BASE_USER = "" # "CN=some_readonly_account,DC=mydomain,DC=com"
179LDAP_BASE_PASS = "" # "my_password"
180LDAP_USER_QUERY = "" # "(username=%s)"  For Active Directory use "(sAMAccountName=%s)"
181LDAP_URI = None
182LDAP_USER_DN_TEMPLATE = None
183
184#Set this to True to delegate authentication to the web server
185USE_REMOTE_USER_AUTHENTICATION = False
186REMOTE_USER_BACKEND = "" # Provide an alternate or subclassed backend
187REMOTE_USER_MIDDLEWARE = "" # Provide an alternate or subclassed middleware
188AUTHENTICATION_BACKENDS=[]
189
190# Django 1.5 requires this so we set a default but warn the user
191SECRET_KEY = 'UNSAFE_DEFAULT'
192
193# Input validation
194# - When False we still validate the received input parameters, but if validation
195#   detects an issue it only logs an error and doesn't directly reject the request
196# - When True we reject requests of which the input validation detected an issue with the
197#   provided arguments and return an error message to the user
198ENFORCE_INPUT_VALIDATION = False
199
200# headers which shall be added to log statements informing about invalid queries,
201# this is useful to identify where a query came from.
202# The dict is keyed by the header name and the associated value is a short description
203# of the header which will be used in the log statement, for example:
204# {'X-FORWARD-FOR': 'forwarded-for'}
205INPUT_VALIDATION_SOURCE_ID_HEADERS = {}
206
207# Django 1.5 requires this to be set. Here we default to prior behavior and allow all
208ALLOWED_HOSTS = [ '*' ]
209
210# Override to link a different URL for login (e.g. for django_openid_auth)
211LOGIN_URL = reverse_lazy('account_login')
212
213# Set the default timezone to UTC
214TIME_ZONE = 'UTC'
215
216# Set to True to require authentication to save or delete dashboards
217DASHBOARD_REQUIRE_AUTHENTICATION = False
218# Require Django change/delete permissions to save or delete dashboards.
219# NOTE: Requires DASHBOARD_REQUIRE_AUTHENTICATION to be set
220DASHBOARD_REQUIRE_PERMISSIONS = False
221# Name of a group to which the user must belong to save or delete dashboards.  Alternative to
222# DASHBOARD_REQUIRE_PERMISSIONS, particularly useful when using only LDAP (without Admin app)
223# NOTE: Requires DASHBOARD_REQUIRE_AUTHENTICATION to be set
224DASHBOARD_REQUIRE_EDIT_GROUP = None
225
226DATABASES = None
227
228# If using rrdcached, set to the address or socket of the daemon
229FLUSHRRDCACHED = ''
230
231## Load our local_settings
232SETTINGS_MODULE = os.environ.get('GRAPHITE_SETTINGS_MODULE', 'graphite.local_settings')
233try:
234    globals().update(import_module(SETTINGS_MODULE).__dict__)
235except ImportError:
236    print("Could not import {0}, using defaults!".format(SETTINGS_MODULE), file=sys.stderr)
237
238## Load Django settings if they werent picked up in local_settings
239if not GRAPHITE_WEB_APP_SETTINGS_LOADED:
240    from graphite.app_settings import *  # noqa
241
242
243STATICFILES_DIRS = (
244    join(WEBAPP_DIR, 'content'),
245)
246
247# Handle renamed timeout settings
248FIND_TIMEOUT = FIND_TIMEOUT or REMOTE_FIND_TIMEOUT or 3.0
249FETCH_TIMEOUT = FETCH_TIMEOUT or REMOTE_FETCH_TIMEOUT or 6.0
250
251## Set config dependent on flags set in local_settings
252# Path configuration
253if not STATIC_ROOT:
254    STATIC_ROOT = join(GRAPHITE_ROOT, 'static')
255
256if not CONF_DIR:
257    CONF_DIR = os.environ.get('GRAPHITE_CONF_DIR', join(GRAPHITE_ROOT, 'conf'))
258if not DASHBOARD_CONF:
259    DASHBOARD_CONF = join(CONF_DIR, 'dashboard.conf')
260if not GRAPHTEMPLATES_CONF:
261    GRAPHTEMPLATES_CONF = join(CONF_DIR, 'graphTemplates.conf')
262
263if not STORAGE_DIR:
264    STORAGE_DIR = os.environ.get('GRAPHITE_STORAGE_DIR', join(GRAPHITE_ROOT, 'storage'))
265if not WHITELIST_FILE:
266    WHITELIST_FILE = join(STORAGE_DIR, 'lists', 'whitelist')
267if not INDEX_FILE:
268    INDEX_FILE = join(STORAGE_DIR, 'index')
269if not LOG_DIR:
270    LOG_DIR = join(STORAGE_DIR, 'log', 'webapp')
271if not WHISPER_DIR:
272    WHISPER_DIR = join(STORAGE_DIR, 'whisper/')
273if not CERES_DIR:
274    CERES_DIR = join(STORAGE_DIR, 'ceres/')
275if not RRD_DIR:
276    RRD_DIR = join(STORAGE_DIR, 'rrd/')
277if not STANDARD_DIRS:
278    try:
279        import whisper  # noqa
280        if os.path.exists(WHISPER_DIR):
281            STANDARD_DIRS.append(WHISPER_DIR)
282    except ImportError:
283        print("WARNING: whisper module could not be loaded, whisper support disabled", file=sys.stderr)
284    try:
285        import ceres  # noqa
286        if os.path.exists(CERES_DIR):
287            STANDARD_DIRS.append(CERES_DIR)
288    except ImportError:
289        pass
290    try:
291        import rrdtool  # noqa
292        if os.path.exists(RRD_DIR):
293            STANDARD_DIRS.append(RRD_DIR)
294    except ImportError:
295        pass
296
297if DATABASES is None:
298    DATABASES = {
299      'default': {
300        'NAME': join(STORAGE_DIR, 'graphite.db'),
301        'ENGINE': 'django.db.backends.sqlite3',
302        'USER': '',
303        'PASSWORD': '',
304        'HOST': '',
305        'PORT': '',
306      },
307    }
308
309# Handle URL prefix in static files handling
310if URL_PREFIX and not STATIC_URL.startswith(URL_PREFIX):
311    STATIC_URL = '/{0}{1}'.format(URL_PREFIX.strip('/'), STATIC_URL)
312
313# Default sqlite db file
314# This is set here so that a user-set STORAGE_DIR is available
315if 'sqlite3' in DATABASES.get('default',{}).get('ENGINE','') \
316        and not DATABASES.get('default',{}).get('NAME'):
317    DATABASES['default']['NAME'] = join(STORAGE_DIR, 'graphite.db')
318
319# Caching shortcuts
320if MEMCACHE_HOSTS:
321    CACHES['default'] = {
322        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
323        'LOCATION': MEMCACHE_HOSTS,
324        'TIMEOUT': DEFAULT_CACHE_DURATION,
325        'KEY_PREFIX': MEMCACHE_KEY_PREFIX,
326        'OPTIONS': MEMCACHE_OPTIONS,
327    }
328
329if not CACHES:
330    CACHES = {
331        'default': {
332            'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
333        },
334    }
335
336# Authentication shortcuts
337if USE_LDAP_AUTH and LDAP_URI is None:
338    LDAP_URI = "ldap://%s:%d/" % (LDAP_SERVER, LDAP_PORT)
339
340if USE_REMOTE_USER_AUTHENTICATION or REMOTE_USER_BACKEND:
341    if REMOTE_USER_MIDDLEWARE:
342        MIDDLEWARE += (REMOTE_USER_MIDDLEWARE,)
343    else:
344        MIDDLEWARE += ('django.contrib.auth.middleware.RemoteUserMiddleware',)
345    if DJANGO_VERSION < (1, 10):
346        MIDDLEWARE_CLASSES = MIDDLEWARE
347    if REMOTE_USER_BACKEND:
348        AUTHENTICATION_BACKENDS.insert(0,REMOTE_USER_BACKEND)
349    else:
350        AUTHENTICATION_BACKENDS.insert(0,'django.contrib.auth.backends.RemoteUserBackend')
351
352if USE_LDAP_AUTH:
353    AUTHENTICATION_BACKENDS.insert(0,'graphite.account.ldapBackend.LDAPBackend')
354
355if SECRET_KEY == 'UNSAFE_DEFAULT':
356    warn('SECRET_KEY is set to an unsafe default. This should be set in local_settings.py for better security')
357
358USE_TZ = True
359