<commit_before>﻿using System;
using System.Linq;
using System.Collections.Generic;
using Akka.Event;
using Serilog.Core;
using Serilog.Core.Enrichers;

namespace Akka.Logger.Serilog
{
    public class SerilogLoggingAdapter : ILoggingAdapter
    {
        private readonly ILoggingAdapter adapter;
        private readonly IDictionary<string, ILogEventEnricher> enrichers = new Dictionary<string, ILogEventEnricher>();

        public SerilogLoggingAdapter(ILoggingAdapter adapter)
        {
            this.adapter = adapter;
        }

        /// <summary>
        /// Check to determine whether the <see cref="F:Akka.Event.LogLevel.DebugLevel" /> is enabled.
        /// </summary>
        public bool IsDebugEnabled => adapter.IsDebugEnabled;

        /// <summary>
        /// Check to determine whether the <see cref="F:Akka.Event.LogLevel.InfoLevel" /> is enabled.
        /// </summary>
        public bool IsInfoEnabled => adapter.IsInfoEnabled;

        /// <summary>
        /// Check to determine whether the <see cref="F:Akka.Event.LogLevel.WarningLevel" /> is enabled.
        /// </summary>
        public bool IsWarningEnabled => adapter.IsWarningEnabled;

        /// <summary>
        /// Check to determine whether the <see cref="F:Akka.Event.LogLevel.ErrorLevel" /> is enabled.
        /// </summary>
        public bool IsErrorEnabled => adapter.IsErrorEnabled;

        /// <summary>Determines whether a specific log level is enabled.</summary>
        /// <param name="logLevel">The log level that is being checked.</param>
        /// <returns><c>true</c> if the specified level is enabled; otherwise <c>false</c>.</returns>
        public bool IsEnabled(LogLevel logLevel)
        {
            return adapter.IsEnabled(logLevel);
        }

        /// <summary>
        /// Logs a <see cref="F:Akka.Event.LogLevel.DebugLevel" /> message.
        /// </summary>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Debug(string format, params object[] args)
        {
            adapter.Debug(format, BuildArgs(args));
        }

        /// <summary>
        /// Logs a <see cref="F:Akka.Event.LogLevel.InfoLevel" /> message.
        /// </summary>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Info(string format, params object[] args)
        {
            adapter.Info(format, BuildArgs(args));
        }

        /// <summary>
        /// Obsolete. Use <see cref="M:Akka.Event.ILoggingAdapter.Warning(System.String,System.Object[])" /> instead!
        /// </summary>
        /// <param name="format">N/A</param>
        /// <param name="args">N/A</param>
        public virtual void Warn(string format, params object[] args)
        {
            adapter.Warning(format, BuildArgs(args));
        }

        /// <summary>
        /// Logs a <see cref="F:Akka.Event.LogLevel.WarningLevel" /> message.
        /// </summary>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Warning(string format, params object[] args)
        {
            adapter.Warning(format, BuildArgs(args));
        }

        /// <summary>
        /// Logs a <see cref="F:Akka.Event.LogLevel.ErrorLevel" /> message.
        /// </summary>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Error(string format, params object[] args)
        {
            adapter.Error(format, BuildArgs(args));
        }

        /// <summary>
        /// Logs a <see cref="F:Akka.Event.LogLevel.ErrorLevel" /> message and associated exception.
        /// </summary>
        /// <param name="cause">The exception associated with this message.</param>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Error(Exception cause, string format, params object[] args)
        {
            adapter.Error(cause, format, BuildArgs(args));
        }

        /// <summary>Logs a message with a specified level.</summary>
        /// <param name="logLevel">The level used to log the message.</param>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Log(LogLevel logLevel, string format, params object[] args)
        {
            adapter.Log(logLevel, format, BuildArgs(args));
        }

        public ILoggingAdapter SetContextProperty(string name, object value, bool destructureObjects = false)
        {
            enrichers.Add(name, new PropertyEnricher(name, value, destructureObjects));
            return this;
        }

        private object[] BuildArgs(IEnumerable<object> args)
        {
            var newArgs = args.ToList();
            newArgs.AddRange(enrichers.Select(enricher => enricher.Value));
            return newArgs.ToArray();
        }
    }
}<commit_msg>ForContext() generate context trees and layered adapter<commit_after>﻿using System;
using System.Linq;
using System.Collections.Generic;
using Akka.Event;
using Serilog.Core;
using Serilog.Core.Enrichers;

namespace Akka.Logger.Serilog
{
    public class SerilogLoggingAdapter : ILoggingAdapter
    {
        /// <summary>
        /// Helper class that allows context trees.
        /// </summary>
        private class ContextNode
        {
            public ContextNode Next { get; set; }
            public ILogEventEnricher Enricher { get; set; }
        }

