milesmcc / shynet

Modern, privacy-friendly, and detailed web analytics that works without cookies or JS.
Apache License 2.0
2.93k stars 190 forks source link

Error 500 after daylight savings clock change #177

Open CasperVerswijvelt opened 3 years ago

CasperVerswijvelt commented 3 years ago

I'm getting an 'Error 500' when trying to visit the dashboard after a clock change for daylight savings time. Looking up the error gives me this description:

Exception raised when attempting to create an ambiguous wallclock time.

At the end of a DST transition period, a particular wallclock time will occur twice (once before the clocks are set back, once after). Both possibilities may be correct, unless further information is supplied.

See DstTzInfo.normalize() for more info

https://www.kite.com/python/docs/pytz.AmbiguousTimeError

Might look into this myself later, but wanted to report this issue asap.

Error log:

ERROR Internal Server Error: /dashboard/
Traceback (most recent call last):                                      
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)                                    
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 204, in _get_response
    response = response.render()                                        
  File "/usr/local/lib/python3.9/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content                                
  File "/usr/local/lib/python3.9/site-packages/django/template/response.py", line 83, in rendered_content
    return template.render(context, self._request)                      
  File "/usr/local/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)                                
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 170, in render
    return self._render(context)                                        
  File "/usr/local/lib/python3.9/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.9/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/defaulttags.py", line 211, in render
    nodelist.append(node.render_annotated(context))
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 195, in render
    return template.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 172, in render
    return self._render(context)
  File "/usr/local/lib/python3.9/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/defaulttags.py", line 516, in render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 195, in render
    return template.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 172, in render
    return self._render(context)
  File "/usr/local/lib/python3.9/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/defaulttags.py", line 514, in render
    values = {key: val.resolve(context) for key, val in self.extra_context.items()}
  File "/usr/local/lib/python3.9/site-packages/django/template/defaulttags.py", line 514, in <dictcomp>
    values = {key: val.resolve(context) for key, val in self.extra_context.items()}
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 671, in resolve
    obj = self.var.resolve(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 796, in resolve
    value = self._resolve_lookup(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 858, in _resolve_lookup
    current = current()
  File "/usr/src/shynet/core/models.py", line 106, in get_daily_stats
    return self.get_core_stats(
  File "/usr/src/shynet/core/models.py", line 116, in get_core_stats
    main_data = self.get_relative_stats(start_time, end_time)
  File "/usr/src/shynet/core/models.py", line 203, in get_relative_stats    chart_data, chart_tooltip_format, chart_granularity = self._get_chart_data(
  File "/usr/src/shynet/core/models.py", line 258, in _get_chart_data
    chart_data = {
  File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 280, in __iter__
    self._fetch_all()
  File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 1324, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 109, in __iter__
    for row in compiler.results_iter(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size):
  File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1122, in apply_converters
    value = converter(value, expression, connection)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/functions/datetime.py", line 246, in convert_value
    value = timezone.make_aware(value, self.tzinfo, is_dst=self.is_dst)
  File "/usr/local/lib/python3.9/site-packages/django/utils/timezone.py", line 239, in make_aware
    return timezone.localize(value, is_dst=is_dst)
  File "/usr/local/lib/python3.9/site-packages/pytz/tzinfo.py", line 363, in localize
    raise AmbiguousTimeError(dt)
pytz.exceptions.AmbiguousTimeError: 2021-10-31 02:00:00
milesmcc commented 3 years ago

Hmm good catch. Thanks for looking into it.

CasperVerswijvelt commented 3 years ago

This StackOverflow answer seems relevant: https://stackoverflow.com/a/21465529

I tried fixing the issue but I couldn't find where exactly I would put the suggested fix, since I'm not really the best with Django and stuff. If someone else could look at this that would be awesome.

CasperVerswijvelt commented 2 years ago

Since DST change is coming up in most countries (september/october) it might be a good time to look into this again ...

milesmcc commented 2 years ago

Good point. Per https://stackoverflow.com/questions/21465528/resolving-ambiguoustimeerror-from-djangos-make-aware, it seems like this is fixed in Django 4. So perhaps the easiest solution is to just get Shynet on Django 4! (Which is something I'd like to do anyway.)

Kovah commented 2 years ago

I just ran into this exact issue. After looking around in the Stack Overflow comments, a quick fix seems to be to set TIME_ZONE=UTC. Had this at TIME_ZONE=Europe/Berlin before.

xgaia commented 2 years ago

same here, fixed with TIME_ZONE=UTC instead of TIME_ZONE=Europe/Paris

milesmcc commented 2 years ago

Ugh, sorry you all had to fix this. Really I think we should just be using UTC everywhere — perhaps that's the best solution...