Skip to content

Commit

Permalink
Merge branch '1.1.x' into backport/1.1.x/pr-2785
Browse files Browse the repository at this point in the history
  • Loading branch information
deniszh authored Feb 19, 2023
2 parents 4b88d95 + 9585590 commit a6f3c27
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 7 deletions.
2 changes: 1 addition & 1 deletion docs/config-webapp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ Finally, configure the nginx vhost:
listen 80;
location /static/ {
alias /opt/graphite/webapp/content/;
alias /opt/graphite/webapp/content/
}
location / {
Expand Down
5 changes: 4 additions & 1 deletion docs/terminology.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ terms mean in the context of Graphite.

metric series
See :term:`series`

node
An element of the name of a :term:`series` separated by periods (``.``).

precision
See :term:`resolution`
Expand All @@ -35,7 +38,7 @@ terms mean in the context of Graphite.

series
A named set of datapoints. A series is identified by a unique name, which is composed of
elements separated by periods (``.``) which are used to display the collection of series
elements (each, a :term:`node`) separated by periods (``.``) which are used to display the collection of series
into a hierarchical tree. A series storing system load average on a server called ``apache02``
in datacenter ``metro_east`` might be named as ``metro_east.servers.apache02.system.load_average``

Expand Down
3 changes: 2 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ deps =
git+https://github.com/graphite-project/ceres.git#egg=ceres
Django<3.2.99
pyparsing: pyparsing>=2.3.0,<3.0.0
Sphinx<1.4
alabaster==0.7.12
Sphinx==1.3.6
jinja2<3.1.0
sphinx_rtd_theme
urllib3
Expand Down
12 changes: 10 additions & 2 deletions webapp/graphite/render/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4002,9 +4002,11 @@ def holtWintersDeviation(gamma,actual,prediction,last_seasonal_dev):
def holtWintersAnalysis(series, seasonality='1d'):
alpha = gamma = 0.1
beta = 0.0035
# season is currently one day
seasonality_time = parseTimeOffset(seasonality)
season_length = (seasonality_time.seconds + (seasonality_time.days * 86400)) // series.step
# season_length should be 2 or more
if season_length < 2:
season_length = 2
intercept = 0
slope = 0
intercepts = list()
Expand Down Expand Up @@ -5100,7 +5102,10 @@ def applyByNode(requestContext, seriesList, nodeNum, templateFunction, newName=N
"""
prefixes = set()
for series in seriesList:
prefix = '.'.join(series.name.split('.')[:nodeNum + 1])
nodes = series.name.split('.')
if nodeNum >= len(nodes):
raise InputParameterError("{} do not contans {} nodes".format(series.name, nodeNum))
prefix = '.'.join(nodes[:nodeNum + 1])
prefixes.add(prefix)
results = []
newContext = requestContext.copy()
Expand Down Expand Up @@ -5391,6 +5396,9 @@ def summarize(requestContext, seriesList, intervalString, func='sum', alignToFro


def _summarizeValues(series, func, interval, newStart=None, newEnd=None):
if interval == 0:
raise InputParameterError("_summarizeValues(): interval parsed to 0")

if newStart is None:
newStart = series.start
if newEnd is None:
Expand Down
34 changes: 33 additions & 1 deletion webapp/tests/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
except ImportError: # Django < 1.10
from django.core.urlresolvers import reverse

from graphite.errors import NormalizeEmptyResultError
from graphite.errors import NormalizeEmptyResultError, InputParameterError
from graphite.functions import _SeriesFunctions, loadFunctions, safe
from graphite.render.datalib import TimeSeries
from graphite.render import functions
Expand Down Expand Up @@ -4522,6 +4522,38 @@ def mock_data_fetcher(reqCtx, path_expression):
)
self.assertEqual(result, expectedResults)

@patch('graphite.render.evaluator.prefetchData', lambda *_: None)
def test_applyByNode_Overflow(self):
seriesList = self._gen_series_list_with_data(
key=['servers.s1.disk.bytes_used', 'servers.s1.disk.bytes_free','servers.s2.disk.bytes_used','servers.s2.disk.bytes_free'],
start=0,
end=3,
data=[[10, 20, 30], [90, 80, 70], [1, 2, 3], [99, 98, 97]]
)

def mock_data_fetcher(reqCtx, path_expression):
rv = []
for s in seriesList:
if s.name == path_expression or fnmatch(s.name, path_expression):
rv.append(s)
if rv:
return rv
raise KeyError('{} not found!'.format(path_expression))

with patch('graphite.render.evaluator.fetchData', mock_data_fetcher):
try:
functions.applyByNode(
self._build_requestContext(
startTime=datetime(1970, 1, 1, 0, 0, 0, 0, pytz.timezone(settings.TIME_ZONE)),
endTime=datetime(1970, 1, 1, 0, 9, 0, 0, pytz.timezone(settings.TIME_ZONE))
),
seriesList, 4,
'divideSeries(%.disk.bytes_used, sumSeries(%.disk.bytes_*))'
)
self.fail('must raise with InputParameterError')
except InputParameterError:
pass

@patch('graphite.render.evaluator.prefetchData', lambda *_: None)
def test_applyByNode_newName(self):
seriesList = self._gen_series_list_with_data(
Expand Down
3 changes: 2 additions & 1 deletion webapp/tests/test_readers_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ def test_MultiReader_get_intervals(self):
reader = MultiReader([node1, node2])
intervals = reader.get_intervals()
for interval in intervals:
self.assertEqual(int(interval.start), self.start_ts - 60)
self.assertIn(int(interval.start), [self.start_ts - 60, self.start_ts - 60 - 1])
self.assertIn(int(interval.end), [self.start_ts, self.start_ts - 1])
self.assertIn(int(interval.end - interval.start), [59,60])

# Confirm fetch works.
def test_MultiReader_fetch(self):
Expand Down
42 changes: 42 additions & 0 deletions webapp/tests/test_xss.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import logging
import sys

try:
from django.urls import reverse
except ImportError: # Django < 1.10
from django.core.urlresolvers import reverse

from .base import TestCase

# Silence logging during tests
LOGGER = logging.getLogger()

# logging.NullHandler is a python 2.7ism
if hasattr(logging, "NullHandler"):
LOGGER.addHandler(logging.NullHandler())

if sys.version_info[0] >= 3:
def resp_text(r):
return r.content.decode('utf-8')
else:
def resp_text(r):
return r.content


class RenderXSSTest(TestCase):
def test_render_xss(self):
url = reverse('render')
xssStr = '<noscript><p title="</noscript><img src=x onerror=alert() onmouseover=alert()>">'

# Check for issue #2779 and others
response = self.client.get(url, {'target': 'test', 'format': 'raw', 'cacheTimeout': xssStr, 'from': xssStr})
self.assertXSS(response, status_code=400, msg_prefix='XSS detected: ')


class FindXSSTest(TestCase):
def test_render_xss(self):
url = reverse('metrics_find')
xssStr = '<noscript><p title="</noscript><img src=x onerror=alert() onmouseover=alert()>">'

response = self.client.get(url, {'query': 'test', 'local': xssStr, 'from': xssStr, 'tz': xssStr})
self.assertXSS(response, status_code=400, msg_prefix='XSS detected: ')

0 comments on commit a6f3c27

Please sign in to comment.