feat: add configurable logging level for backend and Mini App

- Introduced a new `LOG_LEVEL` configuration option in the `.env.example` file to allow users to set the logging level (DEBUG, INFO, WARNING, ERROR).
- Updated the `Settings` class to include the `log_level` attribute, normalizing its value to ensure valid logging levels are used.
- Modified the logging setup in `run.py` to utilize the configured log level, enhancing flexibility in log management.
- Enhanced the Mini App to include the logging level in the JavaScript configuration, allowing for consistent logging behavior across the application.
- Added a new `logger.js` module for frontend logging, implementing level-based filtering and console delegation.
- Included unit tests for the new logger functionality to ensure proper behavior and level handling.
This commit is contained in:
2026-03-02 23:15:22 +03:00
parent 67ba9826c7
commit 43386b15fa
16 changed files with 226 additions and 15 deletions

View File

@@ -6,6 +6,7 @@ import { FETCH_TIMEOUT_MS } from "./constants.js";
import { getInitData } from "./auth.js";
import { state } from "./dom.js";
import { t } from "./i18n.js";
import { logger } from "./logger.js";
/**
* Build fetch options with init data header, Accept-Language and timeout abort.
@@ -49,10 +50,17 @@ export async function apiGet(path, params = {}, options = {}) {
const query = new URLSearchParams(params).toString();
const url = query ? `${base}${path}?${query}` : `${base}${path}`;
const initData = getInitData();
logger.debug("API request", path, params);
const opts = buildFetchOptions(initData, options.signal);
try {
const res = await fetch(url, { headers: opts.headers, signal: opts.signal });
if (!res.ok) {
logger.warn("API non-OK response", path, res.status);
}
return res;
} catch (e) {
logger.error("API request failed", path, e);
throw e;
} finally {
opts.cleanup();
}
@@ -69,6 +77,7 @@ export async function apiGet(path, params = {}, options = {}) {
export async function fetchDuties(from, to, signal) {
const res = await apiGet("/api/duties", { from, to }, { signal });
if (res.status === 403) {
logger.warn("Access denied", from, to);
let detail = t(state.lang, "access_denied");
try {
const body = await res.json();