酷徒LOGO
0 0 评论
文章标签:log  WEB  Server  logs  

 log.server.png

介绍

在我的上一个项目中,我需要查看我的应用程序编写的日志。 我没有提到这里的原因,我没有访问运行应用程序的机器的权限。 我需要找到一个创造性的解决方案来克服这个限制,在许多想法之后,我找到了一个。 每 20秒显示一次文件的最后一行的web服务器。

使用演示应用程序

使用"开始"和"停止"按钮启动和停止日志服务器。 服务器侦听端口 8080,以便使用已经监视文件的List 显示索引页,使用以下地址: ": 127.0.0.1: 8080"。

要添加要监视的文件,请使用"添加"按钮。 将出现一个新对话框。 应该提供URL的前缀和要监视的文件的路径,然后按"行"。 文件应添加到索引页,其中包含最后 10.20.50和 100行的页链接。 这些页面的地址采用以下格式: http://127.0.0.1 :8080/main/last/20,其中主是提供的前缀,而 20是要显示的最后一行的号码。

每 20秒刷新一次页面,这样我们就知道文件的实时情况。 当我们无法调试或者无法访问机器时,这可以能非常有帮助诊断问题。

在 C# 程序中嵌入服务器

有时更好的解决方案是将日志服务器嵌入到应用程序中。 例如要添加两个文件" main.log"和" error.log",可以使用下面的代码:

LogServer _logServer = new LogServer();
FileMonitorListHandler _handler = new FileMonitorListHandler();
_logServer.AddHandler(_handler);
_handler.AddFile("main","main.log");
_handler.AddFile("error","error.log");
server.Start(8080);

LogServer 是可以显示日志文件的网络服务器。 首先,我们添加实例 FileMonitorListHandler,它负责显示文件 List 和页面文件。 要添加日志文件,应该使用 AddFile 方法。 这个方法采用前缀 URL ("主"还有"错误") 并将它的映射到被监视文件路径(" main.log"还有" error.log")。

服务器从 8080开始后,我们可以使用以下地址查看这些文件中的最后一行: http://127.0.0.1 :8080/main/last/20 和 http://127.0.0.1 :8080/error/last/20,其中 20是要显示的最后一行的最大行数。

下面的小节将解释如何完成这一。

创建网络服务器

启动web服务器时,将创建一个新的线程来侦听传入的HTTP请求。 _stopEvent 将允许我们在需要时正常地停止服务器。

publicbool Start(int port) {
 if (_thread!= null) {
 returnfalse;
 }
 Port = port;
 bool rc = false;
 try {
 _thread = new Thread(new ThreadStart(Listen));
 _stopEvent = new AutoResetEvent(false);
 _thread.Start();
 rc = true;
 } catch (Exception ee) {
 Logger.Info("{0}",ee.Message);
 }
 return rc;
}

侦听线程将侦听传入请求。 在 _stopEvent 被设置或者有一个新的连接来处理之前,我们等待它空闲。 在第一种情况下,我们只是从无限循环中断,终止服务器侦听线程并停止服务器。 在第二种情况下,我们通过调用 MainHandler.HandleInThread() 在一个新线程中处理请求。

privatevoid Listen() {
 _listener = new TcpListener(Port);
 _listener.Start();
 Logger.Info("Listening on {0}",Port);
 while (true) {
 IAsyncResult ar = _listener.BeginAcceptSocket(
 new AsyncCallback(delegate(IAsyncResult aa) { }),null);
 WaitHandle[] handles = new WaitHandle[] { _stopEvent, ar.AsyncWaitHandle };
 int reason = WaitHandle.WaitAny(handles);
 if (reason == 0) {
 break;
 }
 Socket socket = _listener.EndAcceptSocket(ar);
 if (socket.Connected) {
 Logger.Info("Client Connected from IP {0}",socket.RemoteEndPoint);
 MainHandler handler = new MainHandler(ref socket,ref _handlers);
 handler.HandleInThread();
 }
 }
 _thread = null;
}

MainHandler 负责解析请求并创建响应。 这些对象将被传递到 MainHandler.Handle 以进行额外处理。 处理完成后,响应将发送到浏览器,套接字已经关闭,线程终止。

publicvoid Handle() {
 Request request = Request.GetRequest(ref _socket);
 Response response = new Response();
 Handle(ref request,ref response);
 response.Send(ref _socket);
 _socket.Close();
}

处理程序

每个服务器都有一个 List 处理器,可以使用 LogServer.AddHandle。 处理程序实现 IHandler 接口:

publicinterface IHandler { 
 HandleStatus Handle(ref Request request,ref Response response);
}

