use local timezone in log messages; closes #96

timezone can be changed with `export TZ=Europe/Oslo` before launch

using naive timestamps like this appears to be safe as of 3.13-rc1,
no deprecation warnings, just a tiny bit slower than assuming UTC
This commit is contained in:
ed 2024-09-05 19:31:33 +00:00
parent a8dabc99f6
commit b599fbae97
6 changed files with 28 additions and 42 deletions

View file

@ -1285,6 +1285,7 @@ def add_logging(ap):
ap2.add_argument("--ansi", action="store_true", help="force colors; overrides environment-variable NO_COLOR") ap2.add_argument("--ansi", action="store_true", help="force colors; overrides environment-variable NO_COLOR")
ap2.add_argument("--no-logflush", action="store_true", help="don't flush the logfile after each write; tiny bit faster") ap2.add_argument("--no-logflush", action="store_true", help="don't flush the logfile after each write; tiny bit faster")
ap2.add_argument("--no-voldump", action="store_true", help="do not list volumes and permissions on startup") ap2.add_argument("--no-voldump", action="store_true", help="do not list volumes and permissions on startup")
ap2.add_argument("--log-utc", action="store_true", help="do not use local timezone; assume the TZ env-var is UTC (tiny bit faster)")
ap2.add_argument("--log-tdec", metavar="N", type=int, default=3, help="timestamp resolution / number of timestamp decimals") ap2.add_argument("--log-tdec", metavar="N", type=int, default=3, help="timestamp resolution / number of timestamp decimals")
ap2.add_argument("--log-badpwd", metavar="N", type=int, default=1, help="log failed login attempt passwords: 0=terse, 1=plaintext, 2=hashed") ap2.add_argument("--log-badpwd", metavar="N", type=int, default=1, help="log failed login attempt passwords: 0=terse, 1=plaintext, 2=hashed")
ap2.add_argument("--log-conn", action="store_true", help="debug: print tcp-server msgs") ap2.add_argument("--log-conn", action="store_true", help="debug: print tcp-server msgs")

View file

