【ELK_Log4net】.net Core重写一个TcpAppender
最近搞了下ELK,三个工具部署完毕,想再集成上log4net。没想到.net core版Log4net竟然没有直接Tcp发送消息的appender。醉了。log4net

1.RemotingAppender:core已经不支持。
2.RemoteSysLogAppender:只监听 udp的514端口。【原文:The BSD syslog protocol is used to remotely log to a syslog daemon. The syslogd listens for for messages on UDP port 514.】
3.UdpAppender:udp协议传输数据
4.TelnetAppender:一开始以为肯定是这个可以用了。官网没有examples。。科学上网翻了config。里面竟然只有port配置没有remotingAddress等(黑人问号)???。官网解释这个东西怎么玩的【原文:The TelnetAppender accepts socket connections and streams logging messages back to the client. The output is provided in a telnet-friendly way so that a log can be monitored over a TCP/IP socket. This allows simple remote monitoring of application logging.】
也就是它是开了一个监听。监听别人给他发的日志数据,然后记录数据然后再发回去。。。What???。我要的是你发出去。混蛋。下面去反编译看看他的源码。。
namespace log4net.Appender
{
public class TelnetAppender : AppenderSkeleton
{
private static readonly Type declaringType = typeof (TelnetAppender);
private int m_listeningPort = ;
private TelnetAppender.SocketHandler m_handler; public int Port
{
get
{
return this.m_listeningPort;
}
set
{
if (value < || value > (int) ushort.MaxValue)
throw SystemInfo.CreateArgumentOutOfRangeException("value", (object) value, "The value specified for Port is less than " + .ToString((IFormatProvider) NumberFormatInfo.InvariantInfo) + " or greater than " + ((int) ushort.MaxValue).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo) + ".");
this.m_listeningPort = value;
}
} protected override bool RequiresLayout
{
get
{
return true;
}
} protected override void OnClose()
{
base.OnClose();
if (this.m_handler == null)
return;
this.m_handler.Dispose();
this.m_handler = (TelnetAppender.SocketHandler) null;
} public override void ActivateOptions()
{
base.ActivateOptions();
try
{
LogLog.Debug(TelnetAppender.declaringType, "Creating SocketHandler to listen on port [" + (object) this.m_listeningPort + "]");
this.m_handler = new TelnetAppender.SocketHandler(this.m_listeningPort);
}
catch (Exception ex)
{
LogLog.Error(TelnetAppender.declaringType, "Failed to create SocketHandler", ex);
throw;
}
} protected override void Append(LoggingEvent loggingEvent)
{
if (this.m_handler == null || !this.m_handler.HasConnections)
return;
this.m_handler.Send(this.RenderLoggingEvent(loggingEvent));
} protected class SocketHandler : IDisposable
{
private ArrayList m_clients = new ArrayList();
private const int MAX_CONNECTIONS = ;
private Socket m_serverSocket; public bool HasConnections
{
get
{
ArrayList clients = this.m_clients;
if (clients != null)
return clients.Count > ;
return false;
}
} public SocketHandler(int port)
{
this.m_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.m_serverSocket.Bind((EndPoint) new IPEndPoint(IPAddress.Any, port));
this.m_serverSocket.Listen();
this.AcceptConnection();
} private void AcceptConnection()
{
this.m_serverSocket.AcceptAsync().ContinueWith(new Action<Task<Socket>>(this.OnConnect), TaskScheduler.Default);
} public void Send(string message)
{
foreach (TelnetAppender.SocketHandler.SocketClient client in this.m_clients)
{
try
{
client.Send(message);
}
catch (Exception ex)
{
client.Dispose();
this.RemoveClient(client);
}
}
} private void AddClient(TelnetAppender.SocketHandler.SocketClient client)
{
TelnetAppender.SocketHandler socketHandler = this;
bool lockTaken = false;
try
{
Monitor.Enter((object) socketHandler, ref lockTaken);
ArrayList arrayList = (ArrayList) this.m_clients.Clone();
arrayList.Add((object) client);
this.m_clients = arrayList;
}
finally
{
if (lockTaken)
Monitor.Exit((object) socketHandler);
}
} private void RemoveClient(TelnetAppender.SocketHandler.SocketClient client)
{
TelnetAppender.SocketHandler socketHandler = this;
bool lockTaken = false;
try
{
Monitor.Enter((object) socketHandler, ref lockTaken);
ArrayList arrayList = (ArrayList) this.m_clients.Clone();
arrayList.Remove((object) client);
this.m_clients = arrayList;
}
finally
{
if (lockTaken)
Monitor.Exit((object) socketHandler);
}
} private void OnConnect(Task<Socket> acceptTask)
{
try
{
Socket result = acceptTask.GetAwaiter().GetResult();
LogLog.Debug(TelnetAppender.declaringType, "Accepting connection from [" + result.RemoteEndPoint.ToString() + "]");
TelnetAppender.SocketHandler.SocketClient client = new TelnetAppender.SocketHandler.SocketClient(result);
int count = this.m_clients.Count;
if (count < )
{
try
{
client.Send("TelnetAppender v1.0 (" + (object) (count + ) + " active connections)\r\n\r\n");
this.AddClient(client);
}
catch
{
client.Dispose();
}
}
else
{
client.Send("Sorry - Too many connections.\r\n");
client.Dispose();
}
}
catch
{
}
finally
{
if (this.m_serverSocket != null)
this.AcceptConnection();
}
} public void Dispose()
{
foreach (TelnetAppender.SocketHandler.SocketClient client in this.m_clients)
client.Dispose();
this.m_clients.Clear();
Socket serverSocket = this.m_serverSocket;
this.m_serverSocket = (Socket) null;
try
{
serverSocket.Shutdown(SocketShutdown.Both);
}
catch
{
}
try
{
CompatibilityExtensions.Close(serverSocket);
}
catch
{
}
} protected class SocketClient : IDisposable
{
private Socket m_socket;
private StreamWriter m_writer; public SocketClient(Socket socket)
{
this.m_socket = socket;
try
{
this.m_writer = new StreamWriter((Stream) new NetworkStream(socket));
}
catch
{
this.Dispose();
throw;
}
} public void Send(string message)
{
this.m_writer.Write(message);
this.m_writer.Flush();
} public void Dispose()
{
try
{
if (this.m_writer != null)
{
CompatibilityExtensions.Close(this.m_writer);
this.m_writer = (StreamWriter) null;
}
}
catch
{
}
if (this.m_socket == null)
return;
try
{
this.m_socket.Shutdown(SocketShutdown.Both);
}
catch
{
}
try
{
CompatibilityExtensions.Close(this.m_socket);
}
catch
{
}
this.m_socket = (Socket) null;
}
}
}
}
}
那就没办法。。我自己再重写一个直接发送的TcpAppender吧。。写法是完全看udpAppender源码改的。暴露出来的配置和udp基本一致。把local的去除了
internal class TcpAppender : AppenderSkeleton
{
private Encoding _encoding = Encoding.Unicode;
private IPAddress _remoteAddress;
private int _remotePort;
private IPEndPoint _remoteEndPoint;
private TcpClient _client; public IPAddress RemoteAddress
{
get
{
return this._remoteAddress;
}
set
{
this._remoteAddress = value;
}
} public int RemotePort
{
get
{
return this._remotePort;
}
set
{
if (value < || value > (int)ushort.MaxValue)
throw SystemInfo.CreateArgumentOutOfRangeException("value", (object)value, "The value specified is less than " + .ToString((IFormatProvider)NumberFormatInfo.InvariantInfo) + " or greater than " + ((int)ushort.MaxValue).ToString((IFormatProvider)NumberFormatInfo.InvariantInfo) + ".");
this._remotePort = value;
}
} public Encoding Encoding
{
get
{
return this._encoding;
}
set
{
this._encoding = value;
}
} protected TcpClient Client
{
get
{
return this._client;
}
set
{
this._client = value;
}
} protected IPEndPoint RemoteEndPoint
{
get
{
return this._remoteEndPoint;
}
set
{
this._remoteEndPoint = value;
}
} protected override bool RequiresLayout
{
get
{
return true;
}
} public override void ActivateOptions()
{
base.ActivateOptions();
if (this.RemoteAddress == null)
throw new ArgumentNullException("The required property 'Address' was not specified.");
if (this.RemotePort < || this.RemotePort > (int)ushort.MaxValue)
throw SystemInfo.CreateArgumentOutOfRangeException("this.RemotePort", (object)this.RemotePort, "The RemotePort is less than " + .ToString((IFormatProvider)NumberFormatInfo.InvariantInfo) + " or greater than " + ((int)ushort.MaxValue).ToString((IFormatProvider)NumberFormatInfo.InvariantInfo) + ".");
this.RemoteEndPoint = new IPEndPoint(this.RemoteAddress, this.RemotePort);
this.InitializeClientConnection();
} protected override void Append(LoggingEvent loggingEvent)
{
try
{
NetworkStream ntwStream = this.Client.GetStream();
var aa = this.RenderLoggingEvent(loggingEvent).ToCharArray();
byte[] bytes = this._encoding.GetBytes(this.RenderLoggingEvent(loggingEvent).ToCharArray());
ntwStream.Write(bytes, , bytes.Length);
}
catch (Exception ex)
{
this.ErrorHandler.Error("Unable to send logging event to remote host " + this.RemoteAddress.ToString() + " on port " + (object)this.RemotePort + ".", ex, ErrorCode.WriteFailure);
}
} protected override void OnClose()
{
base.OnClose();
if (this.Client == null)
return;
Client.Dispose();
this.Client = null;
} protected virtual void InitializeClientConnection()
{
try
{
this.Client = new TcpClient(this.RemoteAddress.ToString(), this.RemotePort);
}
catch (Exception ex)
{
this.ErrorHandler.Error("Could not initialize the UdpClient connection on port " + this.RemotePort.ToString((IFormatProvider)NumberFormatInfo.InvariantInfo) + ".", ex, ErrorCode.GenericFailure);
this.Client = null;
}
}
}
用法代码。里面额外加入了一个consoleAppender 方便查看调试
static void Main(string[] args)
{
Test();
Console.ReadKey();
} private static void Test()
{
var repo = LogManager.CreateRepository("R"); var layout = new PatternLayout()
{
ConversionPattern = "#%date #%level #%message#",
};
var tcpAppender = new TcpAppender
{
Encoding = Encoding.UTF8,
RemoteAddress = new IPAddress(new byte[] { ,,, }),
RemotePort = ,
Layout = layout
};
var consoleAppender = new ConsoleAppender
{
Layout = layout
};
layout.ActivateOptions();
tcpAppender.ActivateOptions();
BasicConfigurator.Configure(repo, consoleAppender,tcpAppender); ILog log = LogManager.GetLogger(repo.Name, "Debug");
log.Info("");
Console.ReadKey();
}
下面是成功发送到虚拟机上的kibana的后台显示。部分数据和字段没匹配好是logstash的规则和log4net规则没对应好

