Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default to UTC #68

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 14 additions & 17 deletions meshinfo/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def configure(
filters = settings.setdefault("jinja2.filters", {})
filters.setdefault("duration", "meshinfo.filters.duration")
filters.setdefault("in_tz", "meshinfo.filters.in_tz")
filters.setdefault("local_tz", "meshinfo.filters.local_tz")
filters.setdefault("client_tz", "meshinfo.filters.client_tz")

if app_config.env == Environment.DEV:
settings["pyramid.reload_all"] = True
Expand Down Expand Up @@ -185,23 +185,20 @@ def configure(
if app_config.env == Environment.DEV:
config.include("pyramid_debugtoolbar")

server_timezone = pendulum.tz.local_timezone()

def client_timezone(request):
if "local_tz" in request.cookies:
try:
client_tz = pendulum.timezone(request.cookies["local_tz"])
except Exception as exc:
# TODO: identify client?
logger.warning(
"Invalid timezone specified: {} ({!r})",
request.cookies["local_tz"],
exc,
)
client_tz = server_timezone
return client_tz.name
else:
return server_timezone.name
if "client_tz" not in request.cookies:
return pendulum.timezone("UTC")
try:
client_tz = pendulum.timezone(request.cookies["client_tz"])
except Exception as exc:
# TODO: identify client?
logger.warning(
"Invalid timezone specified: {} ({!r})",
request.cookies["client_tz"],
exc,
)
client_tz = pendulum.timezone("UTC")
return client_tz

config.add_request_method(lambda r: client_timezone(r), "timezone", reify=True)

Expand Down
2 changes: 1 addition & 1 deletion meshinfo/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ def in_tz(dt, tz="utc"):


@jinja2.pass_context
def local_tz(ctx, dt):
def client_tz(ctx, dt):
request = ctx.get("request") or get_current_request()
return dt.in_tz(request.timezone).format("YYYY-MM-DD HH:mm:ss zz")
36 changes: 25 additions & 11 deletions meshinfo/historical.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import enum
import os
from itertools import cycle
from pathlib import Path
from typing import Any, Iterable, List, Optional
Expand Down Expand Up @@ -132,6 +133,7 @@ def graph_network_stats(
self,
*,
params: GraphParams,
timezone: str,
) -> bytes:
"""Graph network poller statistics."""
rrd_file = self._network_filename()
Expand All @@ -150,9 +152,9 @@ def graph_network_stats(
legend=ds.replace("_count", "s"),
)

return graph.render()
return graph.render(timezone=timezone)

def graph_poller_stats(self, *, params: GraphParams) -> bytes:
def graph_poller_stats(self, *, params: GraphParams, timezone: str) -> bytes:
"""Graph network info."""
rrd_file = self._network_filename()
colors = cycle(COLORS)
Expand All @@ -170,13 +172,14 @@ def graph_poller_stats(self, *, params: GraphParams) -> bytes:
style="LINE1",
legend=ds.replace("_time", ""),
)
return graph.render()
return graph.render(timezone=timezone)

def graph_node_uptime(
self,
node: Node,
*,
params: GraphParams,
timezone: str,
) -> bytes:
"""Graph node uptime."""
rrd_file = self._node_filename(node)
Expand All @@ -193,13 +196,14 @@ def graph_node_uptime(
style="AREA",
legend="uptime",
)
return graph.render()
return graph.render(timezone=timezone)

def graph_node_load(
self,
node: Node,
*,
params: GraphParams,
timezone: str,
) -> bytes:
"""Graph node uptime."""
rrd_file = self._node_filename(node)
Expand All @@ -216,13 +220,14 @@ def graph_node_load(
style="LINE1",
legend="load",
)
return graph.render()
return graph.render(timezone=timezone)

def graph_node_links(
self,
node: Node,
*,
params: GraphParams,
timezone: str,
) -> bytes:
"""Graph node links."""
rrd_file = self._node_filename(node)
Expand Down Expand Up @@ -256,13 +261,14 @@ def graph_node_links(
style="LINE1",
)

return graph.render()
return graph.render(timezone=timezone)

def graph_link_cost(
self,
link: Link,
*,
params: GraphParams,
timezone: str,
) -> bytes:
"""Graph link routing cost."""

Expand All @@ -278,13 +284,14 @@ def graph_link_cost(
style="LINE1",
legend="route cost",
)
return graph.render()
return graph.render(timezone=timezone)

def graph_link_snr(
self,
link: Link,
*,
params: GraphParams,
timezone: str,
) -> bytes:
"""Graph node uptime."""
# TODO: add a black line at 0 so it stands out
Expand Down Expand Up @@ -316,13 +323,14 @@ def graph_link_snr(
style="LINE1",
legend="noise",
)
return graph.render()
return graph.render(timezone=timezone)

def graph_link_quality(
self,
link: Link,
*,
params: GraphParams,
timezone: str,
) -> bytes:
"""Graph link quality and neighbor quality."""

Expand All @@ -347,7 +355,7 @@ def graph_link_quality(
style="LINE1",
legend="neighbor",
)
return graph.render()
return graph.render(timezone=timezone)

def update_link_stats(self, link: Link) -> bool:
# switch to async after testing!
Expand Down Expand Up @@ -590,8 +598,8 @@ def add_summarized_ds(
)
self.elements[-1] += r"\l"

def render(self) -> bytes:
"""Draw the graph via RRDtool."""
def render(self, *, timezone: str) -> bytes:
"""Draw the graph via RRDtool in a particular timezone."""

self.options.extend(("--start", self.start))
if self.end:
Expand All @@ -616,5 +624,11 @@ def render(self) -> bytes:
)
logger.trace("Rendering graph: {}", graphv_args)

