1

We are trying to consolidate our logging data in Splunk and then limit/reduce access to the Sitecore servers. I've not seen much from the community on how to set this up.

Are there any examples available demonstrating how to do this?

1 Answer 1

4

Prerequisites

The following must be setup in advance to make logging to Splunk possible.

Note: The following example could use some TLC but gets the job done.

Code

First step is to write some code that taps into the logging mechanism in Sitecore (log4net).

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using log4net.Appender;
using log4net.spi;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace Scms.Foundation.Logging
{
    public class SplunkAppender : AppenderSkeleton
    {
        private readonly HttpClient _httpClient;
        private Uri _baseUrl;

        public SplunkAppender()
        {
            var httpClientHandler = new HttpClientHandler
            {
                ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
            };
            _httpClient = new HttpClient(httpClientHandler);
        }

        public string Url { get; set; }

        public string Token { get; set; }

        public override void ActivateOptions()
        {
            base.ActivateOptions();
            _baseUrl = new Uri(Url);
            _httpClient.DefaultRequestHeaders.ExpectContinue = false;

            if (string.IsNullOrWhiteSpace(Token))
                return;

            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Splunk", Token);
        }

        protected override void Append(LoggingEvent loggingEvent)
        {
            Task.Run(async () =>
            {
                try
                {
                    var logEntry = new SplunkLogEntry
                    {
                        Event =
                        {
                            Level = loggingEvent.Level.Name,
                            Message = loggingEvent.RenderedMessage,
                            Time = loggingEvent.TimeStamp.ToString("HH:mm:ss"),
                            Date = loggingEvent.TimeStamp.ToString("yyyy-MM-dd"),
                            Username = loggingEvent.UserName
                        },
                        Source = loggingEvent.LoggerName
                    };
                    var serializedContent = JsonConvert.SerializeObject(logEntry, new JsonSerializerSettings()
                    {
                        NullValueHandling = NullValueHandling.Ignore,
                        ContractResolver = new CamelCasePropertyNamesContractResolver()
                    });
                    var stringContent = new StringContent(serializedContent, Encoding.UTF8, "application/json");
                    var responseMessage = await _httpClient.PostAsync(_baseUrl, stringContent);
                }
                catch (Exception ex)
                {
                    this.ErrorHandler.Error("Unable to send logging event to remote host: " + Url, ex);
                }
            });
        }
    }

    public class SplunkLogEntry
    {
        public string Index { get; set; } = "sitecore";

        [JsonProperty("sourcetype")]
        public string SourceType { get; set; } = "sitecore:log4net";

        public string Source { get; set; } = nameof(SplunkAppender).ToLower();

        public string Host { get; set; } = Environment.MachineName.ToLower();

        public SplunkEvent Event { get; set; } = new SplunkEvent();
    }

    public class SplunkEvent
    {
        public string Level { get; set; }
        public string Message { get; set; }
        public string Time { get; set; }
        public string Date { get; set; }
        public string Username { get; set; }
    }
}

Second step is to patch in the new appender.

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <log4net>
      <appender name="SplunkAppender" type="Scms.Foundation.Logging.SplunkAppender, Scms.Foundation">
        <url value="https://your-splunk-instance:8088/services/collector/raw" />
        <token value="your-guid-from-splunk" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%4t %d{ABSOLUTE} %-5p %m%n"/>
        </layout>
      </appender>
      <root>
        <appender-ref ref="SplunkAppender" />
      </root>
    </log4net>
  </sitecore>
</configuration>

Finally, log into Splunk and watch all your hard work pay off.

enter image description here

Possible Enhancements

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.