Customize event logging

You can customize event logging by:

  • Handling system events – customize event information, limit which types of events the system logs, or execute any custom logic when an event gets logged.
  • Implementing classes of the IEventLogWritertype – specify additional logging destinations for events (e.g., another database, dedicated file, external system, etc.).

Handling event log events

By handling certain events, you can customize how the system logs records into its Event log.

The system raises the following types of logging events:

  • EventLogEvents.LogEvent.Before – allows you to customize the data logged for events or cancel logging for certain types of events.
  • EventLogEvents.LogEvent.After – allows you to perform custom actions after events are successfully logged.

Note: Performing demanding operations during event logging can negatively impact the performance of the website (particularly on sites under heavy load where a large number of events are logged).

Example

The following example demonstrates how to disable logging for events of a specific type and modify the Description text for certain events.

Note: Custom event handlers for EventLogEvents.LogEventonly affect events logged into the project’s main database (specified in the CMSConnectionStringconnection string in appsettings.json). Events logged using custom event log writers are not affected.

  1. Open your solution in Visual Studio.
  2. Create a custom module class.
  3. Override the module’s OnInit method and assign a handler method to EventLogEvents.LogEvent.Before.
  4. Perform the required actions within the handler method.
    • Access the data of the logged event through the Event property of the handler’s LogEventArgs parameter.
    • To cancel the logging of an event, call the Cancel method of the handler’s LogEventArgs parameter.


using CMS;

using CMS.DataEngine;
using CMS.EventLog;
using CMS.Base;

// Registers the custom module into the system
[assembly: RegisterModule(typeof(EventLogCustomization))]

public class EventLogCustomization : Module
{
    // Module class constructor, the system registers the module under the name "EventLogCustomization"
    public EventLogCustomization()
        : base("EventLogCustomization")
    {
    }

    // Contains initialization code that is executed when the application starts
    protected override void OnInit()
    {
        base.OnInit();

        // Assigns a handler to the LogEvent.Before event
        EventLogEvents.LogEvent.Before += LogEvent_Before;
    }

    private void LogEvent_Before(object sender, LogEventArgs e)
    {
        // Gets an object representing the event that is being logged
        EventLogInfo eventLogRecord = e.Event;

        // Cancels logging for events with the "CREATEOBJ" or "UPDATEOBJ" event codes.
        // Disables event log records notifying about the creation or update of objects in the system,
        // but still allows events related to object deletion.
        string eventCode = eventLogRecord.EventCode;
        if (String.Equals(eventLogRecord.EventCode, "CREATEOBJ", StringComparison.OrdinalIgnoreCase || String.Equals(eventLogData.EventCode, "UPDATEOBJ", StringComparison.OrdinalIgnoreCase)
        {
            e.Cancel();
        }

        // Adds a custom message to the Description field for events of the Information type
        if (String.Equals(eventLogRecord.EventType, EventType.INFORMATION, StringComparison.OrdinalIgnoreCase))
        {
            eventLogRecord.EventDescription += " Custom message";
        }
    }
}

Implement event log writers

Whenever the system logs an event to the database, you may want to persist the information in additional locations (external system, static file, etc.). For this purpose, the system allows you to specify additional logging destinations via event log writers.

An event log writer is a class that implements the IEventLogWriter interface. When the system logs an event, it iterates over all registered event log writers and calls their WriteLog(EventLogData eventLogData) method (given by the interface). The EventLogData parameter contains all data associated with the event being logged. This information can be used to direct the logging logic, for example, based on event severity.

The following example shows the implementation of an event log writer that writes all events of the ERROR type to a file located in the application’s root directory. It also sends an email to the address specified in NOTIFICATION_RECIPIENT.

  1. Create a new CsvErrorEventWriter class.
  2. Implement the IEventLogWriter interface.
  3. Register the implementation using the RegisterImplementation assembly attribute.
Custom event log writer implementation


using CMS;
using CMS.Base;
using CMS.Core;
using CMS.EmailEngine;

using System;
using System.IO;

using EventLogCustomizations;

[assembly: RegisterImplementation(typeof(IEventLogWriter), typeof(CsvErrorEventWriter))] 
public class CsvErrorEventWriter : IEventLogWriter
{
    private readonly IEmailService emailService;
    private const string NOTIFICATION_RECIPIENT = "administrators@localhost.local";
    private const string NOTIFICATION_SENDER = "automation@localhost.local";

    public CsvErrorEventWriter(IEmailService emailService)
    {
        this.emailService = emailService;
    }

    public void WriteLog(EventLogData eventLogData)
    {
        if (eventLogData.EventType == EventTypeEnum.Error)
        {
            // Checks if the error event contains an exception
            string exception = eventLogData.Exception != null ? eventLogData.Exception.ToString() : "No exception logged.";

            string eventData = $"Error, {eventLogData.EventCode}, {DateTime.Now}, {eventLogData.EventDescription}, {exception}{Environment.NewLine}";

            // Writes logged error events into a 'errors.csv' file in the application's root directory
            File.AppendAllText(SystemContext.WebApplicationPhysicalPath + "\\errors.csv", eventData);

            // Sends an email notifying about the error event
            emailService.SendEmail(GetEmailMessage(eventLogData, eventData));
        }
    }

    private EmailMessage GetEmailMessage(EventLogData data, string eventData)
    {
        return new EmailMessage()
        {
            From = NOTIFICATION_SENDER,
            Recipients = NOTIFICATION_RECIPIENT,
            Subject = $"Error {data.EventCode}",
            Body = $"The following error occurred:{Environment.NewLine}{Environment.NewLine}{eventData}"
        };
    }
}

CsvErrorEventWriter is now registered in the system. When logging an event, the system calls the writer’s WriteLog method, executing the code within.