How to save Log4Net logs to a mongodb Database

Source: Internet
Author: User
Tags log4net

How to save Log4Net logs to a mongodb Database
The name of log4net has been heard and never been used. This time, the APP project is ready to use log4net on the server. The log data volume is large, and frequent database writes may affect the overall system performance. Therefore, it is a good choice to write logs to the mongodb database independently. --- After two days of exploration, this document is summarized. Github has an open source project log4mongo-net, another skdia author according to the open source project made changes http://skyd.sinaapp.com/archives/1282. So we can use the skydia Code directly. 1. Upgrade the log4net and mongodb drivers to the latest version. Log2net: 1.2.15 mongodb: 2.2.3.32. A new LogHelper class (single-piece mode) is added. All logs are written through the static LogHelper method.

public  class LogHelper
  {
private static readonly LogHelper instance=new LogHelper();
  private static ILog log = null;   private Logger()  {      // XmlConfigurator.Configure();          LogLog.InternalDebugging = true;                }public  static LogHelper getInstance()
  {      if (log == null)      {          log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);      }          return instance;  }
public void Debug(Object message, Exception exception){      log.Debug(message);}public void Debug(Object message){      log.Debug(message);}
}
The result shows that there is a problem. log4net can originally record the class name where the log occurred and the specific row number. If a separate class is used to write logs, the recorded classes and row numbers are the content of LogHelper, and the specific error location cannot be located. The reason is that ILog uses LogManger. getLogger (Type) method. To obtain the wrong class and row number, you must independently call LogManger in each class. getLogger (System. reflection. methodBase. getCurrentMethod (). declaringType ). (Your understanding is not necessarily accurate) 3. Custom log Content fields. I can find many ways to add fields to Log4net on the Internet, but I use the modified log4mongo. The configuration is simplified. All fields are displayed by default. Therefore, it is basically not applicable to configuration changes. Start preparing to use LogicalThreadContext. Properties ["CustomColumn"] = "Custom value" to write more Custom content to the log. Before you run log. Debug (object), set the custom content through LogicalThreadContext. Then run log. Debug (object ). Although this method can achieve the goal, it is not very convenient. Another problem is that after LogicalThreadContext is set, these values will always exist and log will be executed again in the same thread. when debugging (object), Anyway will record these custom property values, which is not well controlled and easy to write wrong content. Another method is to use log. the objects in Debug (object) are implemented by directly logging. debug ("this is message") to write logs. You can also pass an object to log. debug. Before writing data to the database, you can use loggingEvent. renderedMessage is used to read the passed objects. public class LogInfo {public string AppKey {set; get;} public string UserID {set; get;} public string HostName {set; get ;} public string IPAddress {set; get;} public string Message {set; get;} public override string ToString () {var bsonDoc = this. toBsonDocument (); return bsonDoc. toString () ;}} default loggingEvent. renderedMessage is used to obtain the object. The value of ToString (). Here we need to rewrite ToString () to convert the class to BsonDocument. LoggingEvent. RenderedMessage obtains BsonDocument and then splits it into specific attributes. Private static void BuildCustomMessage (string message, ref Log log) {try {var bson = BsonDocument. parse (message); foreach (var item in bson. elements) {string value = item. value. toString (); if (item. value. isBsonNull) {value = string. empty;} log. properties. add (item. name, value) ;}} catch (Exception) {log. renderedMessage = message;} directly uses BsonDocument for convenience. parse (message) to determine whether it is a complex object or a String. Using try catch directly affects the performance. Compared with passing strings directly, BuildCustomMessage is not required. When passing complex objects, the performance difference is about 6%. The 6% mainly refers to the conversion of the object ToString () to BsonDocument and BuildCustomMessage. 4. A strange problem occurred during the test. A separate statement log. Debug (string) can be output to the console, but the database cannot be written. While using a loop to execute log. Debug (string) can be written to the database normally. Log4net prompts Shutdown called on Hierarchy, but does not know what it means or whether it is related. The solution is to change the database write operations from Asynchronous to synchronous. The specific reason is not found. Log4net problems, mongodb drivers, and log4net caches cannot be ruled out. // Collection. insertOneAsync (BuildBsonDocument (loggingEvent); collection. insertOne (BuildBsonDocument (loggingEvent); 5. To facilitate future maintenance, set the Database Name and Collection (Table Name) to the configuration file. <Appender name = "MongoDBAppender" type = "Log4Mongo. mongoDBAppender, Log4Mongo "> <connectionString value =" mongodb: // root: 123456 @ localhost: 27017 "/> <DatabaseName value =" log4mongo "/> <CollectionName value =" yyyyMM "/> </appender>: appenderSkeleton is directly obtained in this class. You do not need to process public string ConnectionStringName {get; set;} public string DatabaseName {get; set;} public string Colle. CtionName {get; set ;}< CollectionName value = "yyyyMM"/> is written to allow logs to automatically split tables by date. You can modify the configuration to split tables by day, month, or year.
        private IMongoCollection<Log> GetCollection(){            string tableName;            tableName = CollectionName ?? "yyyyMM";            tableName = "log"+ string.Format("{0:" + tableName + "}", DateTime.Now);            return GetDatabase().GetCollection<Log>(tableName); }

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.