之前都是用java开发,换成asp.net,没有实时的日志输出监控,总是感觉很不方便,由于项目中采用的日志组件是log4net,就直接写个小的基于控制台的udp客户端接收log4net的日志消息,嗯,这回方便多了。
log4net的udp配置
<appender name="UdpAppender" type="log4net.Appender.UdpAppender">
<remoteAddress value="127.0.0.1"/>
<remotePort value="60001"/>
<encoding value="UTF-8"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%d{HH:mm:ss}] [%-5p] - %m%n"/>
</layout>
</appender>
log4net客户端接收代码,使用方式 log4netudpsvr 60001
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Text.RegularExpressions;
namespace log4netudpsvr {
class Program {
//log4net配置范例说明
private const string SIMPLE_TEXT =
@"<appender name=""UdpAppender"" type=""log4net.Appender.UdpAppender"">
<remoteAddress value=""127.0.0.1""/>
<remotePort value=""60001""/>
<encoding value=""UTF-8""/>
<layout type=""log4net.Layout.PatternLayout"">
<conversionPattern value=""[%d{HH:mm:ss}] [%-5p] - %m%n""/>
</layout>
</appender>";
//解析日志格式的正则表达式
private readonly Regex m_log_re = new Regex(@"(^\[.+?\]) (\[.+?\])([\s\S]*)$");
private Socket m_server_socket; //监听端口返回的socket
private EndPoint m_epSender; //接受数据的客户端套接字信息
private byte[] m_recive_data = new byte[65536]; //udp数据接受缓冲区
private ConsoleColor m_fg, m_bg; //缺省的控制台前景色与背景色
public static Program Instance { get; private set; }
static void Main(string[] args) {
/*
string s = "字符串";
foreach (var item in Enum.GetValues(typeof(ConsoleColor))) {
Console.WriteLine();
Console.WriteLine();
foreach (var sub_item in Enum.GetValues(typeof(ConsoleColor))) {
Console.BackgroundColor = (ConsoleColor)item;
Console.ForegroundColor = (ConsoleColor)sub_item;
Console.Write("[背景={0},前景={1}]", item.ToString(), sub_item.ToString());
Console.ForegroundColor = ConsoleColor.White;
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\t");
}
}
*/
if (args.Length == 0) { //无参数时显示帮助
Usage();
return;
}
try {
var port = int.Parse(args[0]); //解析用户输入的port参数
if (port < 1 || port > 65535) {
Console.WriteLine("port incorrect,must in 1-65535.");
return;
}
Instance = new Program();
Instance.StartListen(port); //启动监听服务
}
catch (Exception) {
Console.WriteLine("can't parse port number.");
}
}
static void Usage() { //使用帮助函数
Console.WriteLine();
Console.WriteLine("Usage: {0} <port>",
AppDomain.CurrentDomain.SetupInformation.ApplicationName);
Console.WriteLine();
Console.WriteLine("log4net config simple:");
Console.WriteLine(SIMPLE_TEXT);
}
private void ResetColor() { //恢复控制台缺省的前景色和背景色
Console.ForegroundColor = m_fg;
Console.BackgroundColor = m_bg;
}
private void StartListen(int port) { //启动监听服务
m_fg = Console.ForegroundColor;
m_bg = Console.BackgroundColor;
try {
m_server_socket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
IPEndPoint server = new IPEndPoint(IPAddress.Any, port);
m_server_socket.Bind(server); //绑定udp指定端口
IPEndPoint client = new IPEndPoint(IPAddress.Any, 0);
m_epSender = (EndPoint)client;
//异步通讯方式接受udp数据
m_server_socket.BeginReceiveFrom(m_recive_data, 0,
m_recive_data.Length, SocketFlags.None,
ref m_epSender, new AsyncCallback(ReceiveData), m_epSender);
Console.WriteLine("listening port {0} ...", port);
Console.WriteLine("please input \"quit\" to exit program.", port);
var cmd = "";
//接受用户输入,防止控制台程序自动关闭
while (cmd != "quit") cmd = Console.ReadLine();
}
catch (System.Exception ex) {
Console.WriteLine("can't listen udp port {0}.", port);
Console.WriteLine(ex.ToString());
return;
}
}
private void ReceiveData(IAsyncResult ar) {
int recv_len = 0;
try {
recv_len = m_server_socket.EndReceiveFrom(ar, ref m_epSender);
}
catch (Exception e) {
ResetColor();
Console.WriteLine(e.ToString());
}
//对接受的数据进行utf8转码
string recv_text = Encoding.UTF8.GetString(m_recive_data, 0, recv_len);
OnAppendLog(recv_text); //调用日志的控制台输出函数
if (m_server_socket != null) //再次启动异步回调接受udp数据
m_server_socket.BeginReceiveFrom(m_recive_data, 0, m_recive_data.Length,
SocketFlags.None, ref m_epSender, new AsyncCallback(ReceiveData), m_epSender);
}
private void OnAppendLog(string logMsg) {
var m = m_log_re.Match(logMsg);
if (!m.Success) { //不是log4net发来的日志,直接显示在控制台
ResetColor();
Console.WriteLine((logMsg));
return;
}
//显示时间字段
Write(ConsoleColor.Gray, ConsoleColor.DarkGreen, m.Groups[1].ToString());
Write(m_fg, m_bg, " ");
//显示日志级别
var level = m.Groups[2].ToString();
var msg = m.Groups[3].ToString();
if (level == "[DEBUG]") {
Write(ConsoleColor.Gray, ConsoleColor.DarkCyan, level);
Write(ConsoleColor.Gray, m_bg, msg);
}
else if (level == "[INFO ]") {
Write(ConsoleColor.Gray, ConsoleColor.DarkBlue, level);
Write(ConsoleColor.DarkGreen, m_bg, msg);
}
else if (level == "[WARN ]") {
Write(ConsoleColor.Gray, ConsoleColor.DarkYellow, level);
Write(ConsoleColor.DarkYellow, m_bg, msg);
}
else if (level == "[ERROR]") {
Write(ConsoleColor.Gray, ConsoleColor.DarkRed, level);
Write(ConsoleColor.Red, m_bg, msg);
}
else if (level == "[FATAL]") {
Write(ConsoleColor.Gray, ConsoleColor.DarkMagenta, level);
Write(ConsoleColor.DarkMagenta, m_bg, msg);
}
else {
Write(ConsoleColor.Blue, ConsoleColor.DarkRed, level);
Write(ConsoleColor.Yellow, ConsoleColor.DarkRed, msg);
}
//Write(m_fg, m_bg, "\n");
}
private void Write(ConsoleColor fg, ConsoleColor bg, string text) {
Console.ForegroundColor = fg;
Console.BackgroundColor = bg;
Console.Write(text);
}
}
}