方法 Handle 采用两个参数: requestresponse 该方法应该添加所需的功能(。例如更新 response 对象的StatusCodeContentType 或者 Data ),并返回 HandleStatus。 这是由 MainHandler.Handle 使用的。 MainHandler.Handlerequestresponse 对象逐个移动到处理程序中,直到其中一个处理程序的Handle 返回 HandleStatus.Done。 如果返回 HandleStatus.Next,则将调用下一个处理程序。

public HandleStatus Handle(ref Request request,ref Response response) {
 foreach (IHandler handler in _handlers) {
 if ( handler.Handle(ref request,ref response) == HandleStatus.Done ) {
 break;
 }
 }
 return HandleStatus.Done;
}

FileMonitorHandler

魔术是在 FileMonitorHandler.Handle 中完成的,它显示页面。

public HandleStatus Handle(ref Request request,ref Response response) {
 char[] sep = new char[1];
 sep[0] = '/';
 string[] parts = request.Uri.LocalPath.Split(sep, 
 StringSplitOptions.RemoveEmptyEntries);
 if (parts.Length >0 && parts[0]!= _prefix) {
 return HandleStatus.Next;
 }
 string contents = String.Empty;
 if (parts.Length >2 && parts[1] == "last") {
 int num = Int16.Parse(parts[2]);
 int count = 0;
 foreach( string line in GetLastLines(_filename,num)) {
 contents += String.Format("<p class='row{0} row'>{1}</p>",count % 2,line);
 count++;
 }
 }
 response.Data += String.Format(
 @"<html>
 <head>
 <title>{0} - {1}</title>
 <meta http-equiv='refresh' content='20'>
 <style> 
 body {{ font-size: 14px; }}
 h1 {{font-size: 16px; }}
. row0 {{ background-color: #f0f0f0; }}
. row1 {{ background-color: #ffff99; }}
. row {{ margin:0px; border: 1px #00f solid; padding:2px 10px;}}
 </style>
 </head>
 <body>
 <h1>{0} - {1}</h1>
 {2}
 </body>
 </html>",Path.GetFileName(_filename),DateTime.Now.ToString(),contents);
 return HandleStatus.Done;
}

首先,我们检查请求是否属于这里处理程序。 如果是这种情况,它会发现要显示的最后一行数。 然后读取最后一行,然后使用这里内容生成 HTML,并指示浏览器每 20秒刷新一次页面( meta命令: <元 http-equiv='刷新'content='20'> )。

FileMonitorListHandler

这里处理程序负责显示带有监视文件的索引页,并带有指向它的最后一行页的链接。

public HandleStatus Handle(ref Request request,ref Response response) {
 foreach (IHandler handler in _handlers) {
 if (handler.Handle(ref request,ref response) == HandleStatus.Done) {
 return HandleStatus.Done;
 }
 }
 StringBuilder fileList = new StringBuilder();
 foreach (FileMonitorHandler handler in _handlers) {
 fileList.Append("<tr>");
 fileList.Append(String.Format("<td>{0}</td>",handler.Prefix));
 fileList.Append(String.Format("<td><a href='http://www.codeproject.com" + 
 "/{0}/last/10'>Last 10</a>&nbsp;<a href='http://www.codeproject.com/" + 
 "{0}/last/20'>Last 20</a>&nbsp;<a href='http://www.codeproject.com/" + 
 "{0}/last/50'>Last 50</a>&nbsp;<a href='http://www.codeproject.com/" + 
 "{0}/last/100'>Last 100</a>&nbsp;",handler.Prefix));
 fileList.Append("</tr>");
 }
 response.Data += String.Format(
 @"<html>
 <head>
 <title>Welcome to Log Server</title<
 <style <
 body {{ font-size: 14px; }}
 h1 {{font-size: 16px; }}
 td,th {{ border: 1px solid #000000; 
 text-align:center; padding: 0px 10px; }}
 th {{ background-color:#ffffbb;}}
 td {{ background-color:#ffffcc;}}
 table {{ border-collapse:collapse; }}
 </style<
 </head<
 <body<
 <p<Monintoring the following files : </p<
 <table<
 <tr<<th<Prefix</th <<th<Last Lines</th<<tr<
 {0}
 </table<
 </body<
 </html<",fileList);
 return HandleStatus.Done;
}

下一步?

尽管服务器不提供 ASP.NET 提供的所有豪华,但它有一些优势。 服务器是轻量级的,使用非常简单,并且很容易将它嵌入任何 C# 应用程序中。

另一个优点是能够扩展服务器以响应新的类型请求。 唯一需要做的就是实现 IHandler 接口,并使用 LogServer.AddHandler 向服务器添加新实例。

历史记录

  • 版本 1 - 第一个版本。
  • 版本 2 - 添加了日志服务器演示应用程序。


文章标签:WEB  Server  log  logs  

Copyright © 2011 HelpLib All rights reserved.    知识分享协议 京ICP备17041772号-2  |  如果智培  |  酷兔英语  |  帮酷