Also use log4net to log records to the background of the database implementation (II)
Good afternoon everyone, yesterday told the configuration, today we talk about the background implementation, after the completion of the backstage implementation, we can really solve the custom attribute field values into the database.
Before I write, I emphasize that the concept of "log" is very extensive, with error logs, operation logs, access logs, event logs, and so on. We do not advocate logging all logs to the database because it is not necessary to do so. At the same time, if the Log data table and the business table in the same database, the frequent logging operations will affect performance (Log4net provides a caching mechanism, can be cached when the log data reached a set value, such as 200, log4net will be batch data input into the database. Even if it is such a good mechanism, I still suggest that you must distinguish between the situation, the general error log and event log we use the document as a record, the corresponding operation log we can use database records.
The focus of the universal logging system is general. Can adapt to a variety of requirements, such as to provide a rich log format (such as files, databases, etc.), and adapt to different business needs, such as a business want to record a1,a2,a3 field, b business want to record b1,b2,b3 field. Flexibility is also needed to adapt to business changes. Log4net is such an open source framework, said so much, I would like to express that: the way the database logging is not the only and best, we must be in the discretion of the.
Okay, so let's go back to the process code in the background:
(1), log object, is the carrier in the storage log:
public class LogMessage {public int UserID {get; set;}}
LogMessage as a log object in the project, everyone must be wondering why I have only one property userid. The reason is that I'm testing whether custom properties can be recorded in the log database, so it's not necessary to get too many properties.
Log4net provides some default properties when logging to a database, respectively:
[Id] [int] IDENTITY (1, 1) NOT NULL, [Date] [datetime] NULL, --异常记录时间[Thread] [varchar] (255) NULL, --线程ID(数字)[Level] [varchar] (50) NULL, --日志级别(FALAT,ERROR,WARN,INFO,DEBUG)[Logger] [varchar] (255) NULL, --记录的类[Message] [varchar] (4000) NULL, --消息 |
These default values we had better in each log table to add, I test the time to delete the message, the results can not be recorded in the log. So I suggest you take these all with you. Field name you can change, for example, I changed the date to Recordtime, but in the configuration file, the Recordtime field corresponding to the value is still @log_date, forget the classmate back to the previous article to see the configuration.
(2), CustomLayout class
The CustomLayout class inherits to Log4net. Layout.patternlayout
We should be familiar with layout, "the layout component is used to display the last formatted output information to the user. Output information can be displayed in a variety of formats, mainly depending on the type of layout component we are using. can be linear or an XML file. The layout component works with a Appender component. A list of the different layout components in the API help manual. A Appender object that can only correspond to one layout object. To implement your own layout class, you need to get from log4net. Layout.layoutskeleton class inherits, it implements the Ilayout interface. ”
Because we're going to use the custom property userid, so we're going to implement our own layout class, let's look at the code:
public class customlayout:log4net. layout.patternlayout{public customlayout () {this . Addconverter ("UserID", typeof (Useridpatternconverter));} }
The Useridpatternconverter in the typeof (Useridpatternconverter) statement implements the formatted output information.
Internal sealed class Useridpatternconverter:patternlayoutconverter { override protected void Convert (TextWriter Writer, loggingevent loggingevent) { LogMessage logmessage = loggingevent.messageobject as logmessage; if (logmessage! = null) writer. Write (Logmessage.userid);} }
(3), simple package for log4net
public class Loghelper {public Loghelper () {} public static string loggername = String . Empty; private static LogMessage message = NULL; private static ILog _log; public static ILog Log {get {string path = @ "C:\Log4Net.config"; Log4net. Config.XmlConfigurator.Configure (new FileInfo (path)); if (_log = = null) {//Read logger object from the configuration file//weblogger configuration information is used to input the log into Database//Do for the expansion of the decision to determine the log form, database or TXT document, or console program. _log = log4net. Logmanager.getlogger (Loggername); Log4net. Logmanager.getlogger ("Weblogger"); } else {if (_log. Logger.name! = loggername) {_log = log4net. Logmanager.getlogger (Loggername); }} return _log; }}///<summary>//debug//</summary> public static void Debug () {if (log. isdebugenabled) {log. Debug (message); }}///<summary>//Error//</summary> public static void error () { if (log. iserrorenabled) {log. Error (message); }}///<summary>///Fatal error///</summary> public static void Fatal () {if (log. isfatalenabled) {log. Fatal (message); }}///<summary>///Record general Log////</summary> public static void info () {if (log. isinfoenabled) {//log. Info ("Jerry"); Log. Info (message); }}///<summary>///Record warning///</summary> public static void Warn () {if (log. iswarnenabled) {log. Warn (message); }}///<summary>///Where the log is required to call this method///</summary>//<param name = "Level" > Custom levels </param> public static void Savemessage (LogMessage logmessage,int) { message = LogMessage; Switch (level) {case 1:info (); Break Case 2:warn (); Break Case 3:error (); Break Case 4:fatal (); Break Default:break; } } }
Log4net provides different logging methods depending on the log level, so the log level here is the corresponding levels field, so let's take a look at the log level of log4net:
This is the diagram I found on other websites to illustrate the level. Well, to this end, we've already put the log4net bottom up, and notice that you can write all of the classes on the previous page in a single class library. The advantage of this is that when other projects to use the logging function, the direct reference to your class library DLL can be, is not very convenient. It also enables a simple encapsulation of log4net, making it easier for other project groups to use.
Highlight it and remember to refer to Log4Net.dll in this class library. After all, we are to use log4net to achieve log records, do not write for a long while not quoted, it will be a problem.
(4) Well, let's call him in the Web presentation layer! Default.aspx
protected void Page_Load (object sender, EventArgs e) { loghelper.loggername = "Weblogger"; LogMessage logmessage = new LogMessage (); Logmessage.userid = 123456; Loghelper.savemessage (logmessage,1);}
Because we set the cache number in the configuration file, <buffersize value= "Ten"/> So you refresh 10, this time the data into the database. But the smart thing to do is to change the value of buffersize to 1.
(5), information in the database
(6), sorry, just see the time I saw the SQL statement without the table, now fill.
Use [logsys]go/****** Object: Table [dbo].[ Log] Script date:08/29/2012 14:56:11 ******/set ansi_nulls ongoset quoted_identifier ongoset ansi_padding Ongocreate TABLE [dbo]. [Log] ( [Id] [int] IDENTITY () not NULL, [levelname] [varchar] (+) NULL, [UserID] [int] null, [Message] [ VARCHAR] (4000) NULL, [Exception] [varchar] (+) NULL, [recordtime] [varchar] (+) NULL, CONSTRAINT [pk_log_1] PRIMARY KEY CLUSTERED ( [Id] ASC) with (pad_index = off, statistics_norecompute = off, Ignore_dup_key = off, Allow_row_locks = on, allow_page_locks = on) on [PRIMARY]) on [Primary]goset ansi_padding Offgo
Well, write here, I am lark, I wish you good mood every day, health.
Also use log4net to log records to the background of the database implementation (II)