RikaCelery 1905f0503f
在非ansi环境强制显示进度条等信息 (#327)
* 添加自定义Console,可强制以ansi模式输出

* 添加 `--force-ansi-console` 以在非ansi环境显示进度信息

* 添加用于移除ANSI颜色的 `--noansi`

* 只去除颜色和指针移动

* 使用系统默认输出编码

* 不重复输出,修复错误的正则替换,补充一个过滤

* 移除在NoAnsi环境下的无用输出

* force console width to max

* add escape sequence `\e[?25h`

* remove spinner for HTTPLiveRecordManager.cs and SimpleDownloadManager.cs when `--noansi`

* camelCase

* rename variable

* auto enable `--no-ansi` and `--force-ansi-console` when out/err redirected

* avoid null reference

* format code and clean up

* capitalize word `ANSI`

---------

Co-authored-by: RikaCelery <celeryfx@outlook.com>
2024-06-30 12:16:00 +08:00

244 lines
7.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Spectre.Console;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;
namespace N_m3u8DL_RE.Common.Log
{
public partial class Logger
{
[GeneratedRegex("{}")]
private static partial Regex VarsRepRegex();
/// <summary>
/// 日志级别默认为INFO
/// </summary>
public static LogLevel LogLevel { get; set; } = LogLevel.INFO;
/// <summary>
/// 是否写出日志文件
/// </summary>
public static bool IsWriteFile { get; set; } = true;
/// <summary>
/// 本次运行日志文件所在位置
/// </summary>
private static string? LogFilePath { get; set; }
//读写锁
static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
public static void InitLogFile()
{
if (!IsWriteFile) return;
try
{
var logDir = Path.GetDirectoryName(Environment.ProcessPath) + "/Logs";
if (!Directory.Exists(logDir))
{
Directory.CreateDirectory(logDir);
}
LogFilePath = Path.Combine(logDir, DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss-fff") + ".log");
//若文件存在则加序号
int index = 1;
var fileName = Path.GetFileNameWithoutExtension(LogFilePath);
while (File.Exists(LogFilePath))
{
LogFilePath = Path.Combine(Path.GetDirectoryName(LogFilePath)!, $"{fileName}-{index++}.log");
}
string now = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
string init = "LOG " + DateTime.Now.ToString("yyyy/MM/dd") + Environment.NewLine
+ "Save Path: " + Path.GetDirectoryName(LogFilePath) + Environment.NewLine
+ "Task Start: " + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + Environment.NewLine
+ "Task CommandLine: " + Environment.CommandLine;
init += $"{Environment.NewLine}{Environment.NewLine}";
File.WriteAllText(LogFilePath, init, Encoding.UTF8);
}
catch (Exception ex)
{
Error($"Init log failed! {ex.Message.RemoveMarkup()}");
}
}
private static string GetCurrTime()
{
return DateTime.Now.ToString("HH:mm:ss.fff");
}
private static void HandleLog(string write, string subWrite = "")
{
try
{
if (subWrite == "")
{
CustomAnsiConsole.MarkupLine(write);
}
else
{
CustomAnsiConsole.Markup(write);
Console.WriteLine(subWrite);
}
if (IsWriteFile && File.Exists(LogFilePath))
{
var plain = write.RemoveMarkup() + subWrite.RemoveMarkup();
try
{
//进入写入
LogWriteLock.EnterWriteLock();
using (StreamWriter sw = File.AppendText(LogFilePath))
{
sw.WriteLine(plain);
}
}
finally
{
//释放占用
LogWriteLock.ExitWriteLock();
}
}
}
catch (Exception)
{
Console.WriteLine("Failed to write: " + write);
}
}
private static string ReplaceVars(string data, params object[] ps)
{
for (int i = 0; i < ps.Length; i++)
{
data = VarsRepRegex().Replace(data, $"{ps[i]}", 1);
}
return data;
}
public static void Info(string data, params object[] ps)
{
if (LogLevel >= LogLevel.INFO)
{
data = ReplaceVars(data, ps);
var write = GetCurrTime() + " " + "[underline #548c26]INFO[/] : ";
HandleLog(write, data);
}
}
public static void InfoMarkUp(string data, params object[] ps)
{
if (LogLevel >= LogLevel.INFO)
{
data = ReplaceVars(data, ps);
var write = GetCurrTime() + " " + "[underline #548c26]INFO[/] : " + data;
HandleLog(write);
}
}
public static void Debug(string data, params object[] ps)
{
if (LogLevel >= LogLevel.DEBUG)
{
data = ReplaceVars(data, ps);
var write = GetCurrTime() + " " + "[underline grey]DEBUG[/]: ";
HandleLog(write, data);
}
}
public static void DebugMarkUp(string data, params object[] ps)
{
if (LogLevel >= LogLevel.DEBUG)
{
data = ReplaceVars(data, ps);
var write = GetCurrTime() + " " + "[underline grey]DEBUG[/]: " + data;
HandleLog(write);
}
}
public static void Warn(string data, params object[] ps)
{
if (LogLevel >= LogLevel.WARN)
{
data = ReplaceVars(data, ps);
var write = GetCurrTime() + " " + "[underline #a89022]WARN[/] : ";
HandleLog(write, data);
}
}
public static void WarnMarkUp(string data, params object[] ps)
{
if (LogLevel >= LogLevel.WARN)
{
data = ReplaceVars(data, ps);
var write = GetCurrTime() + " " + "[underline #a89022]WARN[/] : " + data;
HandleLog(write);
}
}
public static void Error(string data, params object[] ps)
{
if (LogLevel >= LogLevel.ERROR)
{
data = ReplaceVars(data, ps);
var write = GetCurrTime() + " " + "[underline red1]ERROR[/]: ";
HandleLog(write, data);
}
}
public static void ErrorMarkUp(string data, params object[] ps)
{
if (LogLevel >= LogLevel.ERROR)
{
data = ReplaceVars(data, ps);
var write = GetCurrTime() + " " + "[underline red1]ERROR[/]: " + data;
HandleLog(write);
}
}
public static void ErrorMarkUp(Exception exception)
{
string data = exception.Message.EscapeMarkup();
if (LogLevel >= LogLevel.ERROR)
{
data = exception.ToString().EscapeMarkup();
}
ErrorMarkUp(data);
}
/// <summary>
/// This thing will only write to the log file.
/// </summary>
/// <param name="data"></param>
/// <param name="ps"></param>
public static void Extra(string data, params object[] ps)
{
if (IsWriteFile && File.Exists(LogFilePath))
{
data = ReplaceVars(data, ps);
var plain = GetCurrTime() + " " + "EXTRA: " + data.RemoveMarkup();
try
{
//进入写入
LogWriteLock.EnterWriteLock();
using (StreamWriter sw = File.AppendText(LogFilePath))
{
sw.WriteLine(plain, Encoding.UTF8);
}
}
finally
{
//释放占用
LogWriteLock.ExitWriteLock();
}
}
}
}
}