基于.NetCore的日志服務(wù)器

文章轉(zhuǎn)載自平娃子(QQ:273206491):http://os.pingwazi.cn/resource/riziserver

系統(tǒng)日志是觀察系統(tǒng)運(yùn)行情況的窗口,它可以幫助我們快速定位錯(cuò)誤、發(fā)現(xiàn)系統(tǒng)性能瓶頸甚至可以分析用戶行為等。下面基于.NetCore開發(fā)的一套簡單的日志服務(wù)器,供大家交流學(xué)習(xí)。

一、為什么要單獨(dú)實(shí)現(xiàn)日志服務(wù)器:

1、系統(tǒng)日志操作(寫日志)是一個(gè)頻率非常高的操作,當(dāng)系統(tǒng)用戶量達(dá)到一定程度后,對于高頻的日志操作很有可能會成為系統(tǒng)的性能瓶頸

2、實(shí)現(xiàn)日志處理與系統(tǒng)的解耦

3、有利于系統(tǒng)的擴(kuò)展(如果日志單臺日志服務(wù)器到達(dá)負(fù)載了,再加一臺日志服務(wù)器就行)

4、利于日志的集中管理

二、采用什么方式實(shí)現(xiàn)日志服務(wù)器

1、日志的傳輸采用tcp協(xié)議進(jìn)行傳輸

2、日志服務(wù)器是監(jiān)聽了指定ip和端口的socket服務(wù)器

3、服務(wù)器的日志操作采用多線程,充分利用服務(wù)器資源

三、如何實(shí)現(xiàn)日志服務(wù)器

1、安裝.NetCore連接數(shù)據(jù)庫的驅(qū)動程序(我這里使用的是mysql),便于將日志信息保存到數(shù)據(jù)中

Install-Package MySql.Data -Version 8.0.15

2、安裝Log4Net,當(dāng)日志服務(wù)器發(fā)生異常的時(shí)候記錄異常日志到文件中,便于后期進(jìn)行錯(cuò)誤處理

Install-Package log4net -Version 2.0.8

2.1、配置Log4Net

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

? <!-- This section contains the log4net configuration settings -->

? <log4net>

? ? <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">

? ? ? <file type="log4net.Util.PatternString" value="Log/" />

? ? ? <appendToFile value="true" />

? ? ? <rollingStyle value="Composite" />

? ? ? <staticLogFileName value="false" />

? ? ? <datePattern value="yyyyMMdd'.log'" />

? ? ? <maxSizeRollBackups value="10" />

? ? ? <maximumFileSize value="50MB" />

? ? ? <layout type="log4net.Layout.PatternLayout">

? ? ? ? <conversionPattern value="%date? [%thread]? %-5level? %message%newline" />

? ? ? </layout>

? ? </appender>

? ? <!-- Setup the root category, add the appenders and set the default level -->

? ? <root>

? ? ? <level value="ALL" />

? ? ? <appender-ref ref="RollingLogFileAppender" />

? ? </root>

? </log4net>

</configuration>

2.2、實(shí)現(xiàn)LogHelper類,這個(gè)類主要用于文件日志的記

using log4net;

using log4net.Appender;

using log4net.Config;

using log4net.Repository;

using System;

using System.IO;

namespace LogServer

