using System;
using System.Collections.Concurrent;
namespace Aivfo.OperationLog
{
///
/// 组件配置(14§10 可配置)。集中持有,支持运行时改(热生效简化为:直接改属性即下次记日志生效)。
/// 模块级开关:默认全开,可按模块名设 开/关 + 最低级别。
///
public sealed class OperationLogOptions
{
/// 端/服务名(project 字段),如 "operate" / "front"。
public string Project { get; set; } = "operate";
/// Kafka 地址,如 "localhost:9092"。
public string KafkaBootstrapServers { get; set; } = "localhost:9092";
/// Kafka topic。
public string Topic { get; set; } = "tl-oplog";
/// 全局总开关。关掉则完全不记(连入队都跳过)。
public bool Enabled { get; set; } = true;
///
/// 全局最低级别。低于此级别的日志不发 Kafka。
/// 默认 Info:只发操作级;调试级(Debug)默认走本地文件、不入 Kafka。
///
public OpLogLevel GlobalLevel { get; set; } = OpLogLevel.Info;
/// 内存队列上限。满了走降级(丢弃 Debug / 落本地兜底)。
public int QueueCapacity { get; set; } = 10000;
/// 后台发送批量大小。
public int BatchSize { get; set; } = 100;
/// 本地文件目录(调试级 + 兜底)。
public string LocalLogDir { get; set; } = "oplog_local";
/// 设备上下文:培养箱 SN(可选,作为全局默认)。
public string TlSn { get; set; }
/// 本机 host(默认取机器名)。
public string Host { get; set; } = SafeMachineName();
// 模块级开关:moduleName -> (enabled, minLevel)。缺省即全开、按 GlobalLevel。
private readonly ConcurrentDictionary _modules =
new ConcurrentDictionary();
/// 设置某模块的开关与最低级别(运行时可调,热生效)。
public void SetModule(string module, bool enabled, OpLogLevel minLevel = OpLogLevel.Info)
{
if (string.IsNullOrEmpty(module)) return;
_modules[module] = new ModuleSetting { Enabled = enabled, MinLevel = minLevel };
}
/// 判断某模块是否启用(总开关 + 模块开关)。关闭则连本地调试文件也不写。
public bool IsModuleEnabled(string module)
{
if (!Enabled) return false;
if (!string.IsNullOrEmpty(module) && _modules.TryGetValue(module, out var s))
return s.Enabled;
return true;
}
///
/// 判断某模块某级别是否应**发 Kafka 入库**(操作级门槛)。
/// 调试级(Debug)天然低于 Info,故默认不发 Kafka、走本地文件——这是 14§4 两级设计。
/// 要让某模块的调试级也入库(很少用),把该模块 MinLevel 设为 Debug。
///
public bool ShouldSendKafka(string module, OpLogLevel level)
{
if (!IsModuleEnabled(module)) return false;
if (!string.IsNullOrEmpty(module) && _modules.TryGetValue(module, out var s))
return level >= s.MinLevel;
return level >= GlobalLevel;
}
private static string SafeMachineName()
{
try { return Environment.MachineName; }
catch { return "unknown"; }
}
private sealed class ModuleSetting
{
public bool Enabled;
public OpLogLevel MinLevel;
}
}
}