        private readonly ILoggingAdapter adapter;
        private readonly ContextNode enricherNode;

        public SerilogLoggingAdapter(ILoggingAdapter adapter)
            : this(adapter, null)
        {
        }

        private SerilogLoggingAdapter(ILoggingAdapter adapter, ContextNode enricherNode)
        {
            this.adapter = adapter;
            this.enricherNode = enricherNode;
        }

        /// <summary>
        /// Check to determine whether the <see cref="F:Akka.Event.LogLevel.DebugLevel" /> is enabled.
        /// </summary>
        public bool IsDebugEnabled => adapter.IsDebugEnabled;

        /// <summary>
        /// Check to determine whether the <see cref="F:Akka.Event.LogLevel.InfoLevel" /> is enabled.
        /// </summary>
        public bool IsInfoEnabled => adapter.IsInfoEnabled;

        /// <summary>
        /// Check to determine whether the <see cref="F:Akka.Event.LogLevel.WarningLevel" /> is enabled.
        /// </summary>
        public bool IsWarningEnabled => adapter.IsWarningEnabled;

        /// <summary>
        /// Check to determine whether the <see cref="F:Akka.Event.LogLevel.ErrorLevel" /> is enabled.
        /// </summary>
        public bool IsErrorEnabled => adapter.IsErrorEnabled;

        /// <summary>Determines whether a specific log level is enabled.</summary>
        /// <param name="logLevel">The log level that is being checked.</param>
        /// <returns><c>true</c> if the specified level is enabled; otherwise <c>false</c>.</returns>
        public bool IsEnabled(LogLevel logLevel)
        {
            return adapter.IsEnabled(logLevel);
        }

        /// <summary>
        /// Logs a <see cref="F:Akka.Event.LogLevel.DebugLevel" /> message.
        /// </summary>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Debug(string format, params object[] args)
        {
            adapter.Debug(format, BuildArgs(args));
        }

        /// <summary>
        /// Logs a <see cref="F:Akka.Event.LogLevel.InfoLevel" /> message.
        /// </summary>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Info(string format, params object[] args)
        {
            adapter.Info(format, BuildArgs(args));
        }

        /// <summary>
        /// Obsolete. Use <see cref="M:Akka.Event.ILoggingAdapter.Warning(System.String,System.Object[])" /> instead!
        /// </summary>
        /// <param name="format">N/A</param>
        /// <param name="args">N/A</param>
        public virtual void Warn(string format, params object[] args)
        {
            adapter.Warning(format, BuildArgs(args));
        }

        /// <summary>
        /// Logs a <see cref="F:Akka.Event.LogLevel.WarningLevel" /> message.
        /// </summary>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Warning(string format, params object[] args)
        {
            adapter.Warning(format, BuildArgs(args));
        }

        /// <summary>
        /// Logs a <see cref="F:Akka.Event.LogLevel.ErrorLevel" /> message.
        /// </summary>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Error(string format, params object[] args)
        {
            adapter.Error(format, BuildArgs(args));
        }

        /// <summary>
        /// Logs a <see cref="F:Akka.Event.LogLevel.ErrorLevel" /> message and associated exception.
        /// </summary>
        /// <param name="cause">The exception associated with this message.</param>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Error(Exception cause, string format, params object[] args)
        {
            adapter.Error(cause, format, BuildArgs(args));
        }

        /// <summary>Logs a message with a specified level.</summary>
        /// <param name="logLevel">The level used to log the message.</param>
        /// <param name="format">The message that is being logged.</param>
        /// <param name="args">An optional list of items used to format the message.</param>
        public virtual void Log(LogLevel logLevel, string format, params object[] args)
        {
            adapter.Log(logLevel, format, BuildArgs(args));
        }

        public ILoggingAdapter SetContextProperty(string name, object value, bool destructureObjects = false)
        {
            var contextProperty = new PropertyEnricher(name, value, destructureObjects);

            var contextNode = new ContextNode
            {
                Enricher = contextProperty,
                Next = enricherNode
            };

            return new SerilogLoggingAdapter(adapter, contextNode);
        }

        private object[] BuildArgs(IEnumerable<object> args)
        {
            var newArgs = args.ToList();
            if (enricherNode != null)
            {
                var currentNode = enricherNode;
                while (currentNode != null)
                {
                    newArgs.Add(currentNode.Enricher);
                    currentNode = currentNode.Next;
                }
            }
            return newArgs.ToArray();
        }
    }
}
{'fraction_non_alphanumeric': 0.12538304392236976, 'fraction_numerical': 0.0, 'mean_word_length': 2.095100105374078, 'pattern_counts': {'":': 0, '<': 157, '<?xml version=': 0, '>': 166, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6712938', 'n_tokens_mistral': 3100, 'n_tokens_neox': 3029, 'n_words': 869}