{

? ? /// <summary>

? ? /// 日志幫助類

? ? /// </summary>

? ? public class LogHelper

? ? {

? ? ? ? private static ILog Logger { get; set; }

? ? ? ? static LogHelper()

? ? ? ? {

? ? ? ? ? ? if (Logger == null)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? //log4net注冊

? ? ? ? ? ? ? ? ILoggerRepository loggerRepository = LogManager.CreateRepository("NETCoreRepository");

? ? ? ? ? ? ? ? XmlConfigurator.Configure(loggerRepository, new FileInfo("log4net.config"));

? ? ? ? ? ? ? ? Logger = LogManager.GetLogger(loggerRepository.Name, "InfoLogger");

? ? ? ? ? ? ? ? IAppender[] appenders = loggerRepository.GetAppenders();

? ? ? ? ? ? ? ? ///打印日志的保存路徑

? ? ? ? ? ? ? ? foreach (var appender in appenders)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? RollingFileAppender rollingFileAppender = appender as RollingFileAppender;

? ? ? ? ? ? ? ? ? ? Console.WriteLine(rollingFileAppender.File);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? /// <summary>

? ? ? ? /// 調(diào)試信息

? ? ? ? /// </summary>

? ? ? ? /// <param name="msg"></param>

? ? ? ? /// <param name="ex"></param>

? ? ? ? public static void Debug(string msg, Exception ex = null)

? ? ? ? {

? ? ? ? ? ? if (ex == null)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Logger.Debug(msg);

? ? ? ? ? ? }

? ? ? ? ? ? else

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Logger.Debug(msg, ex);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? //錯(cuò)誤信息

? ? ? ? public static void Error(string msg, Exception ex = null)

? ? ? ? {

? ? ? ? ? ? if (ex == null)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Logger.Error(msg);

? ? ? ? ? ? }

? ? ? ? ? ? else

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Logger.Error(msg, ex);

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

3、客戶端數(shù)據(jù)處理類

using MySql.Data.MySqlClient;

using System;

using System.Collections.Generic;

using System.Net.Sockets;

using System.Text;

using System.Threading;

namespace LogServer

{

? ? public class TcpClientManager

? ? {

? ? ? ? private TcpListener _TcpListener { get; set; }

? ? ? ? private TcpClient _TcpClient { get; set; }

? ? ? ? public TcpClientManager(TcpListener tcpListener, TcpClient tcpClient)

? ? ? ? {

? ? ? ? ? ? this._TcpClient = tcpClient;

? ? ? ? ? ? this._TcpListener = tcpListener;

? ? ? ? }

? ? ? ? public void DealClientData()

? ? ? ? {

? ? ? ? ? ? StringBuilder sb = new StringBuilder();

? ? ? ? ? ? try

? ? ? ? ? ? {

? ? ? ? ? ? ? ? //1、獲取客戶端數(shù)據(jù)流

? ? ? ? ? ? ? ? NetworkStream networkStream = this._TcpClient.GetStream();

? ? ? ? ? ? ? ? //2、創(chuàng)建網(wǎng)絡(luò)流中自定義數(shù)據(jù)類型(int類型的存儲占用4個(gè)字節(jié))

? ? ? ? ? ? ? ? byte[] dataLenByte = new byte[4];

? ? ? ? ? ? ? ? byte[] dataTypeByte = new byte[4];

? ? ? ? ? ? ? ? //3、獲取自定義數(shù)據(jù)值

? ? ? ? ? ? ? ? int readCount = networkStream.Read(dataLenByte, 0, dataLenByte.Length);

? ? ? ? ? ? ? ? while (readCount > 0)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? //3.1、獲取自定義數(shù)據(jù)

? ? ? ? ? ? ? ? ? ? networkStream.Read(dataTypeByte, 0, dataTypeByte.Length);

? ? ? ? ? ? ? ? ? ? int dataLen = BitConverter.ToInt32(dataLenByte, 0);

? ? ? ? ? ? ? ? ? ? int dataType = BitConverter.ToInt32(dataTypeByte, 0);

? ? ? ? ? ? ? ? ? ? if (dataLen > 0)

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? //讀取數(shù)據(jù)

? ? ? ? ? ? ? ? ? ? ? ? byte[] data = new byte[dataLen];

? ? ? ? ? ? ? ? ? ? ? ? int readedDataLen = 0;

? ? ? ? ? ? ? ? ? ? ? ? while (dataLen - readedDataLen > 0)

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? int dataBufferReadCount = 0;

? ? ? ? ? ? ? ? ? ? ? ? ? ? if (dataLen - readedDataLen >= 1024)

? ? ? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dataBufferReadCount = 1024;

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? else

? ? ? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dataBufferReadCount = dataLen - readedDataLen;

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? //讀取數(shù)據(jù)到緩沖區(qū)

? ? ? ? ? ? ? ? ? ? ? ? ? ? byte[] dataBuffer = new byte[dataBufferReadCount];

? ? ? ? ? ? ? ? ? ? ? ? ? ? int tempReadCount = networkStream.Read(dataBuffer, 0, dataBuffer.Length);

? ? ? ? ? ? ? ? ? ? ? ? ? ? //拷貝數(shù)據(jù)到數(shù)據(jù)容器中

? ? ? ? ? ? ? ? ? ? ? ? ? ? dataBuffer.CopyTo(data, readedDataLen);

? ? ? ? ? ? ? ? ? ? ? ? ? ? readedDataLen += tempReadCount;

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? sb.Append($"({dataType},'{Encoding.UTF8.GetString(data)}'),");

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? //讀取當(dāng)前客戶端連接的下一條數(shù)據(jù)

? ? ? ? ? ? ? ? ? ? readCount = networkStream.Read(dataLenByte, 0, dataLenByte.Length);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if (!string.IsNullOrEmpty(sb.ToString()))

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? using (MySqlConnection conn =

? ? ? ? ? ? ? ? ? ? ? ? new MySqlConnection("server=127.0.0.1;database=Log;uid=root;pwd=root;charset=utf8;"))

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? using (MySqlCommand cmd = conn.CreateCommand())

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? conn.Open();

? ? ? ? ? ? ? ? ? ? ? ? ? ? cmd.CommandText = $"insert into apilog(`Type`,`Msg`) values {sb.ToString().TrimEnd(',')}";

? ? ? ? ? ? ? ? ? ? ? ? ? ? cmd.ExecuteNonQuery();

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? catch (Exception ex)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Console.WriteLine($"保存日志信息發(fā)生異常:{ex}");

? ? ? ? ? ? ? ? LogHelper.Error("保存日志信息發(fā)生異常", ex);

? ? ? ? ? ? }

? ? ? ? ? ? finally

? ? ? ? ? ? {

? ? ? ? ? ? ? ? //關(guān)閉客戶端連接

? ? ? ? ? ? ? ? this._TcpClient.Close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

4、主程序

using MySql.Data.MySqlClient;

using System;

using System.IO;

using System.Net;

using System.Net.Sockets;

using System.Threading;

namespace LogServer

{

? ? class Program

? ? {

? ? ? ? static void Main(string[] args)

? ? ? ? {

? ? ? ? ? ? Thread tcpListenerThread = new Thread(() =>

? ? ? ? ? ? {

? ? ? ? ? ? ? ? IPEndPoint ipEndPoint=new IPEndPoint(IPAddress.Any,8888);

? ? ? ? ? ? ? ? TcpListener tcpServer = new TcpListener(ipEndPoint);

? ? ? ? ? ? ? ? tcpServer.Start(100);

? ? ? ? ? ? ? ? while (true)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? Console.WriteLine("日志服務(wù)器正在運(yùn)行中...");

? ? ? ? ? ? ? ? ? ? TcpClient tcpClient = tcpServer.AcceptTcpClient();

? ? ? ? ? ? ? ? ? ? Console.WriteLine("請求來了!開始處理...");

? ? ? ? ? ? ? ? ? ? TcpClientManager tcpClientManager = new TcpClientManager(tcpServer, tcpClient);

? ? ? ? ? ? ? ? ? ? Thread tcpClientThread = new Thread(tcpClientManager.DealClientData);

? ? ? ? ? ? ? ? ? ? tcpClientThread.IsBackground = true;

? ? ? ? ? ? ? ? ? ? tcpClientThread.Start();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? });

? ? ? ? ? ? tcpListenerThread.IsBackground = true;

? ? ? ? ? ? tcpListenerThread.Start();

? ? ? ? ? ? while (true)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Console.WriteLine("日志服務(wù)器正在運(yùn)行中...");

? ? ? ? ? ? ? ? Console.ReadKey();

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

5、寫日志測試

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net.Sockets;

using System.Text;

using System.Threading.Tasks;

using Microsoft.AspNetCore.Mvc;

namespace ApiServer.Controllers

{

? ? [Route("api/[controller]")]

? ? [ApiController]

? ? public class ValuesController : ControllerBase

? ? {

? ? ? ? // GET api/values

? ? ? ? [HttpGet]

? ? ? ? public ActionResult<string> Get(string msg)

? ? ? ? {

? ? ? ? ? ? try

? ? ? ? ? ? {

? ? ? ? ? ? ? ? using (TcpClient tcpClient = new TcpClient("127.0.0.1", 8888))

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? if (string.IsNullOrEmpty(msg))

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? return "請傳正確的請求參數(shù)";

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? //發(fā)送日志數(shù)據(jù)

? ? ? ? ? ? ? ? ? ? for (int i = 0; i < 100; i++)

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? byte[] sourceData = Encoding.UTF8.GetBytes(msg);

? ? ? ? ? ? ? ? ? ? ? ? byte[] dataLen = BitConverter.GetBytes(sourceData.Length);

? ? ? ? ? ? ? ? ? ? ? ? byte[] dataType = BitConverter.GetBytes(1);

? ? ? ? ? ? ? ? ? ? ? ? byte[] sendData = new byte[sourceData.Length + 8];

? ? ? ? ? ? ? ? ? ? ? ? dataLen.CopyTo(sendData, 0);

? ? ? ? ? ? ? ? ? ? ? ? dataType.CopyTo(sendData, 4);

? ? ? ? ? ? ? ? ? ? ? ? sourceData.CopyTo(sendData, 8);

? ? ? ? ? ? ? ? ? ? ? ? tcpClient.Client.Send(sendData);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? //關(guān)閉與日志服務(wù)器的連接

? ? ? ? ? ? ? ? ? ? tcpClient.Close();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? catch (Exception ex)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? return ex.Message;

? ? ? ? ? ? }

? ? ? ? ? ? return "日志保存成功";

? ? ? ? }

? ? }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評論 6 541
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,312評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,993評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,410評論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,778評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,955評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,521評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,266評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,468評論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,696評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,193評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,431評論 2 378

推薦閱讀更多精彩內(nèi)容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 2,718評論 0 3
  • 英文文檔,一開始我也是抗拒的,邊翻譯邊看,也就花費(fèi)了1個(gè)小時(shí)基本就閱讀過了,我的英文基礎(chǔ)其實(shí)很差。附上鏈接:鏈接:...
    lonecolonel閱讀 9,985評論 3 1
  • (http://www.cnblogs.com/zhangchenliang/p/4546352.html) 1、...
    凌雲(yún)木閱讀 2,447評論 0 2
  • 本文是對FTP相關(guān)操作,例如新建/刪除目錄、新建/刪除文件、獲取文件/目錄列表等的總結(jié),方便日后調(diào)用。 其實(shí)C#操...
    Nmao閱讀 1,275評論 0 0
  • 同頻共振,播種富而有愛的種子 發(fā)愿: 愿正法久住,愿眾生離苦得樂 時(shí)時(shí)與源頭聯(lián)結(jié), 我之富有,與眾生共享...
    福氣東來閱讀 598評論 0 0