@ -3,7 +3,6 @@ from __future__ import print_function, unicode_literals
import argparse import argparse
import base64 import base64
import calendar
import errno import errno
import gzip import gzip
import logging import logging
@ -16,7 +15,7 @@ import string
import sys import sys
import threading import threading
import time import time
from datetime import datetime, timedelta from datetime import datetime
# from inspect import currentframe # from inspect import currentframe
# print(currentframe().f_lineno) # print(currentframe().f_lineno)
@ -104,6 +103,7 @@ class SvcHub(object):
self.argv = argv self.argv = argv
self.E: EnvParams = args.E self.E: EnvParams = args.E
self.no_ansi = args.no_ansi self.no_ansi = args.no_ansi
self.tz = UTC if args.log_utc else None
self.logf: Optional[typing.TextIO] = None self.logf: Optional[typing.TextIO] = None
self.logf_base_fn = "" self.logf_base_fn = ""
self.is_dut = False # running in unittest; always False self.is_dut = False # running in unittest; always False
@ -118,7 +118,8 @@ class SvcHub(object):
self.httpsrv_up = 0 self.httpsrv_up = 0
self.log_mutex = threading.Lock() self.log_mutex = threading.Lock()
self.next_day = 0 self.cday = 0
self.cmon = 0
self.tstack = 0.0 self.tstack = 0.0
self.iphash = HMaccas(os.path.join(self.E.cfg, "iphash"), 8) self.iphash = HMaccas(os.path.join(self.E.cfg, "iphash"), 8)
@ -791,7 +792,7 @@ class SvcHub(object):
self.args.nc = min(self.args.nc, soft // 2) self.args.nc = min(self.args.nc, soft // 2)
def _logname(self) -> str: def _logname(self) -> str:
dt = datetime.now(UTC) dt = datetime.now(self.tz)
fn = str(self.args.lo) fn = str(self.args.lo)
for fs in "YmdHMS": for fs in "YmdHMS":
fs = "%" + fs fs = "%" + fs
@ -1064,12 +1065,12 @@ class SvcHub(object):
return return
with self.log_mutex: with self.log_mutex:
zd = datetime.now(UTC) dt = datetime.now(self.tz)
ts = self.log_dfmt % ( ts = self.log_dfmt % (
zd.year, dt.year,
zd.month * 100 + zd.day, dt.month * 100 + dt.day,
(zd.hour * 100 + zd.minute) * 100 + zd.second, (dt.hour * 100 + dt.minute) * 100 + dt.second,
zd.microsecond // self.log_div, dt.microsecond // self.log_div,
) )
if c and not self.args.no_ansi: if c and not self.args.no_ansi:
@ -1090,41 +1091,26 @@ class SvcHub(object):
if not self.args.no_logflush: if not self.args.no_logflush:
self.logf.flush() self.logf.flush()
now = time.time() if dt.day != self.cday or dt.month != self.cmon:
if int(now) >= self.next_day: self._set_next_day(dt)
self._set_next_day()
def _set_next_day(self) -> None: def _set_next_day(self, dt: datetime) -> None:
if self.next_day and self.logf and self.logf_base_fn != self._logname(): if self.cday and self.logf and self.logf_base_fn != self._logname():
self.logf.close() self.logf.close()
self._setup_logfile("") self._setup_logfile("")
dt = datetime.now(UTC) self.cday = dt.day
self.cmon = dt.month
# unix timestamp of next 00:00:00 (leap-seconds safe)
day_now = dt.day
while dt.day == day_now:
dt += timedelta(hours=12)
dt = dt.replace(hour=0, minute=0, second=0)
try:
tt = dt.utctimetuple()
except:
# still makes me hella uncomfortable
tt = dt.timetuple()
self.next_day = calendar.timegm(tt)
def _log_enabled(self, src: str, msg: str, c: Union[int, str] = 0) -> None: def _log_enabled(self, src: str, msg: str, c: Union[int, str] = 0) -> None:
"""handles logging from all components""" """handles logging from all components"""
with self.log_mutex: with self.log_mutex:
now = time.time() dt = datetime.now(self.tz)
if int(now) >= self.next_day: if dt.day != self.cday or dt.month != self.cmon:
dt = datetime.fromtimestamp(now, UTC)
zs = "{}\n" if self.no_ansi else "\033[36m{}\033[0m\n" zs = "{}\n" if self.no_ansi else "\033[36m{}\033[0m\n"
zs = zs.format(dt.strftime("%Y-%m-%d")) zs = zs.format(dt.strftime("%Y-%m-%d"))
print(zs, end="") print(zs, end="")
self._set_next_day() self._set_next_day(dt)
if self.logf: if self.logf:
self.logf.write(zs) self.logf.write(zs)
@ -1143,12 +1129,11 @@ class SvcHub(object):
else: else:
msg = "%s%s\033[0m" % (c, msg) msg = "%s%s\033[0m" % (c, msg)
zd = datetime.fromtimestamp(now, UTC)
ts = self.log_efmt % ( ts = self.log_efmt % (
zd.hour, dt.hour,
zd.minute, dt.minute,
zd.second, dt.second,
zd.microsecond // self.log_div, dt.microsecond // self.log_div,
) )
msg = fmt % (ts, src, msg) msg = fmt % (ts, src, msg)
try: try:

View file

@ -8,7 +8,7 @@ LABEL org.opencontainers.image.url="https://github.com/9001/copyparty" \
ENV XDG_CONFIG_HOME=/cfg ENV XDG_CONFIG_HOME=/cfg
RUN apk --no-cache add !pyc \ RUN apk --no-cache add !pyc \
wget \ tzdata wget \
py3-jinja2 py3-argon2-cffi py3-pillow \ py3-jinja2 py3-argon2-cffi py3-pillow \
ffmpeg ffmpeg

View file

@ -11,7 +11,7 @@ COPY i/bin/mtag/install-deps.sh ./
COPY i/bin/mtag/audio-bpm.py /mtag/ COPY i/bin/mtag/audio-bpm.py /mtag/
COPY i/bin/mtag/audio-key.py /mtag/ COPY i/bin/mtag/audio-key.py /mtag/
RUN apk add -U !pyc \ RUN apk add -U !pyc \
wget \ tzdata wget \
py3-jinja2 py3-argon2-cffi py3-pillow py3-pip py3-cffi \ py3-jinja2 py3-argon2-cffi py3-pillow py3-pip py3-cffi \
ffmpeg \ ffmpeg \
vips-jxl vips-heif vips-poppler vips-magick \ vips-jxl vips-heif vips-poppler vips-magick \

View file

@ -8,7 +8,7 @@ LABEL org.opencontainers.image.url="https://github.com/9001/copyparty" \
ENV XDG_CONFIG_HOME=/cfg ENV XDG_CONFIG_HOME=/cfg
RUN apk --no-cache add !pyc \ RUN apk --no-cache add !pyc \
wget \ tzdata wget \
py3-jinja2 py3-argon2-cffi py3-pillow py3-mutagen py3-jinja2 py3-argon2-cffi py3-pillow py3-mutagen
COPY i/dist/copyparty-sfx.py innvikler.sh ./ COPY i/dist/copyparty-sfx.py innvikler.sh ./

View file

@ -8,7 +8,7 @@ LABEL org.opencontainers.image.url="https://github.com/9001/copyparty" \
ENV XDG_CONFIG_HOME=/cfg ENV XDG_CONFIG_HOME=/cfg
RUN apk add -U !pyc \ RUN apk add -U !pyc \
wget \ tzdata wget \
py3-jinja2 py3-argon2-cffi py3-pillow py3-pip py3-cffi \ py3-jinja2 py3-argon2-cffi py3-pillow py3-pip py3-cffi \
ffmpeg \ ffmpeg \
vips-jxl vips-heif vips-poppler vips-magick \ vips-jxl vips-heif vips-poppler vips-magick \