refactor(logging): migrate from CCLog to structured Logger

This commit is contained in:
2025-11-21 14:23:10 +08:00
parent 3287661318
commit cf7ddefc2e
3 changed files with 611 additions and 633 deletions

View File

@@ -1,4 +1,3 @@
import { CCLog, DAY, LogLevel } from "@/lib/ccLog";
import { ToastConfig, UserGroupConfig, loadConfig } from "./config"; import { ToastConfig, UserGroupConfig, loadConfig } from "./config";
import { createAccessControlCli } from "./cli"; import { createAccessControlCli } from "./cli";
import { launchAccessControlTUI } from "./tui"; import { launchAccessControlTUI } from "./tui";
@@ -7,14 +6,31 @@ import { ReadWriteLock } from "@/lib/mutex/ReadWriteLock";
import { ChatManager } from "@/lib/ChatManager"; import { ChatManager } from "@/lib/ChatManager";
import { gTimerManager } from "@/lib/TimerManager"; import { gTimerManager } from "@/lib/TimerManager";
import { KeyEvent, pullEventAs } from "@/lib/event"; import { KeyEvent, pullEventAs } from "@/lib/event";
import {
ConditionalStream,
ConsoleStream,
DAY,
FileStream,
Logger,
LogLevel,
processor,
textRenderer,
} from "@/lib/ccStructLog";
const args = [...$vararg]; const args = [...$vararg];
// Init Log // Init Log
const logger = new CCLog("accesscontrol.log", { let isOnConsoleStream = true;
printTerminal: true, const logger = new Logger({
logInterval: DAY, processors: [
outputMinLevel: LogLevel.Info, processor.filterByLevel(LogLevel.Info),
processor.addTimestamp(),
],
renderer: textRenderer,
streams: [
new ConditionalStream(new ConsoleStream(), () => isOnConsoleStream),
new FileStream("accesscontrol.log", DAY),
],
}); });
// Load Config // Load Config
@@ -203,7 +219,9 @@ function watchLoop() {
continue; continue;
} }
const watchPlayerNames = gWatchPlayersInfo.flatMap((value) => value.name); const watchPlayerNames = gWatchPlayersInfo.flatMap(
(value) => value.name,
);
logger.debug(`Watch Players [ ${watchPlayerNames.join(", ")} ]`); logger.debug(`Watch Players [ ${watchPlayerNames.join(", ")} ]`);
for (const player of gWatchPlayersInfo) { for (const player of gWatchPlayersInfo) {
const playerInfo = playerDetector.getPlayerPos(player.name); const playerInfo = playerDetector.getPlayerPos(player.name);
@@ -329,13 +347,15 @@ function keyboardLoop() {
if (event.key === keys.c) { if (event.key === keys.c) {
logger.info("Launching Access Control TUI..."); logger.info("Launching Access Control TUI...");
try { try {
logger.setInTerminal(false); isOnConsoleStream = false;
launchAccessControlTUI(); launchAccessControlTUI();
logger.info("TUI closed, resuming normal operation"); logger.info("TUI closed, resuming normal operation");
} catch (error) { } catch (error) {
logger.error(`TUI error: ${textutils.serialise(error as object)}`); logger.error(
`TUI error: ${textutils.serialise(error as object)}`,
);
} finally { } finally {
logger.setInTerminal(true); isOnConsoleStream = true;
reloadConfig(); reloadConfig();
} }
} else if (event.key === keys.r) { } else if (event.key === keys.r) {
@@ -379,7 +399,9 @@ function cliLoop() {
releaser = configLock.tryAcquireRead(); releaser = configLock.tryAcquireRead();
} }
const isAdmin = config.adminGroupConfig.groupUsers.includes(ev.username); const isAdmin = config.adminGroupConfig.groupUsers.includes(
ev.username,
);
releaser.release(); releaser.release();
if (!isAdmin) continue; if (!isAdmin) continue;
@@ -422,11 +444,14 @@ function main(args: string[]) {
return; return;
} else if (args[0] == "config") { } else if (args[0] == "config") {
logger.info("Launching Access Control TUI..."); logger.info("Launching Access Control TUI...");
logger.setInTerminal(false); isOnConsoleStream = false;
try { try {
launchAccessControlTUI(); launchAccessControlTUI();
} catch (error) { } catch (error) {
logger.error(`TUI error: ${textutils.serialise(error as object)}`); logger.error(
`TUI error: ${textutils.serialise(error as object)}`,
);
} }
return; return;
} }

View File

@@ -3,10 +3,23 @@ import {
CraftRecipe, CraftRecipe,
CreatePackageTag, CreatePackageTag,
} from "@/lib/CraftManager"; } from "@/lib/CraftManager";
import { CCLog, LogLevel } from "@/lib/ccLog";
import { Queue } from "@/lib/datatype/Queue"; import { Queue } from "@/lib/datatype/Queue";
import {
ConsoleStream,
Logger,
LogLevel,
processor,
textRenderer,
} from "@/lib/ccStructLog";
const logger = new CCLog("autocraft.log", { outputMinLevel: LogLevel.Info }); const logger = new Logger({
processors: [
processor.filterByLevel(LogLevel.Info),
processor.addFullTimestamp(),
],
renderer: textRenderer,
streams: [new ConsoleStream()],
});
const peripheralsNames = { const peripheralsNames = {
// packsInventory: "minecraft:chest_14", // packsInventory: "minecraft:chest_14",
@@ -103,17 +116,20 @@ function main() {
logger.debug( logger.debug(
`Turtle:\n${textutils.serialise(blockReader.getBlockData()!, { allow_repetitions: true })}`, `Turtle:\n${textutils.serialise(blockReader.getBlockData()!, { allow_repetitions: true })}`,
); );
const packageDetailInfo = blockReader.getBlockData()?.Items[1]; const packageDetailInfo =
blockReader.getBlockData()?.Items[1];
if (packageDetailInfo === undefined) { if (packageDetailInfo === undefined) {
logger.error(`Package detail info not found`); logger.error(`Package detail info not found`);
continue; continue;
} }
// Get OrderId and isFinal // Get OrderId and isFinal
const packageOrderId = (packageDetailInfo.tag as CreatePackageTag) const packageOrderId = (
.Fragment.OrderId; packageDetailInfo.tag as CreatePackageTag
).Fragment.OrderId;
const packageIsFinal = const packageIsFinal =
(packageDetailInfo.tag as CreatePackageTag).Fragment.IsFinal > 0 (packageDetailInfo.tag as CreatePackageTag).Fragment
.IsFinal > 0
? true ? true
: false; : false;
@@ -121,11 +137,21 @@ function main() {
const packageRecipes = const packageRecipes =
CraftManager.getPackageRecipe(packageDetailInfo); CraftManager.getPackageRecipe(packageDetailInfo);
if (packageRecipes.isSome()) { if (packageRecipes.isSome()) {
if (packageIsFinal) recipesQueue.enqueue(packageRecipes.value); if (packageIsFinal)
else recipesWaitingMap.set(packageOrderId, packageRecipes.value); recipesQueue.enqueue(packageRecipes.value);
else
recipesWaitingMap.set(
packageOrderId,
packageRecipes.value,
);
} else { } else {
if (packageIsFinal && recipesWaitingMap.has(packageOrderId)) { if (
recipesQueue.enqueue(recipesWaitingMap.get(packageOrderId)!); packageIsFinal &&
recipesWaitingMap.has(packageOrderId)
) {
recipesQueue.enqueue(
recipesWaitingMap.get(packageOrderId)!,
);
recipesWaitingMap.delete(packageOrderId); recipesWaitingMap.delete(packageOrderId);
} else { } else {
logger.debug(`No recipe, just pass`); logger.debug(`No recipe, just pass`);
@@ -166,7 +192,8 @@ function main() {
}); });
if (craftCnt == 0) break; if (craftCnt == 0) break;
if (craftCnt < maxSignleCraftCnt) maxSignleCraftCnt = craftCnt; if (craftCnt < maxSignleCraftCnt)
maxSignleCraftCnt = craftCnt;
const craftRet = craftManager.craft(maxSignleCraftCnt); const craftRet = craftManager.craft(maxSignleCraftCnt);
craftItemDetail ??= craftRet; craftItemDetail ??= craftRet;
logger.info(`Craft ${craftCnt} times`); logger.info(`Craft ${craftCnt} times`);

View File

@@ -7,56 +7,16 @@
import { import {
Logger, Logger,
createDevLogger, processor,
createProdLogger,
// Processors
addTimestamp,
addFormattedTimestamp,
addFullTimestamp,
addSource,
addComputerId,
addStaticFields,
transformField,
// Renderers
textRenderer,
jsonRenderer,
// Streams
ConsoleStream, ConsoleStream,
FileStream, FileStream,
BufferStream, BufferStream,
DAY, ConditionalStream,
HOUR, HOUR,
jsonRenderer,
LogLevel, LogLevel,
textRenderer,
} from "../lib/ccStructLog"; } from "../lib/ccStructLog";
import { ConditionalStream } from "@/lib/ccStructLog/streams";
// =============================================================================
// Basic Usage Examples
// =============================================================================
print("=== Basic Usage Examples ===");
// 1. Quick start with pre-configured loggers
const devLog = createDevLogger();
devLog.info("Application started", { version: "1.0.0", port: 8080 });
devLog.debug("Debug information", { userId: 123, action: "login" });
devLog.error("Something went wrong", {
error: "Connection failed",
retries: 3,
});
// 2. Production logging to file
const prodLog = createProdLogger("app.log", {
source: "MyApplication",
rotationInterval: DAY,
includeConsole: true,
});
prodLog.info("User action", { userId: 456, action: "purchase", amount: 29.99 });
prodLog.warn("Low disk space", { available: 1024, threshold: 2048 });
// ============================================================================= // =============================================================================
// Custom Logger Configurations // Custom Logger Configurations
@@ -67,10 +27,10 @@ print("\n=== Custom Logger Configurations ===");
// 4. Custom logger with specific processors and renderer // 4. Custom logger with specific processors and renderer
const customLogger = new Logger({ const customLogger = new Logger({
processors: [ processors: [
addFullTimestamp(), processor.addTimestamp(),
addComputerId(), processor.addComputerId(),
addSource("CustomApp"), processor.addSource("CustomApp"),
addStaticFields({ processor.addStaticFields({
environment: "development", environment: "development",
version: "2.1.0", version: "2.1.0",
}), }),
@@ -109,10 +69,10 @@ const sanitizePasswords = (event: Map<string, unknown>) => {
const secureLogger = new Logger({ const secureLogger = new Logger({
processors: [ processors: [
addTimestamp(), processor.addTimestamp(),
addRequestId, addRequestId,
sanitizePasswords, sanitizePasswords,
transformField("message", (msg) => `[SECURE] ${msg}`), processor.transformField("message", (msg) => `[SECURE] ${msg}`),
], ],
renderer: jsonRenderer, renderer: jsonRenderer,
streams: [new ConsoleStream()], streams: [new ConsoleStream()],
@@ -133,7 +93,7 @@ print("\n=== Stream Examples ===");
// 11. Buffer stream for batch processing // 11. Buffer stream for batch processing
const bufferStream = new BufferStream(100); // Keep last 100 messages const bufferStream = new BufferStream(100); // Keep last 100 messages
const bufferLogger = new Logger({ const bufferLogger = new Logger({
processors: [addFormattedTimestamp()], processors: [processor.addTimestamp()],
renderer: textRenderer, renderer: textRenderer,
streams: [ streams: [
new ConditionalStream(new ConsoleStream(), (msg, event) => { new ConditionalStream(new ConsoleStream(), (msg, event) => {
@@ -162,7 +122,7 @@ for (const msg of bufferedMessages) {
// 12. Multi-stream with different formats // 12. Multi-stream with different formats
const multiFormatLogger = new Logger({ const multiFormatLogger = new Logger({
processors: [addFullTimestamp(), addComputerId()], processors: [processor.addTimestamp(), processor.addComputerId()],
renderer: (event) => "default", // This won't be used renderer: (event) => "default", // This won't be used
streams: [ streams: [
// Console with human-readable format // Console with human-readable format
@@ -196,7 +156,7 @@ print("\n=== Error Handling Examples ===");
// 13. Robust error handling // 13. Robust error handling
const robustLogger = new Logger({ const robustLogger = new Logger({
processors: [ processors: [
addTimestamp(), processor.addTimestamp(),
// Processor that might fail // Processor that might fail
(event) => { (event) => {
try { try {
@@ -231,7 +191,7 @@ print("\n=== Cleanup Examples ===");
// 14. Proper cleanup // 14. Proper cleanup
const fileLogger = new Logger({ const fileLogger = new Logger({
processors: [addTimestamp()], processors: [processor.addTimestamp()],
renderer: jsonRenderer, renderer: jsonRenderer,
streams: [new FileStream("temp.log")], streams: [new FileStream("temp.log")],
}); });
@@ -249,37 +209,3 @@ print("- all.log (complete log)");
print("- debug.log (detailed debug info)"); print("- debug.log (detailed debug info)");
print("- structured.log (JSON format)"); print("- structured.log (JSON format)");
print("- temp.log (temporary file, now closed)"); print("- temp.log (temporary file, now closed)");
// =============================================================================
// Performance Comparison (commented out to avoid noise)
// =============================================================================
/*
print("\n=== Performance Comparison ===");
const iterations = 1000;
// Test simple console logging
const startTime1 = os.clock();
const simpleLogger = createMinimalLogger();
for (let i = 0; i < iterations; i++) {
simpleLogger.info(`Simple message ${i}`);
}
const endTime1 = os.clock();
print(`Simple Console Logger: ${endTime1 - startTime1} seconds`);
// Test complex processor chain
const startTime2 = os.clock();
const complexLogger = createDetailedLogger("perf_test.log", {
source: "PerfTest"
});
for (let i = 0; i < iterations; i++) {
complexLogger.info(`Complex message ${i}`, {
iteration: i,
data: { nested: { value: i * 2 } }
});
}
complexLogger.close();
const endTime2 = os.clock();
print(`Complex Processor Chain: ${endTime2 - startTime2} seconds`);
*/