<commit_before>﻿using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ApplicationInsights.TelemetryReplication.AspNetCore
{
    public class TelemetryReplicationMiddleware
    {
        private readonly RequestDelegate next;
        private readonly Uri proxyUri;
        private readonly string proxyPath;
        private readonly TelemetryConfiguration telemetryConfiguration;
        private readonly ILogger logger;
        /// <summary>
        /// Initiate TelemetryReplicationMiddleware instance.
        /// </summary>
        /// <param name="appId">Id for this application.</param>
        /// <param name="next">Next request delegate.</param>
        /// <param name="proxyUri">Absolute uri of the telemetry proxy.</param>
        /// <param name="telemetryConfiguration">Telemetry configuration.</param>
        /// <param name="loggerFactory">Logger factory</param>
        public TelemetryReplicationMiddleware(
            AppId appId,
            RequestDelegate next,
            Uri proxyUri,
            TelemetryConfiguration telemetryConfiguration,
            ILoggerFactory loggerFactory)
        {
            if (appId == null)
            {
                throw new ArgumentNullException(nameof(appId));
            }
            if (proxyUri == null)
            {
                throw new ArgumentNullException(nameof(proxyUri));
            }
            if (false == proxyUri.IsAbsoluteUri)
            {
                throw new ArgumentException("proxyUri must be an absolute uri.");
            }
            if (telemetryConfiguration == null)
            {
                telemetryConfiguration = TelemetryConfiguration.Active;
            }
            if (loggerFactory == null)
            {
                logger = new NoopLogger(nameof(TelemetryReplicationMiddleware));
            }
            else
            {
                logger = loggerFactory.CreateLogger<TelemetryReplicationMiddleware>();
            }

            this.next = next;
            this.proxyUri = proxyUri;
            proxyPath = $"/{proxyUri.GetComponents(UriComponents.Path, UriFormat.UriEscaped).Trim('/')}";
            this.telemetryConfiguration = telemetryConfiguration;
            AddTelemetryProcessor(appId, telemetryConfiguration);
        }

        private void AddTelemetryProcessor(
            AppId appId, 
            TelemetryConfiguration telemetryConfiguration)
        {
            telemetryConfiguration
                .TelemetryProcessorChainBuilder
                .UseAppId(appId);
        }

        private int checker = 0;
        public async Task Invoke(HttpContext context)
        {
            if (Interlocked.CompareExchange(ref checker, 1, 0) == 0)
            {
                telemetryConfiguration
                    .UseTelemetryProxy(proxyUri.ToString());
                logger.LogInformation($"The end-point of Telemetry proxy has been determinated. {telemetryConfiguration.TelemetryChannel.EndpointAddress}");
            }
            if (context.Request.Path.Equals(proxyPath, StringComparison.OrdinalIgnoreCase))
            {
                logger.LogDebug($"A telemetry transmission({context.TraceIdentifier}) is being processed by the TelemetryProxy.");
                var proxy = context.RequestServices.GetService<TelemetryProxy>();
                var headers = context.Request.Headers
                    .Select(header => new KeyValuePair<string, IEnumerable<string>>(
                        header.Key,
                        header.Value));
                var response = await proxy.ProcessAsync(context.Request.Body, headers);
                foreach (var header in response.Headers)
                {
                    context.Response.Headers.Add(header.Key, new StringValues(header.Value.ToArray()));
                }
                context.Response.StatusCode = (int)response.StatusCode;
                await context.Response.WriteAsync(await response.Content.ReadAsStringAsync(), Encoding.UTF8);
                logger.LogDebug($"A telemetry transmission({context.TraceIdentifier}) is completed.");
            }
            else
            {
                await next(context);
            }
        }

        private class NoopLogger : ILogger
        {
            private readonly string logName;
            public NoopLogger(string logName)
            {
                this.logName = logName;
            }
            public IDisposable BeginScope<TState>(TState state)
            {
                return Noop.Instance;
            }

            private class Noop : IDisposable
            {
                public static Noop Instance = new Noop();
                public void Dispose()
                {
                    // noop.
                }
            }

            public bool IsEnabled(LogLevel logLevel)
            {
                return true;
            }
<commit_msg>add debug information to the middleware<commit_after>﻿using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ApplicationInsights.TelemetryReplication.AspNetCore
{
    public class TelemetryReplicationMiddleware
    {
        private readonly RequestDelegate next;
        private readonly Uri proxyUri;
        private readonly string proxyPath;
        private readonly TelemetryConfiguration telemetryConfiguration;
        private readonly ILogger logger;
        /// <summary>
        /// Initiate TelemetryReplicationMiddleware instance.
        /// </summary>
        /// <param name="appId">Id for this application.</param>
        /// <param name="next">Next request delegate.</param>
        /// <param name="proxyUri">Absolute uri of the telemetry proxy.</param>
        /// <param name="telemetryConfiguration">Telemetry configuration.</param>
        /// <param name="loggerFactory">Logger factory</param>
        public TelemetryReplicationMiddleware(
            AppId appId,
            RequestDelegate next,
            Uri proxyUri,
            TelemetryConfiguration telemetryConfiguration,
            ILoggerFactory loggerFactory)
        {
            if (appId == null)
            {
                throw new ArgumentNullException(nameof(appId));
            }
            if (proxyUri == null)
            {
                throw new ArgumentNullException(nameof(proxyUri));
            }
            if (false == proxyUri.IsAbsoluteUri)
            {
                throw new ArgumentException("proxyUri must be an absolute uri.");
            }
            if (telemetryConfiguration == null)
            {
                telemetryConfiguration = TelemetryConfiguration.Active;
            }
            if (loggerFactory == null)
            {
                logger = new NoopLogger(nameof(TelemetryReplicationMiddleware));
            }
            else
            {
                logger = loggerFactory.CreateLogger<TelemetryReplicationMiddleware>();
            }

            this.next = next;
            this.proxyUri = proxyUri;
            proxyPath = $"/{proxyUri.GetComponents(UriComponents.Path, UriFormat.UriEscaped).Trim('/')}";
            this.telemetryConfiguration = telemetryConfiguration;
            AddTelemetryProcessor(appId, telemetryConfiguration);
        }

        private void AddTelemetryProcessor(
            AppId appId, 
            TelemetryConfiguration telemetryConfiguration)
        {
            telemetryConfiguration
                .TelemetryProcessorChainBuilder
                .UseAppId(appId);
        }

        private int checker = 0;
        public async Task Invoke(HttpContext context)
        {
            if (Interlocked.CompareExchange(ref checker, 1, 0) == 0)
            {
                telemetryConfiguration
                    .UseTelemetryProxy(proxyUri.ToString());
                logger.LogInformation($"The end-point of Telemetry proxy has been determinated. {telemetryConfiguration.TelemetryChannel.EndpointAddress}");
            }
            if (context.Request.Path.Equals(proxyPath, StringComparison.OrdinalIgnoreCase))
            {
                try
                {
                    await ProcessAsync(context);
                }
                catch (Exception ex)
                {
                    context.Response.StatusCode = 500;
                    var message = ex.Message;
                    var stream = new MemoryStream();
                    using (var sw = new StreamWriter(stream))
                    {
                        sw.WriteLine($"{message}\n{ex.StackTrace}");
                        if (ex.InnerException != null)
                        {
                            sw.WriteLine($"inner exception:");
                            sw.WriteLine($"{ex.InnerException.Message}\n{ex.StackTrace}");
                        }
                        context.Response.Body = stream;
                    }
                }
            }
            else
            {
                await next(context);
            }
        }

        private async Task ProcessAsync(HttpContext context)
        {
            logger.LogDebug($"A telemetry transmission({context.TraceIdentifier}) is being processed by the TelemetryProxy.");
            var proxy = context.RequestServices.GetService<TelemetryProxy>();
            var headers = context.Request.Headers
                .Select(header => new KeyValuePair<string, IEnumerable<string>>(
                    header.Key,
                    header.Value));
            var response = await proxy.ProcessAsync(context.Request.Body, headers);
            foreach (var header in response.Headers)
            {
                context.Response.Headers.Add(header.Key, new StringValues(header.Value.ToArray()));
            }
            context.Response.StatusCode = (int)response.StatusCode;
            await context.Response.WriteAsync(await response.Content.ReadAsStringAsync(), Encoding.UTF8);
            logger.LogDebug($"A telemetry transmission({context.TraceIdentifier}) is completed.");
        }

        private class NoopLogger : ILogger
        {
            private readonly string logName;
            public NoopLogger(string logName)
            {
                this.logName = logName;
            }
            public IDisposable BeginScope<TState>(TState state)
            {
                return Noop.Instance;
            }

            private class Noop : IDisposable
            {
                public static Noop Instance = new Noop();
                public void Dispose()
                {
                    // noop.
                }
            }

            public bool IsEnabled(LogLevel logLevel)
            {
                return true;
            }

{'fraction_non_alphanumeric': 0.08109772187527486, 'fraction_numerical': 0.0011434602867446565, 'mean_word_length': 1.69878946119155, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 39, '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': '2566347', 'n_tokens_mistral': 2597, 'n_tokens_neox': 2522, 'n_words': 565}