current_timezone = os.getenv("TZ")
os.environ["TZ"] = timezone
graph_info = rrdtool.graphv(*graphv_args)
if current_timezone is None:
del os.environ["TZ"]
else:
os.environ["TZ"] = current_timezone
return graph_info["image"]
2 changes: 1 addition & 1 deletion meshinfo/templates/home.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<div class="column is-narrow">
<div class="mb-2">
<div class="heading">Last Ran</div>
<div>{{ last_run.started_at|local_tz }}</div>
<div>{{ last_run.started_at|client_tz }}</div>
</div>
<div class="mb-2">
<div class="heading">Polling Time</div>
Expand Down
6 changes: 3 additions & 3 deletions meshinfo/templates/network-errors.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@

{% block content %}
<div class="container is-fluid">
<h1 class="title">Node Polling Errors at {{ stats.started_at|local_tz }}</h1>
<h1 class="title">Node Polling Errors at {{ stats.started_at|client_tz }}</h1>
<div class="content">
<div class="columns container">
<div class="column">
<div class="mb-2">
<div class="heading">Started At</div>
<div>{{ stats.started_at|local_tz }}</div>
<div>{{ stats.started_at|client_tz }}</div>
</div>
<div class="mb-2">
<div class="heading">Finished At</div>
<div>{{ stats.finished_at|local_tz }}</div>
<div>{{ stats.finished_at|client_tz }}</div>
</div>
</div>
<div class="column">
Expand Down
4 changes: 2 additions & 2 deletions meshinfo/templates/node-details.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
</div>
<div class="mb-2">
<div class="heading">Last Seen</div>
<div>{{ node.last_seen|local_tz }}</div>
<div>{{ node.last_seen|client_tz }}</div>
</div>
<div class="mb-2">
<a href="http://{{ node.name }}.local.mesh:8080" target="_blank" rel="noopener noreferrer">AREDN Page</a>
Expand Down Expand Up @@ -153,7 +153,7 @@
</div>
<div class="mb-2">
<div class="heading">Last Seen</div>
<div>{{ link.last_seen|local_tz }}</div>
<div>{{ link.last_seen|client_tz }}</div>
</div>
</div>
<div class="column is-narrow">
Expand Down
2 changes: 1 addition & 1 deletion meshinfo/templates/nodes.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
'{{ node.active_tunnel_count }}',
'{{ node.firmware_version }}',
'{{ node.up_time }}',
'{{ node.last_seen|local_tz }}'
'{{ node.last_seen|client_tz }}'
]{% if not loop.last %},{% endif %}
{% endfor %}
],
Expand Down
16 changes: 13 additions & 3 deletions meshinfo/views/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def __init__(self, request: Request):
self.graph_params = schema.graph_params(request.GET)