【ELK_Log4net】.net Core重写一个TcpAppender的更多相关文章
- ASP.NET Core重写个人博客站点小结
今天用ASP.NET Core重写了个人博客站点,原来是基于ASP.NET 4.5开发的.重写工作总体很顺利,最后成功发布到Ubunt+Nginx平台上.效果如下: 右边的Header信息里可以看到已 ...
- 使用ASP.NET Core MVC 和 Entity Framework Core 开发一个CRUD(增删改查)的应用程序
使用ASP.NET Core MVC 和 Entity Framework Core 开发一个CRUD(增删改查)的应用程序 不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻 ...
- NopCommerce用core重写ef
最近看了NopCommerce源码,用core学习着写了一个项目,修改的地方记录下.项目地址 NopCommerce框架出来好久了.18年的第一季度 懒加载出来后也会全部移动到.net core.那么 ...
- NopCommerce用.net core重写ef
最近看了NopCommerce源码,用core学习着写了一个项目,修改的地方记录下.项目地址 NopCommerce框架出来好久了.18年的第一季度 懒加载出来后也会全部移动到.net core.那么 ...
- 自定义View(7)官方教程:自定义View(含onMeasure),自定义一个Layout(混合组件),重写一个现有组件
Custom Components In this document The Basic Approach Fully Customized Components Compound Controls ...
- .NET Core跨平台:使用.NET Core开发一个初心源商城总括
1..NET Core基本介绍 a 作为一个.NET的开发者,在以前的开发中,我们开发的项目基本都是部署在windows服务器上,但是在windows服务器上的话某些比较流行的解决访问量的方案基本都是 ...
- Object-C的类可以多重继承吗?可以实现多个接口吗?category是什么?重写一个类的方式用继承好还是分类好,为什么?
Object-C的类可以多重继承吗?可以实现多个接口吗?category是什么?重写一个类的方式用继承好还是分类好,为什么? 答:Object-c的类不可以多重继承,可以实现多个接口(协议),Cate ...
- RecyclerView.Adapter封装,最简单实用的BaseRecyclerViewAdapter;只需重写一个方法,设置数据链式调用;
之前对ListView的BaseAdapter进行过封装,只需重写一个getView方法: 现在慢慢的RecyclerView成为主流,下面是RecyclerView.Adapter的封装: Base ...
- 给 asp.net core 写一个简单的健康检查
给 asp.net core 写一个简单的健康检查 Intro 健康检查可以帮助我们知道应用的当前状态是不是处于良好状态,现在无论是 docker 还是 k8s 还是现在大多数的服务注册发现大多都提供 ...
随机推荐
- UNIX域协议(无名套接字)
关于什么是UNIX域套接字可以参考:http://www.cnblogs.com/xcywt/p/8185597.html这里主要介绍非命名的UNIX域套接字的用法.1.socketpair函数先看m ...
- JS 中 cookie 的使用
1.cookie 是什么? ①.cookie 是存储于访问者计算机中的变量.每当一台计算机通过浏览器来访问某个页面时,那么就可以通过 JavaScript 来创建和读取 cookie. ②.实际上 c ...
- 图解JQUERY尺寸及位置定义
最近在学习JQUERY的一些应用,接触到了JQUERY对于元素尺寸及位置定义,还有就是配合浏览器尺 寸及状态的计算所做出的一些动画特效.其实像这类JQUERY应用无外乎涉及这些属性的调用:innerH ...
- JS 对象API之修改、删除对象的属性
无论是修改还是删除对象的属性,我们首先要清楚:自有属性.共有属性的处理方法肯定是不同的: 先创建一个对象实例 var obj = { name: '小马扎', age: }; Object.proto ...
- shell脚本的if语句,判断某程序是否存在,不存在启动该程序!
想必大家都知道 "如果......那么......" 这种语法的应用吧! 当然呢,linux下对于这种用法也是有所考虑的,很多时候我们都需要写一个shell脚本,难免会避免if语句 ...
- linux系统编程:IO读写过程的原子性操作实验
所谓原子性操作指的是:内核保证某系统调用中的所有步骤(操作)作为独立操作而一次性加以执行,其间不会被其他进程或线程所中断. 举个通俗点的例子:你和女朋友OOXX的时候,突然来了个电话,势必会打断你们高 ...
- LindDotNetCore~Mock对实际应用中的意义
回到目录 Mock在单元测试里的意义 Mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以 便测试的测试方法.一个闹钟根据时间来进行提醒服务,如果过了下午5点 ...
- C语言中不同变量的访问方式
C语言中的变量大致可以分为全局变量,局部变量,堆变量和静态局部变量,这些不同的变量存储在不同的位置,有不同的生命周期.一般程序将内存分为数据段.代码段.栈段.堆段,这几类变量存储在不同的段中,造成了它 ...
- [UWP]如何使用Fluent Design System (下)
4. 兼容旧版本 FDS最常见的问题之一是如何与Fall Creators Update之前的版本兼容,其实做起来也挺简单的,ColorfulBox就实现了Creators Update与Fall C ...
- 实体处理模块IEntityModule
在2015年7月16日,XCode新增了实体处理模块IEntityModule,用于拦截实体对象添删改操作. 该接口参考IHttpModule设计理念,横切在实体对象的关键生命周期之中,以达到多实体类 ...