675ab26a6e
Phase 5 — ERP Features: - CREATE VIEW name AS SELECT ... — parser + executor with view expansion - DROP VIEW — parser + executor - CREATE MIGRATION name AS 'sql' — parser + executor, stored in LSM-Tree - APPLY MIGRATION name — parser + executor, replays stored migration SQL - Views table in ExecutionContext, expanded on SELECT FROM view Phase 6 — Production Readiness: - Deadlock detection: timeout-based auto-abort for stale transactions (30s default) - TxnManager.txnTimeoutMs configurable - Structured JSON logging module (logging.nim) with levels: debug/info/warn/error - Admin dashboard Web UI at GET /admin — SQL playground, schema browser, metrics - Dark theme HTML/CSS with tabs Lexer: added tkView, tkMigration, tkApply tokens Parser: parseCreateView, parseDropView, parseCreateMigration, parseApplyMigration AST: nkCreateView, nkDropView, nkCreateMigration, nkApplyMigration nodes All 216 tests pass
50 lines
1.2 KiB
Nim
50 lines
1.2 KiB
Nim
## BaraDB Structured JSON Logger
|
|
import std/json
|
|
import std/times
|
|
import std/os
|
|
|
|
type
|
|
LogLevel* = enum
|
|
llDebug = 0
|
|
llInfo = 1
|
|
llWarn = 2
|
|
llError = 3
|
|
|
|
Logger* = ref object
|
|
level*: LogLevel
|
|
output*: File
|
|
|
|
var defaultLogger* = Logger(level: llInfo, output: stdout)
|
|
|
|
proc newLogger*(level: LogLevel = llInfo, filepath: string = ""): Logger =
|
|
var f = stdout
|
|
if filepath.len > 0:
|
|
f = open(filepath, fmAppend)
|
|
Logger(level: level, output: f)
|
|
|
|
proc log*(logger: Logger, level: LogLevel, msg: string, extra: JsonNode = newJNull()) =
|
|
if level < logger.level: return
|
|
let entry = %*{
|
|
"ts": $now(),
|
|
"level": $level,
|
|
"msg": msg,
|
|
"extra": extra
|
|
}
|
|
logger.output.writeLine($entry)
|
|
logger.output.flushFile()
|
|
|
|
proc log*(msg: string, level: LogLevel = llInfo) =
|
|
defaultLogger.log(level, msg)
|
|
|
|
proc debug*(msg: string) = defaultLogger.log(llDebug, msg)
|
|
proc info*(msg: string) = defaultLogger.log(llInfo, msg)
|
|
proc warn*(msg: string) = defaultLogger.log(llWarn, msg)
|
|
proc errorMsg*(msg: string) = defaultLogger.log(llError, msg)
|
|
|
|
proc setLevel*(logger: Logger, level: LogLevel) =
|
|
logger.level = level
|
|
|
|
proc close*(logger: Logger) =
|
|
if logger.output != stdout:
|
|
logger.output.close()
|