self.stats: HistoricalStats = request.find_service(HistoricalStats)
self.timezone: str = request.timezone.name

@view_config(match_param="name=cost")
def cost_graph(self):
Expand All @@ -114,8 +115,11 @@ def cost_graph(self):
self.graph_params.title,
)
self.graph_params.title = " - ".join(part for part in title_parts if part)
graph_data = self.stats.graph_link_cost(
self.link, params=self.graph_params, timezone=self.timezone
)
return Response(
self.stats.graph_link_cost(self.link, params=self.graph_params),
graph_data,
status="200 OK",
content_type="image/png",
)
Expand All @@ -128,8 +132,11 @@ def snr_graph(self):
self.graph_params.title,
)
self.graph_params.title = " - ".join(part for part in title_parts if part)
graph_data = self.stats.graph_link_snr(
self.link, params=self.graph_params, timezone=self.timezone
)
return Response(
self.stats.graph_link_snr(self.link, params=self.graph_params),
graph_data,
status="200 OK",
content_type="image/png",
)
Expand All @@ -142,8 +149,11 @@ def quality_graph(self):
self.graph_params.title,
)
self.graph_params.title = " - ".join(part for part in title_parts if part)
graph_data = self.stats.graph_link_quality(
self.link, params=self.graph_params, timezone=self.timezone
)
return Response(
self.stats.graph_link_quality(self.link, params=self.graph_params),
graph_data,
status="200 OK",
content_type="image/png",
)
13 changes: 9 additions & 4 deletions meshinfo/views/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class NetworkGraphs:
def __init__(self, request: Request):
self.graph_params = schema.graph_params(request.GET)
self.stats: HistoricalStats = request.find_service(HistoricalStats)
self.timezone: str = request.timezone.name

@view_config(match_param="name=info")
def info(self):
Expand All @@ -35,9 +36,11 @@ def info(self):
self.graph_params.title,
)
self.graph_params.title = " - ".join(part for part in title_parts if part)

graph_data = self.stats.graph_network_stats(
params=self.graph_params, timezone=self.timezone
)
return Response(
self.stats.graph_network_stats(params=self.graph_params),
graph_data,
status="200 OK",
content_type="image/png",
)
Expand All @@ -49,9 +52,11 @@ def poller(self):
self.graph_params.title,
)
self.graph_params.title = " - ".join(part for part in title_parts if part)

graph_data = self.stats.graph_poller_stats(
params=self.graph_params, timezone=self.timezone
)
return Response(
self.stats.graph_poller_stats(params=self.graph_params),
graph_data,
status="200 OK",
content_type="image/png",
)
Expand Down
16 changes: 13 additions & 3 deletions meshinfo/views/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ def __init__(self, request: Request):
self.name_in_title = asbool(request.GET.get("name_in_title", False))

self.stats: HistoricalStats = request.find_service(HistoricalStats)
self.timezone: str = request.timezone.name

@view_config(match_param="name=links")
def links(self):
Expand All @@ -135,8 +136,11 @@ def links(self):
self.graph_params.title,
)
self.graph_params.title = " - ".join(part for part in title_parts if part)
graph_data = self.stats.graph_node_links(
self.node, params=self.graph_params, timezone=self.timezone
)
return Response(
self.stats.graph_node_links(self.node, params=self.graph_params),
graph_data,
status="200 OK",
content_type="image/png",
)
Expand All @@ -149,8 +153,11 @@ def load(self):
self.graph_params.title,
)
self.graph_params.title = " - ".join(part for part in title_parts if part)
graph_data = self.stats.graph_node_load(
self.node, params=self.graph_params, timezone=self.timezone
)
return Response(
self.stats.graph_node_load(self.node, params=self.graph_params),
graph_data,
status="200 OK",
content_type="image/png",
)
Expand All @@ -163,8 +170,11 @@ def uptime(self):
self.graph_params.title,
)
self.graph_params.title = " - ".join(part for part in title_parts if part)
graph_data = self.stats.graph_node_uptime(
self.node, params=self.graph_params, timezone=self.timezone
)
return Response(
self.stats.graph_node_uptime(self.node, params=self.graph_params),
graph_data,
status="200 OK",
content_type="image/png",
)