@@ -3,6 +3,7 @@

 using System;
 using System.IO;
+using System.Net;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Http;

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

namespace SampleApp
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(LogLevel.Trace);
            var logger = loggerFactory.CreateLogger("Default");

            app.Run(async context =>
            {
                var connectionFeature = context.Connection;
                logger.LogDebug($"Peer: {connectionFeature.RemoteIpAddress?.ToString()}:{connectionFeature.RemotePort}"
                    + $"{Environment.NewLine}"
                    + $"Sock: {connectionFeature.LocalIpAddress?.ToString()}:{connectionFeature.LocalPort}");

                var response = $"hello, world{Environment.NewLine}";
                context.Response.ContentLength = response.Length;
                context.Response.ContentType = "text/plain";
                await context.Response.WriteAsync(response);
            });
        }

        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseKestrel(options =>
                {
                    // options.ThreadCount = 4;
                    options.NoDelay = true;
                    options.UseHttps("testCert.pfx", "testPassword");
                    options.UseConnectionLogging();
                })
                .UseUrls("http://localhost:5000", "https://localhost:5001")
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup<Startup>()
                .Build();

            // The following section should be used to demo sockets
            //var addresses = application.GetAddresses();
            //addresses.Clear();
            //addresses.Add("http://unix:/tmp/kestrel-test.sock");

            host.Run();
        }
    }
}


@@ -16,6 +16,7 @@
 //

 using System.Collections.Generic;
+using Nethermind.Abi;
 using Nethermind.Consensus.Transactions;
 using Nethermind.Core;

//  Copyright (c) 2018 Demerzel Solutions Limited
//  This file is part of the Nethermind library.
//
//  The Nethermind library is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  The Nethermind library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using System.Collections.Generic;
using Nethermind.Consensus.Transactions;
using Nethermind.Core;

namespace Nethermind.Consensus.AuRa.Validators
{
    public partial class ContractBasedValidator : ITxSource
    {
        private readonly long _posdaoTransition;

        public IEnumerable<Transaction> GetTransactions(BlockHeader parent, long gasLimit)
        {
            if (ForSealing)
            {
                var newBlockNumber = parent.Number + 1;
                if (newBlockNumber < _posdaoTransition)
                {
                    if (_logger.IsTrace) _logger.Trace("Skipping a call to emitInitiateChange");
                }
                else
                {
                    bool emitInitChangeCallable = false;

                    try
                    {
                        emitInitChangeCallable = ValidatorContract.EmitInitiateChangeCallable(parent);
                    }
                    catch (AuRaException e)
                    {
                        if (_logger.IsError) _logger.Error($"Call to {nameof(ValidatorContract.EmitInitiateChangeCallable)} failed.", e);
                    }

                    if (emitInitChangeCallable)
                    {
                        if (_logger.IsTrace) _logger.Trace($"New block #{newBlockNumber} issued ― calling emitInitiateChange()");
                        Metrics.EmitInitiateChange++;
                        yield return ValidatorContract.EmitInitiateChange();
                    }
                    else
                    {
                        if (_logger.IsTrace) _logger.Trace($"New block #{newBlockNumber} issued ― no need to call emitInitiateChange()");
                    }
                }
            }
        }
    }
}


@@ -100,15 +100,15 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection
             bool isRunStartingNow,
             ITestMessageEventHandler runEventsHandler)
         {
-            bool areTestCaseLevelEventsRequired = false;
-            bool isDataCollectionStarted = false;
+            var areTestCaseLevelEventsRequired = false;
+            var isDataCollectionStarted = false;
             IDictionary<string, string> environmentVariables = null;

             var dataCollectionEventsPort = 0;
             this.InvokeDataCollectionServiceAction(
             () =>
             {
-                var result = this.dataCollectionRequestSender.SendBeforeTestRunStartAndGetResult(settingsXml);
+                var result = this.dataCollectionRequestSender.SendBeforeTestRunStartAndGetResult(this.settingsXml, runEventsHandler);
                 areTestCaseLevelEventsRequired = result.AreTestCaseLevelEventsRequired;
                 environmentVariables = result.EnvironmentVariables;
                 dataCollectionEventsPort = result.DataCollectionEventsPort;

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;

    using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces;
    using Microsoft.VisualStudio.TestPlatform.ObjectModel;
    using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
    using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.DataCollection.Interfaces;
    using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.DataCollection;

    /// <summary>
    /// The test data collection client.
    /// </summary>
    internal class ProxyDataCollectionManager : IProxyDataCollectionManager
    {
        private const string PortOption = "--port";

        private IDataCollectionRequestSender dataCollectionRequestSender;
        private IDataCollectionLauncher dataCollectionLauncher;
        private string settingsXml;

        /// <summary>
        /// Initializes a new instance of the <see cref="ProxyDataCollectionManager"/> class.
        /// </summary>
        /// <param name="arch">
        /// The arch.
        /// </param>
        /// <param name="settingsXml">
        /// The settings Xml.
        /// </param>
        public ProxyDataCollectionManager(Architecture arch, string settingsXml)
            : this(arch, settingsXml, new DataCollectionRequestSender(), new DataCollectionLauncher())
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ProxyDataCollectionManager"/> class.
        /// </summary>
        /// <param name="dataCollectionRequestSender">
        /// The data collection request sender.
        /// </param>
        /// <param name="dataCollectionLauncher">
        /// The data collection launcher.
        /// </param>
        internal ProxyDataCollectionManager(Architecture arch, string settingsXml, IDataCollectionRequestSender dataCollectionRequestSender, IDataCollectionLauncher dataCollectionLauncher)
        {
            this.settingsXml = settingsXml;
            this.dataCollectionRequestSender = dataCollectionRequestSender;
            this.dataCollectionLauncher = dataCollectionLauncher;
            this.InitializeSocketCommunication(arch);
        }

        /// <summary>
        /// Invoked after ending of test run
        /// </summary>
        /// <param name="isCanceled">
        /// The is Canceled.
        /// </param>
        /// <param name="runEventsHandler">
        /// The run Events Handler.
        /// </param>
        /// <returns>
        /// The <see cref="Collection"/>.
        /// </returns>
        public Collection<AttachmentSet> AfterTestRunEnd(bool isCanceled, ITestMessageEventHandler runEventsHandler)
        {
            Collection<AttachmentSet> attachmentSet = null;
            this.InvokeDataCollectionServiceAction(
           () =>
           {
               attachmentSet = this.dataCollectionRequestSender.SendAfterTestRunStartAndGetResult();
           },
                runEventsHandler);
            return attachmentSet;
        }

        /// <summary>
        /// Invoked before starting of test run
        /// </summary>
        /// <param name="resetDataCollectors">
        /// The reset Data Collectors.
        /// </param>
        /// <param name="isRunStartingNow">
        /// The is Run Starting Now.
        /// </param>
        /// <param name="runEventsHandler">
        /// The run Events Handler.
        /// </param>
        /// <returns>
        /// BeforeTestRunStartResult object
        /// </returns>
        public DataCollectionParameters BeforeTestRunStart(
            bool resetDataCollectors,
            bool isRunStartingNow,
            ITestMessageEventHandler runEventsHandler)
        {
            bool areTestCaseLevelEventsRequired = false;
            bool isDataCollectionStarted = false;
            IDictionary<string, string> environmentVariables = null;

            var dataCollectionEventsPort = 0;
            this.InvokeDataCollectionServiceAction(
            () =>
            {
                var result = this.dataCollectionRequestSender.SendBeforeTestRunStartAndGetResult(settingsXml);
                areTestCaseLevelEventsRequired = result.AreTestCaseLevelEventsRequired;
                environmentVariables = result.EnvironmentVariables;
                dataCollectionEventsPort = result.DataCollectionEventsPort;
            },
                runEventsHandler);
            return new DataCollectionParameters(
                            isDataCollectionStarted,
                            areTestCaseLevelEventsRequired,
                            environmentVariables,
                            dataCollectionEventsPort);
        }

        /// <summary>
        /// The dispose.
        /// </summary>
        public void Dispose()
        {
            this.dataCollectionRequestSender.Close();
        }

        /// <summary>
        /// The initialize socket communication.
        /// </summary>
        /// <param name="arch">
        /// The arch.
        /// </param>
        internal void InitializeSocketCommunication(Architecture arch)
        {
            var port = this.dataCollectionRequestSender.InitializeCommunication();

            this.dataCollectionLauncher.Initialize(arch);
            this.dataCollectionLauncher.LaunchDataCollector(null, this.GetCommandLineArguments(port));
            this.dataCollectionRequestSender.WaitForRequestHandlerConnection(connectionTimeout: 5000);
        }

        private void InvokeDataCollectionServiceAction(Action action, ITestMessageEventHandler runEventsHandler)
        {
            try
            {
                if (EqtTrace.IsVerboseEnabled)
                {
                    EqtTrace.Verbose("ProxyDataCollectionManager.InvokeDataCollectionServiceAction: Starting.");
                }

                action();
                if (EqtTrace.IsInfoEnabled)
                {
                    EqtTrace.Info("ProxyDataCollectionManager.InvokeDataCollectionServiceAction: Completed.");
                }
            }
            catch (Exception ex)
            {
                if (EqtTrace.IsWarningEnabled)
                {
                    EqtTrace.Warning("ProxyDataCollectionManager.InvokeDataCollectionServiceAction: TestPlatformException = {0}.", ex);
                }

                this.HandleExceptionMessage(runEventsHandler, ex);
            }
        }

        private void HandleExceptionMessage(ITestMessageEventHandler runEventsHandler, Exception exception)
        {
            if (EqtTrace.IsErrorEnabled)
            {
                EqtTrace.Error(exception);
            }

            runEventsHandler.HandleLogMessage(ObjectModel.Logging.TestMessageLevel.Error, exception.Message);
        }

        private IList<string> GetCommandLineArguments(int portNumber)
        {
            var commandlineArguments = new List<string>();

            commandlineArguments.Add(PortOption);
            commandlineArguments.Add(portNumber.ToString());

            return commandlineArguments;
        }
    }
}


@@ -42,7 +42,7 @@ namespace OpenTelemetry.Context.Propagation
         void Inject<T>(PropagationContext context, T carrier, Action<T, string, string> setter);

         /// <summary>
-        /// Extracts activity context from textual representation.
+        /// Extracts the context from a carrier.
         /// </summary>
         /// <typeparam name="T">Type of object to extract context from. Typically HttpRequest or similar.</typeparam>
         /// <param name="context">The default context to be used if Extract fails.</param>

// <copyright file="IPropagator.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;

namespace OpenTelemetry.Context.Propagation
{
    /// <summary>
    /// Text format wire context propagator. Helps to extract and inject context from textual
    /// representation (typically http headers or metadata collection).
    /// </summary>
    public interface IPropagator
    {
        /// <summary>
        /// Gets the list of headers used by propagator. The use cases of this are:
        ///   * allow pre-allocation of fields, especially in systems like gRPC Metadata
        ///   * allow a single-pass over an iterator (ex OpenTracing has no getter in TextMap).
        /// </summary>
        ISet<string> Fields { get; }

        /// <summary>
        /// Injects textual representation of activity context to transmit over the wire.
        /// </summary>
        /// <typeparam name="T">Type of an object to set context on. Typically HttpRequest or similar.</typeparam>
        /// <param name="context">The default context to transmit over the wire.</param>
        /// <param name="carrier">Object to set context on. Instance of this object will be passed to setter.</param>
        /// <param name="setter">Action that will set name and value pair on the object.</param>
        void Inject<T>(PropagationContext context, T carrier, Action<T, string, string> setter);

        /// <summary>
        /// Extracts activity context from textual representation.
        /// </summary>
        /// <typeparam name="T">Type of object to extract context from. Typically HttpRequest or similar.</typeparam>
        /// <param name="context">The default context to be used if Extract fails.</param>
        /// <param name="carrier">Object to extract context from. Instance of this object will be passed to the getter.</param>
        /// <param name="getter">Function that will return string value of a key with the specified name.</param>
        /// <returns>Context from it's text representation.</returns>
        PropagationContext Extract<T>(PropagationContext context, T carrier, Func<T, string, IEnumerable<string>> getter);
    }
}


@@ -31,9 +31,7 @@ namespace Nethermind.Db
         public IDb ChtDb { get; } = new MemDb();
         public IDb BeamStateDb { get; } = new MemDb();

-        public IDb BaselineTreeDb { get; } = new MemDb();
-
-        public IDb BaselineTreeMetadataDb { get; } = new MemDb();
+        public IEnumerable<IDb> OtherDbs => _otherDbs;

         public void Dispose()
         {

//  Copyright (c) 2018 Demerzel Solutions Limited
//  This file is part of the Nethermind library.
//
//  The Nethermind library is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  The Nethermind library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.

namespace Nethermind.Db
{
    public class MemDbProvider : IDbProvider
    {
        public ISnapshotableDb StateDb { get; } = new StateDb();
        public ISnapshotableDb CodeDb { get; } = new StateDb();
        public IColumnsDb<ReceiptsColumns> ReceiptsDb { get; } = new MemColumnsDb<ReceiptsColumns>();
        public IDb BlocksDb { get; } = new MemDb();
        public IDb HeadersDb { get; } = new MemDb();
        public IDb BlockInfosDb { get; } = new MemDb();
        public IDb PendingTxsDb { get; } = new MemDb();
        public IDb ConfigsDb { get; } = new MemDb();
        public IDb EthRequestsDb { get; } = new MemDb();
        public IDb BloomDb { get; } = new MemDb();
        public IDb ChtDb { get; } = new MemDb();
        public IDb BeamStateDb { get; } = new MemDb();

        public IDb BaselineTreeDb { get; } = new MemDb();

        public IDb BaselineTreeMetadataDb { get; } = new MemDb();

        public void Dispose()
        {
            StateDb?.Dispose();
            CodeDb?.Dispose();
            ReceiptsDb?.Dispose();
            BlocksDb?.Dispose();
            BlockInfosDb?.Dispose();
            PendingTxsDb?.Dispose();
            ConfigsDb?.Dispose();
            EthRequestsDb?.Dispose();
            BloomDb?.Dispose();
            ChtDb?.Dispose();
            BaselineTreeDb?.Dispose();
            BaselineTreeMetadataDb?.Dispose();
        }
    }
}


@@ -20,7 +20,7 @@ namespace Datadog.Trace.ClrProfiler.IntegrationTests.AdoNet
         {
             foreach (object[] item in PackageVersions.MySqlData)
             {
-                if ((string)item[0] == string.Empty || !((string)item[0]).StartsWith("8"))
+                if (!((string)item[0]).StartsWith("8"))
                 {
                     continue;
                 }

using System.Collections.Generic;
using System.Linq;
using Datadog.Core.Tools;
using Datadog.Trace.Configuration;
using Datadog.Trace.TestHelpers;
using Xunit;
using Xunit.Abstractions;

namespace Datadog.Trace.ClrProfiler.IntegrationTests.AdoNet
{
    public class MySqlCommandTests : TestHelper
    {
        public MySqlCommandTests(ITestOutputHelper output)
            : base("MySql", output)
        {
            SetServiceVersion("1.0.0");
        }

        public static IEnumerable<object[]> GetMySql8Data()
        {
            foreach (object[] item in PackageVersions.MySqlData)
            {
                if ((string)item[0] == string.Empty || !((string)item[0]).StartsWith("8"))
                {
                    continue;
                }

                yield return item.Concat(new object[] { false, false, }).ToArray();
                yield return item.Concat(new object[] { true, false, }).ToArray();
                yield return item.Concat(new object[] { true, true, }).ToArray();
            }
        }

        public static IEnumerable<object[]> GetOldMySqlData()
        {
            foreach (object[] item in PackageVersions.MySqlData)
            {
                if ((string)item[0] == string.Empty || ((string)item[0]).StartsWith("8"))
                {
                    continue;
                }

                yield return item.Concat(new object[] { false, false, }).ToArray();
                yield return item.Concat(new object[] { true, false, }).ToArray();
                yield return item.Concat(new object[] { true, true, }).ToArray();
            }
        }

        [Theory]
        [MemberData(nameof(GetMySql8Data))]
        [Trait("Category", "EndToEnd")]
        public void SubmitsTracesWithNetStandardInMySql8(string packageVersion, bool enableCallTarget, bool enableInlining)
        {
            SubmitsTracesWithNetStandard(packageVersion, enableCallTarget, enableInlining);
        }

        [Theory]
        [MemberData(nameof(GetOldMySqlData))]
        [Trait("Category", "EndToEnd")]
        [Trait("Category", "ArmUnsupported")]
        public void SubmitsTracesWithNetStandardInOldMySql(string packageVersion, bool enableCallTarget, bool enableInlining)
        {
            SubmitsTracesWithNetStandard(packageVersion, enableCallTarget, enableInlining);
        }

        [Theory]
        [InlineData(false, false)]
        [InlineData(true, false)]
        [InlineData(true, true)]
        [Trait("Category", "EndToEnd")]
        public void SpansDisabledByAdoNetExcludedTypes(bool enableCallTarget, bool enableInlining)
        {
            SetCallTargetSettings(enableCallTarget, enableInlining);

            var totalSpanCount = 21;

            const string dbType = "mysql";
            const string expectedOperationName = dbType + ".query";

            SetEnvironmentVariable(ConfigurationKeys.AdoNetExcludedTypes, "System.Data.SqlClient.SqlCommand;Microsoft.Data.SqlClient.SqlCommand;MySql.Data.MySqlClient.MySqlCommand;Npgsql.NpgsqlCommand");

            int agentPort = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
            using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port))
            {
                Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                var spans = agent.WaitForSpans(totalSpanCount, returnAllOperations: true);
                Assert.NotEmpty(spans);
                Assert.Empty(spans.Where(s => s.Name.Equals(expectedOperationName)));
            }
        }

        private void SubmitsTracesWithNetStandard(string packageVersion, bool enableCallTarget, bool enableInlining)
        {
            SetCallTargetSettings(enableCallTarget, enableInlining);

            // Note: The automatic instrumentation currently bails out on the generic wrappers.
            // Once this is implemented, this will add another 1 group for the direct assembly reference
            // and another 1 group for the netstandard assembly reference
#if NET452
            var expectedSpanCount = 50; // 7 queries * 7 groups + 1 internal query
#else
            var expectedSpanCount = 78; // 7 queries * 11 groups + 1 internal query
            if (packageVersion == "6.8.8")
            {
                expectedSpanCount = 76; // For this version the callsite instrumentation returns 2 spans less.
            }
#endif

            if (enableCallTarget)
            {
#if NET452
                expectedSpanCount = 62;
#else
                expectedSpanCount = 97;
#endif
            }

            const string dbType = "mysql";
            const string expectedOperationName = dbType + ".query";
            const string expectedServiceName = "Samples.MySql-" + dbType;

            // NOTE: opt into the additional instrumentation of calls into netstandard.dll
            SetEnvironmentVariable("DD_TRACE_NETSTANDARD_ENABLED", "true");

            int agentPort = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
            using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, packageVersion: packageVersion))
            {
                Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                var spans = agent.WaitForSpans(expectedSpanCount, operationName: expectedOperationName);
                Assert.Equal(expectedSpanCount, spans.Count);

                foreach (var span in spans)
                {
                    Assert.Equal(expectedOperationName, span.Name);
                    Assert.Equal(expectedServiceName, span.Service);
                    Assert.Equal(SpanTypes.Sql, span.Type);
                    Assert.Equal(dbType, span.Tags[Tags.DbType]);
                    Assert.False(span.Tags?.ContainsKey(Tags.Version), "External service span should not have service version tag.");
                }
            }
        }
    }
}


@@ -14,6 +14,8 @@
 //  You should have received a copy of the GNU Lesser General Public License
 //  along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.

+using Nethermind.Core;
+
 namespace Nethermind.KeyStore.Config
 {
     public class KeyStoreConfig : IKeyStoreConfig

//  Copyright (c) 2018 Demerzel Solutions Limited
//  This file is part of the Nethermind library.
//
//  The Nethermind library is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  The Nethermind library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.

namespace Nethermind.KeyStore.Config
{
    public class KeyStoreConfig : IKeyStoreConfig
    {
        public string KeyStoreDirectory { get; set; } = "keystore";
        public string KeyStoreEncoding { get; set; } = "UTF-8";
        public string Kdf { get; set; } = "scrypt";
        public string Cipher { get; set; } = "aes-128-ctr";
        public int KdfparamsDklen { get; set; } = 32;
        public int KdfparamsN { get; set; } = 262144;
        public int KdfparamsP { get; set; } = 1;
        public int KdfparamsR { get; set; } = 8;

        public int KdfparamsSaltLen { get; set; } = 32;
        public int SymmetricEncrypterBlockSize { get; set; } = 128;
        public int SymmetricEncrypterKeySize { get; set; } = 128;
        public int IVSize { get; set; } = 16;
        public string TestNodeKey { get; set; }
    }
}


@@ -112,6 +112,13 @@ namespace Datadog.Trace.Tests.Logging
             Assert.DoesNotContain(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys());
             Assert.DoesNotContain(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());

+            // Scope: N/A
+            // Custom property: N/A
+            logEvent = filteredLogs[logIndex++];
+            Assert.DoesNotContain(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys());
+            Assert.DoesNotContain(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys());
+            Assert.DoesNotContain(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());
+
             // Scope: N/A
             // Custom property: SET
             logEvent = filteredLogs[logIndex++];

using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Datadog.Trace.Logging;
using Datadog.Trace.Logging.LogProviders;
using log4net.Appender;
using log4net.Config;
using log4net.Core;
using log4net.Layout;
using Newtonsoft.Json;
using Xunit;

namespace Datadog.Trace.Tests.Logging
{
    [Collection(nameof(Datadog.Trace.Tests.Logging))]
    public class Log4NetLogProviderTests
    {
        private readonly ILogProvider _logProvider;
        private readonly ILog _logger;
        private readonly MemoryAppender _memoryAppender;

        public Log4NetLogProviderTests()
        {
            _memoryAppender = new MemoryAppender();
            var repository = log4net.LogManager.GetRepository(Assembly.GetAssembly(typeof(log4net.LogManager)));
            BasicConfigurator.Configure(repository, _memoryAppender);

            _logProvider = new Log4NetLogProvider();
            LogProvider.SetCurrentLogProvider(_logProvider);
            _logger = new LoggerExecutionWrapper(_logProvider.GetLogger("Test"));
        }

        [Fact]
        public void EnabledLibLogSubscriberAddsTraceData()
        {
            // Assert that the Log4Net log provider is correctly being used
            Assert.IsType<Log4NetLogProvider>(LogProvider.CurrentLogProvider);

            // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE
            var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true);
            LoggingProviderTestHelpers.PerformParentChildScopeSequence(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope);

            // Filter the logs
            List<LoggingEvent> filteredLogs = new List<LoggingEvent>(_memoryAppender.GetEvents());
            filteredLogs.RemoveAll(log => !log.MessageObject.ToString().Contains(LoggingProviderTestHelpers.LogPrefix));

            int logIndex = 0;
            LoggingEvent logEvent;

            // Scope: Parent scope
            // Custom property: N/A
            logEvent = filteredLogs[logIndex++];
            logEvent.Contains(parentScope);
            Assert.DoesNotContain(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());

            // Scope: Parent scope
            // Custom property: SET
            logEvent = filteredLogs[logIndex++];
            logEvent.Contains(parentScope);
            Assert.Contains(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());
            Assert.Equal<int>(LoggingProviderTestHelpers.CustomPropertyValue, int.Parse(logEvent.Properties[LoggingProviderTestHelpers.CustomPropertyName].ToString()));

            // Scope: Child scope
            // Custom property: SET
            logEvent = filteredLogs[logIndex++];
            logEvent.Contains(childScope);
            Assert.Contains(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());
            Assert.Equal<int>(LoggingProviderTestHelpers.CustomPropertyValue, int.Parse(logEvent.Properties[LoggingProviderTestHelpers.CustomPropertyName].ToString()));

            // Scope: Parent scope
            // Custom property: SET
            logEvent = filteredLogs[logIndex++];
            logEvent.Contains(parentScope);
            Assert.Contains(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());
            Assert.Equal<int>(LoggingProviderTestHelpers.CustomPropertyValue, int.Parse(logEvent.Properties[LoggingProviderTestHelpers.CustomPropertyName].ToString()));

            // EXISTING: Verify the log event is decorated with the parent scope properties
            // Scope: Parent scope
            // Custom property: N/A
            logEvent = filteredLogs[logIndex++];
            logEvent.Contains(parentScope);
            Assert.DoesNotContain(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());

            // Scope: Default values of TraceId=0,SpanId=0
            // Custom property: N/A
            logEvent = filteredLogs[logIndex++];
            logEvent.Contains(traceId: 0, spanId: 0);
            Assert.DoesNotContain(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());
        }

        [Fact]
        public void DisabledLibLogSubscriberDoesNotAddTraceData()
        {
            // Assert that the Log4Net log provider is correctly being used
            Assert.IsType<Log4NetLogProvider>(LogProvider.CurrentLogProvider);

            // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE
            var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: false);
            LoggingProviderTestHelpers.PerformParentChildScopeSequence(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope);

            // Filter the logs
            List<LoggingEvent> filteredLogs = new List<LoggingEvent>(_memoryAppender.GetEvents());
            filteredLogs.RemoveAll(log => !log.MessageObject.ToString().Contains(LoggingProviderTestHelpers.LogPrefix));

            int logIndex = 0;
            LoggingEvent logEvent;

            // Scope: N/A
            // Custom property: N/A
            logEvent = filteredLogs[logIndex++];
            Assert.DoesNotContain(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys());
            Assert.DoesNotContain(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys());
            Assert.DoesNotContain(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());

            // Scope: N/A
            // Custom property: SET
            logEvent = filteredLogs[logIndex++];
            Assert.DoesNotContain(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys());
            Assert.DoesNotContain(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys());
            Assert.Contains(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());
            Assert.Equal<int>(LoggingProviderTestHelpers.CustomPropertyValue, int.Parse(logEvent.Properties[LoggingProviderTestHelpers.CustomPropertyName].ToString()));

            // Scope: N/A
            // Custom property: SET
            logEvent = filteredLogs[logIndex++];
            Assert.DoesNotContain(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys());
            Assert.DoesNotContain(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys());
            Assert.Contains(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());
            Assert.Equal<int>(LoggingProviderTestHelpers.CustomPropertyValue, int.Parse(logEvent.Properties[LoggingProviderTestHelpers.CustomPropertyName].ToString()));

            // Scope: N/A
            // Custom property: SET
            logEvent = filteredLogs[logIndex++];
            Assert.DoesNotContain(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys());
            Assert.DoesNotContain(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys());
            Assert.Contains(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());
            Assert.Equal<int>(LoggingProviderTestHelpers.CustomPropertyValue, int.Parse(logEvent.Properties[LoggingProviderTestHelpers.CustomPropertyName].ToString()));

            // Scope: N/A
            // Custom property: N/A
            logEvent = filteredLogs[logIndex++];
            Assert.DoesNotContain(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys());
            Assert.DoesNotContain(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys());
            Assert.DoesNotContain(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());

            // Scope: N/A
            // Custom property: N/A
            logEvent = filteredLogs[logIndex++];
            Assert.DoesNotContain(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys());
            Assert.DoesNotContain(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys());
            Assert.DoesNotContain(LoggingProviderTestHelpers.CustomPropertyName, logEvent.Properties.GetKeys());
        }

        /// <summary>
        /// Lightweight JSON-formatter for Log4Net inspired by https://github.com/Litee/log4net.Layout.Json
        /// </summary>
        internal class Log4NetJsonLayout : LayoutSkeleton
        {
            public override void ActivateOptions()
            {
            }

            public override void Format(TextWriter writer, LoggingEvent e)
            {
                var dic = new Dictionary<string, object>
                {
                    ["level"] = e.Level.DisplayName,
                    ["messageObject"] = e.MessageObject,
                    ["renderedMessage"] = e.RenderedMessage,
                    ["timestampUtc"] = e.TimeStamp.ToUniversalTime().ToString("O"),
                    ["logger"] = e.LoggerName,
                    ["thread"] = e.ThreadName,
                    ["exceptionObject"] = e.ExceptionObject,
                    ["exceptionObjectString"] = e.ExceptionObject == null ? null : e.GetExceptionString(),
                    ["userName"] = e.UserName,
                    ["domain"] = e.Domain,
                    ["identity"] = e.Identity,
                    ["location"] = e.LocationInformation.FullInfo,
                    ["properties"] = e.GetProperties()
                };
                writer.Write(JsonConvert.SerializeObject(dic));
            }
        }
    }
}


@@ -8,10 +8,11 @@
 namespace MvvmCross.iOS.Views
 {
     using System;
-
+    using Foundation;
     using MvvmCross.Binding.BindingContext;
     using MvvmCross.Core.ViewModels;
     using MvvmCross.Platform.iOS.Views;
+    using UIKit;

     public class MvxTabBarViewController
         : MvxEventSourceTabBarController

// MvxTabBarViewController.cs

// MvvmCross is licensed using Microsoft Public License (Ms-PL)
// Contributions and inspirations noted in readme.md and license.txt
//
// Project Lead - Stuart Lodge, @slodge, me@slodge.com

namespace MvvmCross.iOS.Views
{
    using System;

    using MvvmCross.Binding.BindingContext;
    using MvvmCross.Core.ViewModels;
    using MvvmCross.Platform.iOS.Views;

    public class MvxTabBarViewController
        : MvxEventSourceTabBarController
          , IMvxIosView
    {
        protected MvxTabBarViewController()
        {
            this.AdaptForBinding();
        }

        protected MvxTabBarViewController(IntPtr handle)
            : base(handle)
        {
            this.AdaptForBinding();
        }

        public object DataContext
        {
            get
            {
                // special code needed in TabBar because View is initialized during construction
                return this.BindingContext?.DataContext;
            }
            set { this.BindingContext.DataContext = value; }
        }

        public IMvxViewModel ViewModel
        {
            get { return this.DataContext as IMvxViewModel; }
            set { this.DataContext = value; }
        }

        public MvxViewModelRequest Request { get; set; }

        public IMvxBindingContext BindingContext { get; set; }
    }

    public class MvxTabBarViewController<TViewModel>
        : MvxTabBarViewController
          , IMvxIosView<TViewModel> where TViewModel : class, IMvxViewModel
    {
        protected MvxTabBarViewController()
        {
        }

        protected MvxTabBarViewController(IntPtr handle)
            : base(handle)
        {
        }

        public new TViewModel ViewModel
        {
            get { return (TViewModel)base.ViewModel; }
            set { base.ViewModel = value; }
        }
    }
}


@@ -26,8 +26,7 @@ namespace OpenTelemetry.Logs
     public class OpenTelemetryLoggerProvider : ILoggerProvider, ISupportExternalScope
     {
         internal BaseProcessor<LogRecord> Processor;
-        private readonly OpenTelemetryLoggerOptions options;
-        private readonly IDictionary<string, ILogger> loggers;
+        private readonly IDictionary<string, OpenTelemetryLogger> loggers = new Dictionary<string, OpenTelemetryLogger>(StringComparer.Ordinal);
         private bool disposed;
         private IExternalScopeProvider scopeProvider;

// <copyright file="OpenTelemetryLoggerProvider.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

#if NET461 || NETSTANDARD2_0
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace OpenTelemetry.Logs
{
    [ProviderAlias("OpenTelemetry")]
    public class OpenTelemetryLoggerProvider : ILoggerProvider, ISupportExternalScope
    {
        internal BaseProcessor<LogRecord> Processor;
        private readonly OpenTelemetryLoggerOptions options;
        private readonly IDictionary<string, ILogger> loggers;
        private bool disposed;
        private IExternalScopeProvider scopeProvider;

        static OpenTelemetryLoggerProvider()
        {
            // Accessing Sdk class is just to trigger its static ctor,
            // which sets default Propagators and default Activity Id format
            _ = Sdk.SuppressInstrumentation;
        }

        public OpenTelemetryLoggerProvider(IOptionsMonitor<OpenTelemetryLoggerOptions> options)
            : this(options?.CurrentValue)
        {
        }

        internal OpenTelemetryLoggerProvider(OpenTelemetryLoggerOptions options)
        {
            this.options = options ?? throw new ArgumentNullException(nameof(options));
            this.loggers = new Dictionary<string, ILogger>(StringComparer.Ordinal);

            foreach (var processor in options.Processors)
            {
                this.AddProcessor(processor);
            }
        }

        internal IExternalScopeProvider ScopeProvider
        {
            get
            {
                if (this.scopeProvider == null)
                {
                    this.scopeProvider = new LoggerExternalScopeProvider();
                }

                return this.scopeProvider;
            }
        }

        void ISupportExternalScope.SetScopeProvider(IExternalScopeProvider scopeProvider)
        {
            // TODO: set existing loggers
            this.scopeProvider = scopeProvider;
        }

        public ILogger CreateLogger(string categoryName)
        {
            lock (this.loggers)
            {
                ILogger logger;

                if (this.loggers.TryGetValue(categoryName, out logger))
                {
                    return logger;
                }

                logger = new OpenTelemetryLogger(categoryName, this);
                this.loggers.Add(categoryName, logger);
                return logger;
            }
        }

        /// <inheritdoc/>
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        internal OpenTelemetryLoggerProvider AddProcessor(BaseProcessor<LogRecord> processor)
        {
            if (processor == null)
            {
                throw new ArgumentNullException(nameof(processor));
            }

            if (this.Processor == null)
            {
                this.Processor = processor;
            }
            else if (this.Processor is CompositeProcessor<LogRecord> compositeProcessor)
            {
                compositeProcessor.AddProcessor(processor);
            }
            else
            {
                this.Processor = new CompositeProcessor<LogRecord>(new[]
                {
                    this.Processor,
                    processor,
                });
            }

            return this;
        }

        protected virtual void Dispose(bool disposing)
        {
            if (this.disposed)
            {
                return;
            }

            if (disposing)
            {
                // Wait for up to 5 seconds grace period
                this.Processor?.Shutdown(5000);
                this.Processor?.Dispose();
            }

            this.disposed = true;
        }
    }
}
#endif


@@ -17,12 +17,17 @@
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Timers;
+using Nethermind.Core.Caching;
+using Nethermind.Core.Timers;
 using Nethermind.Logging;
 using Nethermind.Stats.Model;

 namespace Nethermind.Stats
 {
-    public class NodeStatsManager : INodeStatsManager
+    public class NodeStatsManager : INodeStatsManager, IDisposable
     {
         private class NodeComparer : IEqualityComparer<Node>
         {

//  Copyright (c) 2021 Demerzel Solutions Limited
//  This file is part of the Nethermind library.
//
//  The Nethermind library is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  The Nethermind library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Nethermind.Logging;
using Nethermind.Stats.Model;

namespace Nethermind.Stats
{
    public class NodeStatsManager : INodeStatsManager
    {
        private class NodeComparer : IEqualityComparer<Node>
        {
            public bool Equals(Node x, Node y)
            {
                if (ReferenceEquals(x, null))
                {
                    return ReferenceEquals(y, null);
                }

                if (ReferenceEquals(y, null))
                {
                    return false;
                }

                return x.Id == y.Id;
            }

            public int GetHashCode(Node obj)
            {
                return obj?.GetHashCode() ?? 0;
            }
        }

        private readonly ILogger _logger;
        private readonly ConcurrentDictionary<Node, INodeStats> _nodeStats = new ConcurrentDictionary<Node, INodeStats>(new NodeComparer());

        public NodeStatsManager(ILogManager logManager)
        {
            _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager));
        }

        private INodeStats AddStats(Node node)
        {
            return new NodeStatsLight(node);
        }

        public INodeStats GetOrAdd(Node node)
        {
            if (node == null)
            {
                return null;
            }

            // to avoid allocations
            if (_nodeStats.TryGetValue(node, out INodeStats stats))
            {
                return stats;
            }

            return _nodeStats.GetOrAdd(node, AddStats);
        }

        public void ReportHandshakeEvent(Node node, ConnectionDirection direction)
        {
            INodeStats stats = GetOrAdd(node);
            stats.AddNodeStatsHandshakeEvent(direction);
        }

        public void ReportSyncEvent(Node node, NodeStatsEventType nodeStatsEvent)
        {
            INodeStats stats = GetOrAdd(node);
            stats.AddNodeStatsSyncEvent(nodeStatsEvent);
        }

        public void ReportEvent(Node node, NodeStatsEventType eventType)
        {
            INodeStats stats = GetOrAdd(node);
            stats.AddNodeStatsEvent(eventType);
        }

        public (bool Result, NodeStatsEventType? DelayReason) IsConnectionDelayed(Node node)
        {
            INodeStats stats = GetOrAdd(node);
            return stats.IsConnectionDelayed();
        }

        public CompatibilityValidationType? FindCompatibilityValidationResult(Node node)
        {
            INodeStats stats = GetOrAdd(node);
            return stats.FailedCompatibilityValidation;
        }

        public long GetCurrentReputation(Node node)
        {
            INodeStats stats = GetOrAdd(node);
            return stats.CurrentNodeReputation;
        }

        public void ReportP2PInitializationEvent(Node node, P2PNodeDetails p2PNodeDetails)
        {
            INodeStats stats = GetOrAdd(node);
            stats.AddNodeStatsP2PInitializedEvent(p2PNodeDetails);
        }

        public void ReportSyncPeerInitializeEvent(string protocol, Node node, SyncPeerNodeDetails syncPeerNodeDetails)
        {
            INodeStats stats = GetOrAdd(node);
            if (protocol == "eth")
                stats.AddNodeStatsEth62InitializedEvent(syncPeerNodeDetails);
            else if (protocol == "les")
                stats.AddNodeStatsLesInitializedEvent(syncPeerNodeDetails);
            else
                throw new ArgumentException($"Unknown protocol: {protocol}");
        }

        public void ReportFailedValidation(Node node, CompatibilityValidationType validationType)
        {
            INodeStats stats = GetOrAdd(node);
            stats.FailedCompatibilityValidation = validationType;
        }

        public void ReportDisconnect(Node node, DisconnectType disconnectType, DisconnectReason disconnectReason)
        {
            INodeStats stats = GetOrAdd(node);
            stats.AddNodeStatsDisconnectEvent(disconnectType, disconnectReason);
        }

        public long GetNewPersistedReputation(Node node)
        {
            INodeStats stats = GetOrAdd(node);
            return stats.NewPersistedNodeReputation;
        }

        public long GetCurrentPersistedReputation(Node node)
        {
            INodeStats stats = GetOrAdd(node);
            return stats.CurrentPersistedNodeReputation;
        }

        public bool HasFailedValidation(Node node)
        {
            INodeStats stats = GetOrAdd(node);
            return stats.FailedCompatibilityValidation != null;
        }

        public void ReportTransferSpeedEvent(Node node, TransferSpeedType type, long value)
        {
            INodeStats stats = GetOrAdd(node);
            stats.AddTransferSpeedCaptureEvent(type, value);
        }
    }
}


@@ -24,7 +24,7 @@ using OpenTelemetry.Internal;

 namespace OpenTelemetry.Trace.Internal
 {
-    internal class BroadcastActivityProcessor : ActivityProcessor, IDisposable
+    internal class BroadcastActivityProcessor : ActivityProcessor
     {
         private readonly IEnumerable<ActivityProcessor> processors;
         private bool isDisposed;

// <copyright file="BroadcastActivityProcessor.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Trace.Internal
{
    internal class BroadcastActivityProcessor : ActivityProcessor, IDisposable
    {
        private readonly IEnumerable<ActivityProcessor> processors;
        private bool isDisposed;

        public BroadcastActivityProcessor(IEnumerable<ActivityProcessor> processors)
        {
            if (processors == null)
            {
                throw new ArgumentNullException(nameof(processors));
            }

            if (!processors.Any())
            {
                throw new ArgumentException($"{nameof(processors)} collection is empty");
            }

            this.processors = processors;
        }

        public override void OnEnd(Activity activity)
        {
            foreach (var processor in this.processors)
            {
                try
                {
                    processor.OnEnd(activity);
                }
                catch (Exception e)
                {
                    OpenTelemetrySdkEventSource.Log.SpanProcessorException("OnEnd", e);
                }
            }
        }

        public override void OnStart(Activity activity)
        {
            foreach (var processor in this.processors)
            {
                try
                {
                    processor.OnStart(activity);
                }
                catch (Exception e)
                {
                    OpenTelemetrySdkEventSource.Log.SpanProcessorException("OnStart", e);
                }
            }
        }

        public override Task ShutdownAsync(CancellationToken cancellationToken)
        {
            var tasks = new List<Task>();
            foreach (var processor in this.processors)
            {
                tasks.Add(processor.ShutdownAsync(cancellationToken));
            }

            return Task.WhenAll(tasks);
        }

        public override Task ForceFlushAsync(CancellationToken cancellationToken)
        {
            var tasks = new List<Task>(this.processors.Count());
            foreach (var processor in this.processors)
            {
                tasks.Add(processor.ForceFlushAsync(cancellationToken));
            }

            return Task.WhenAll(tasks);
        }

        public void Dispose()
        {
            this.Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            try
            {
                this.ShutdownAsync(CancellationToken.None).GetAwaiter().GetResult();
            }
            catch (Exception ex)
            {
                OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.Dispose), ex);
            }

            if (disposing && !this.isDisposed)
            {
                foreach (var processor in this.processors)
                {
                    try
                    {
                        if (processor is IDisposable disposable)
                        {
                            disposable.Dispose();
                        }
                    }
                    catch (Exception e)
                    {
                        OpenTelemetrySdkEventSource.Log.SpanProcessorException("Dispose", e);
                    }
                }

                this.isDisposed = true;
            }
        }
    }
}


@@ -6,18 +6,24 @@
 // Project Lead - Stuart Lodge, @slodge, me@slodge.com

 using System;
+using System.Collections.Generic;
+using System.Linq;
 using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
 using MvvmCross.Core.Navigation;
 using MvvmCross.Core.ViewModels;
 using MvvmCross.Core.Views;
 using MvvmCross.Platform;
 using MvvmCross.Platform.Exceptions;
 using MvvmCross.Platform.Platform;
+using MvvmCross.Uwp.Attributes;

 namespace MvvmCross.Uwp.Views
 {
     public class MvxWindowsViewPresenter
-        : MvxViewPresenter, IMvxWindowsViewPresenter
+        : MvxViewPresenter, IMvxWindowsViewPresenter, IMvxAttributeViewPresenter
     {
         protected readonly IMvxWindowsFrame _rootFrame;

// MvxStoreViewPresenter.cs

// MvvmCross is licensed using Microsoft Public License (Ms-PL)
// Contributions and inspirations noted in readme.md and license.txt
//
// Project Lead - Stuart Lodge, @slodge, me@slodge.com

using System;
using Windows.UI.Core;
using MvvmCross.Core.Navigation;
using MvvmCross.Core.ViewModels;
using MvvmCross.Core.Views;
using MvvmCross.Platform;
using MvvmCross.Platform.Exceptions;
using MvvmCross.Platform.Platform;

namespace MvvmCross.Uwp.Views
{
    public class MvxWindowsViewPresenter
        : MvxViewPresenter, IMvxWindowsViewPresenter
    {
        protected readonly IMvxWindowsFrame _rootFrame;

        public MvxWindowsViewPresenter(IMvxWindowsFrame rootFrame)
        {
            _rootFrame = rootFrame;

            SystemNavigationManager.GetForCurrentView().BackRequested += BackButtonOnBackRequested;
        }

        private IMvxViewModelTypeFinder _viewModelTypeFinder;
        public IMvxViewModelTypeFinder ViewModelTypeFinder
        {
            get
            {
                if (_viewModelTypeFinder == null)
                    _viewModelTypeFinder = Mvx.Resolve<IMvxViewModelTypeFinder>();
                return _viewModelTypeFinder;
            }
            set
            {
                _viewModelTypeFinder = value;
            }
        }

        private IMvxViewsContainer _viewsContainer;
        public IMvxViewsContainer ViewsContainer
        {
            get
            {
                if (_viewsContainer == null)
                    _viewsContainer = Mvx.Resolve<IMvxViewsContainer>();
                return _viewsContainer;
            }
            set
            {
                _viewsContainer = value;
            }
        }

        protected virtual async void BackButtonOnBackRequested(object sender, BackRequestedEventArgs backRequestedEventArgs)
        {
            if (backRequestedEventArgs.Handled)
                return;

            var currentView = _rootFrame.Content as IMvxView;
            if (currentView == null)
            {
                Mvx.Warning("Ignoring close for viewmodel - rootframe has no current page");
                return;
            }

            var navigationService = Mvx.Resolve<IMvxNavigationService>();

            backRequestedEventArgs.Handled = await navigationService.Close(currentView.ViewModel);
        }

        public override void Show(MvxViewModelRequest request)
        {
            try
            {
                var requestText = GetRequestText(request);
                var viewsContainer = Mvx.Resolve<IMvxViewsContainer>();
                var viewType = viewsContainer.GetViewType(request.ViewModelType);

                _rootFrame.Navigate(viewType, requestText); //Frame won't allow serialization of it's nav-state if it gets a non-simple type as a nav param

                HandleBackButtonVisibility();
            }
            catch (Exception exception)
            {
                MvxTrace.Trace("Error seen during navigation request to {0} - error {1}", request.ViewModelType.Name,
                               exception.ToLongString());
            }
        }

        protected virtual string GetRequestText(MvxViewModelRequest request)
        {
            var requestTranslator = Mvx.Resolve<IMvxWindowsViewModelRequestTranslator>();
            string requestText = string.Empty;
            if (request is MvxViewModelInstanceRequest)
            {
                requestText = requestTranslator.GetRequestTextWithKeyFor(((MvxViewModelInstanceRequest)request).ViewModelInstance);
            }
            else
            {
                requestText = requestTranslator.GetRequestTextFor(request);
            }

            return requestText;
        }

        public override void ChangePresentation(MvxPresentationHint hint)
        {
            if (HandlePresentationChange(hint)) return;

            if (hint is MvxClosePresentationHint)
            {
                Close((hint as MvxClosePresentationHint).ViewModelToClose);
                return;
            }

            MvxTrace.Warning("Hint ignored {0}", hint.GetType().Name);
        }

        public override void Close(IMvxViewModel viewModel)
        {
            var currentView = _rootFrame.Content as IMvxView;
            if (currentView == null)
            {
                Mvx.Warning("Ignoring close for viewmodel - rootframe has no current page");
                return;
            }

            if (currentView.ViewModel != viewModel)
            {
                Mvx.Warning("Ignoring close for viewmodel - rootframe's current page is not the view for the requested viewmodel");
                return;
            }

            if (!_rootFrame.CanGoBack)
            {
                Mvx.Warning("Ignoring close for viewmodel - rootframe refuses to go back");
                return;
            }

            _rootFrame.GoBack();

            HandleBackButtonVisibility();
        }

        protected virtual void HandleBackButtonVisibility()
        {
            SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
                _rootFrame.CanGoBack ? AppViewBackButtonVisibility.Visible : AppViewBackButtonVisibility.Collapsed;
        }
    }
}


@@ -120,7 +120,7 @@ namespace MvvmCross.Plugins.PictureChooser.iOS
             }

             _picker.DismissViewController(true, () => { });
-            _modalHost.NativeModalViewControllerDisappearedOnItsOwn();
+            _viewPresenter.CloseModalViewControllers();
         }

         private void Picker_FinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs e)

// MvxImagePickerTask.cs
// (c) Copyright Cirrious Ltd. http://www.cirrious.com
// MvvmCross is licensed using Microsoft Public License (Ms-PL)
// Contributions and inspirations noted in readme.md and license.txt
//
// Project Lead - Stuart Lodge, @slodge, me@slodge.com

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using CoreGraphics;
using Foundation;
using MvvmCross.Platform;
using MvvmCross.Platform.iOS.Platform;
using MvvmCross.Platform.iOS.Views;
using MvvmCross.Platform.Logging;
using UIKit;

namespace MvvmCross.Plugins.PictureChooser.iOS
{
    [MvvmCross.Platform.Preserve(AllMembers = true)]
	public class MvxImagePickerTask
        : MvxIosTask, IMvxPictureChooserTask
    {
        private readonly UIImagePickerController _picker;
        private readonly IMvxIosModalHost _modalHost;
        private bool _currentlyActive;
        private int _maxPixelDimension;
        private int _percentQuality;
        private Action<Stream, string> _pictureAvailable;
        private Action _assumeCancelled;

        public MvxImagePickerTask()
        {
            _modalHost = Mvx.Resolve<IMvxIosModalHost>();
            _picker = new UIImagePickerController
            {
                //CameraCaptureMode = UIImagePickerControllerCameraCaptureMode.Photo,
                //CameraDevice = UIImagePickerControllerCameraDevice.Front
            };
            _picker.FinishedPickingMedia += Picker_FinishedPickingMedia;
            _picker.FinishedPickingImage += Picker_FinishedPickingImage;
            _picker.Canceled += Picker_Canceled;
        }

        public void ChoosePictureFromLibrary(int maxPixelDimension, int percentQuality, Action<Stream, string> pictureAvailable,
                                     Action assumeCancelled)
        {
            _picker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;
            ChoosePictureCommon(maxPixelDimension, percentQuality, pictureAvailable, assumeCancelled);
        }

        public void ChoosePictureFromLibrary(int maxPixelDimension, int percentQuality, Action<Stream> pictureAvailable,
                                             Action assumeCancelled)
        {
            ChoosePictureFromLibrary(maxPixelDimension, percentQuality, (stream, name) => pictureAvailable(stream), assumeCancelled);
        }

        public void TakePicture(int maxPixelDimension, int percentQuality, Action<Stream> pictureAvailable,
                                Action assumeCancelled)
        {
            _picker.SourceType = UIImagePickerControllerSourceType.Camera;
            ChoosePictureCommon(maxPixelDimension, percentQuality, (stream, name) => pictureAvailable(stream), assumeCancelled);
        }

        public Task<Stream> ChoosePictureFromLibrary(int maxPixelDimension, int percentQuality)
        {
            var task = new TaskCompletionSource<Stream>();
            ChoosePictureFromLibrary(maxPixelDimension, percentQuality, task.SetResult, () => task.SetResult(null));
            return task.Task;
        }

        public Task<Stream> TakePicture(int maxPixelDimension, int percentQuality)
        {
            var task = new TaskCompletionSource<Stream>();
            TakePicture(maxPixelDimension, percentQuality, task.SetResult, () => task.SetResult(null));
            return task.Task;
        }

        public void ContinueFileOpenPicker(object args)
        {
        }

        private void ChoosePictureCommon(int maxPixelDimension, int percentQuality,
                                         Action<Stream, string> pictureAvailable, Action assumeCancelled)
        {
            SetCurrentlyActive();
            _maxPixelDimension = maxPixelDimension;
            _percentQuality = percentQuality;
            _pictureAvailable = pictureAvailable;
            _assumeCancelled = assumeCancelled;

            _modalHost.PresentModalViewController(_picker, true);
        }

        private void HandleImagePick(UIImage image, string name)
        {
            ClearCurrentlyActive();
            if (image != null)
            {
                if (_maxPixelDimension > 0 && (image.Size.Height > _maxPixelDimension || image.Size.Width > _maxPixelDimension))
                {
                    // resize the image
                    image = image.ImageToFitSize(new CGSize(_maxPixelDimension, _maxPixelDimension));
                }

                using (NSData data = image.AsJPEG(_percentQuality / 100f))
                {
                    var byteArray = new byte[data.Length];
                    Marshal.Copy(data.Bytes, byteArray, 0, Convert.ToInt32(data.Length));

                    var imageStream = new MemoryStream(byteArray, false);
                    _pictureAvailable?.Invoke(imageStream, name);
                }
            }
            else
            {
                _assumeCancelled?.Invoke();
            }

            _picker.DismissViewController(true, () => { });
            _modalHost.NativeModalViewControllerDisappearedOnItsOwn();
        }

        private void Picker_FinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs e)
        {
            NSUrl referenceURL = e.Info[new NSString("UIImagePickerControllerReferenceURL")] as NSUrl;
            var image = e.EditedImage ?? e.OriginalImage;
            HandleImagePick(image, referenceURL != null ? referenceURL.AbsoluteString : string.Empty);
        }

        private void Picker_FinishedPickingImage(object sender, UIImagePickerImagePickedEventArgs e)
        {
            NSUrl referenceURL = e.EditingInfo["UIImagePickerControllerReferenceURL"] as NSUrl;
            var image = e.Image;
            HandleImagePick(image, referenceURL != null ? referenceURL.AbsoluteString : string.Empty);
        }

        private void Picker_Canceled(object sender, EventArgs e)
        {
            ClearCurrentlyActive();
            _assumeCancelled?.Invoke();
            _picker.DismissViewController(true, () => { });
            _modalHost.NativeModalViewControllerDisappearedOnItsOwn();
        }

        private void SetCurrentlyActive()
        {
            if (_currentlyActive)
                MvxPluginLog.Instance.Warn("MvxImagePickerTask called when task already active");
            _currentlyActive = true;
        }

        private void ClearCurrentlyActive()
        {
            if (!_currentlyActive)
                MvxPluginLog.Instance.Warn("Tried to clear currently active - but already cleared");
            _currentlyActive = false;
        }
    }
}


@@ -63,9 +63,26 @@ namespace OpenTelemetry.Instrumentation.SqlClient
         /// <remarks>
         /// <para><see cref="Activity"/>: the activity being enriched.</para>
         /// <para>string: the name of the event.</para>
-        /// <para>object: the raw object from which additional information can be extracted to enrich the activity.
-        /// The type of this object depends on the event, which is given by the above parameter.</para>
+        /// <para>object: the raw <c>SqlCommand</c> object from which additional information can be extracted to enrich the activity.</para>
+        /// <para>See also: example.</para>
         /// </remarks>
+        /// <example>
+        ///
+        /// using var tracerProvider = Sdk.CreateTracerProviderBuilder()
+        ///     .AddSqlClientInstrumentation(opt => opt.Enrich
+        ///         = (activity, eventName, rawObject) =>
+        ///      {
+        ///         if (eventName.Equals("OnCustom"))
+        ///         {
+        ///             if (rawObject is SqlCommand cmd)
+        ///             {
+        ///                 activity.SetTag("db.commandTimeout", cmd.CommandTimeout);
+        ///             }
+        ///         }
+        ///      })
+        ///     .Build();
+        ///
+        /// </example>
         public Action<Activity, string, object> Enrich { get; set; }

         internal static SqlConnectionDetails ParseDataSource(string dataSource)

// <copyright file="SqlClientInstrumentationOptions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections.Concurrent;
using System.Data;
using System.Diagnostics;
using System.Text.RegularExpressions;
using OpenTelemetry.Trace;

namespace OpenTelemetry.Instrumentation.SqlClient
{
    /// <summary>
    /// Options for <see cref="SqlClientInstrumentation"/>.
    /// </summary>
    public class SqlClientInstrumentationOptions
    {
        /*
         * Match...
         *  serverName
         *  serverName[ ]\\[ ]instanceName
         *  serverName[ ],[ ]port
         *  serverName[ ]\\[ ]instanceName[ ],[ ]port
         * [ ] can be any number of white-space, SQL allows it for some reason.
         */
        private static readonly Regex DataSourceRegex = new Regex("^(.*?)\\s*(?:[\\\\,]|$)\\s*(.*?)\\s*(?:,|$)\\s*(.*)$", RegexOptions.Compiled);
        private static readonly ConcurrentDictionary<string, SqlConnectionDetails> ConnectionDetailCache = new ConcurrentDictionary<string, SqlConnectionDetails>(StringComparer.OrdinalIgnoreCase);

        /// <summary>
        /// Gets or sets a value indicating whether or not the <see cref="SqlClientInstrumentation"/> should add the names of <see cref="CommandType.StoredProcedure"/> commands as the <see cref="SemanticConventions.AttributeDbStatement"/> tag. Default value: True.
        /// </summary>
        public bool SetStoredProcedureCommandName { get; set; } = true;

        /// <summary>
        /// Gets or sets a value indicating whether or not the <see cref="SqlClientInstrumentation"/> should add the text of <see cref="CommandType.Text"/> commands as the <see cref="SemanticConventions.AttributeDbStatement"/> tag. Default value: False.
        /// </summary>
        public bool SetTextCommandContent { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether or not the <see cref="SqlClientInstrumentation"/> should parse the DataSource on a SqlConnection into server name, instance name, and/or port connection-level attribute tags. Default value: False.
        /// </summary>
        /// <remarks>
        /// The default behavior is to set the SqlConnection DataSource as the <see cref="SemanticConventions.AttributePeerService"/> tag. If enabled, SqlConnection DataSource will be parsed and the server name will be sent as the <see cref="SemanticConventions.AttributeNetPeerName"/> or <see cref="SemanticConventions.AttributeNetPeerIp"/> tag, the instance name will be sent as the <see cref="SemanticConventions.AttributeDbMsSqlInstanceName"/> tag, and the port will be sent as the <see cref="SemanticConventions.AttributeNetPeerPort"/> tag if it is not 1433 (the default port).
        /// </remarks>
        public bool EnableConnectionLevelAttributes { get; set; }

        /// <summary>
        /// Gets or sets an action to enrich an Activity.
        /// </summary>
        /// <remarks>
        /// <para><see cref="Activity"/>: the activity being enriched.</para>
        /// <para>string: the name of the event.</para>
        /// <para>object: the raw object from which additional information can be extracted to enrich the activity.
        /// The type of this object depends on the event, which is given by the above parameter.</para>
        /// </remarks>
        public Action<Activity, string, object> Enrich { get; set; }

        internal static SqlConnectionDetails ParseDataSource(string dataSource)
        {
            Match match = DataSourceRegex.Match(dataSource);

            string serverHostName = match.Groups[1].Value;
            string serverIpAddress = null;

            var uriHostNameType = Uri.CheckHostName(serverHostName);
            if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6)
            {
                serverIpAddress = serverHostName;
                serverHostName = null;
            }

            string instanceName;
            string port;
            if (match.Groups[3].Length > 0)
            {
                instanceName = match.Groups[2].Value;
                port = match.Groups[3].Value;
                if (port == "1433")
                {
                    port = null;
                }
            }
            else if (int.TryParse(match.Groups[2].Value, out int parsedPort))
            {
                port = parsedPort == 1433 ? null : match.Groups[2].Value;
                instanceName = null;
            }
            else
            {
                instanceName = match.Groups[2].Value;

                if (string.IsNullOrEmpty(instanceName))
                {
                    instanceName = null;
                }

                port = null;
            }

            return new SqlConnectionDetails
            {
                ServerHostName = serverHostName,
                ServerIpAddress = serverIpAddress,
                InstanceName = instanceName,
                Port = port,
            };
        }

        internal void AddConnectionLevelDetailsToActivity(string dataSource, Activity sqlActivity)
        {
            if (!this.EnableConnectionLevelAttributes)
            {
                sqlActivity.SetTag(SemanticConventions.AttributePeerService, dataSource);
            }
            else
            {
                if (!ConnectionDetailCache.TryGetValue(dataSource, out SqlConnectionDetails connectionDetails))
                {
                    connectionDetails = ParseDataSource(dataSource);
                    ConnectionDetailCache.TryAdd(dataSource, connectionDetails);
                }

                if (!string.IsNullOrEmpty(connectionDetails.ServerHostName))
                {
                    sqlActivity.SetTag(SemanticConventions.AttributeNetPeerName, connectionDetails.ServerHostName);
                }
                else
                {
                    sqlActivity.SetTag(SemanticConventions.AttributeNetPeerIp, connectionDetails.ServerIpAddress);
                }

                if (!string.IsNullOrEmpty(connectionDetails.InstanceName))
                {
                    sqlActivity.SetTag(SemanticConventions.AttributeDbMsSqlInstanceName, connectionDetails.InstanceName);
                }

                if (!string.IsNullOrEmpty(connectionDetails.Port))
                {
                    sqlActivity.SetTag(SemanticConventions.AttributeNetPeerPort, connectionDetails.Port);
                }
            }
        }

        internal class SqlConnectionDetails
        {
            public string ServerHostName { get; set; }

            public string ServerIpAddress { get; set; }

            public string InstanceName { get; set; }

            public string Port { get; set; }
        }
    }
}


@@ -55,6 +55,12 @@ namespace OpenTelemetry.Instrumentation.AspNet

                 if (propagationContext.Baggage != default)
                 {
+                    // todo: RestoreActivityIfNeeded below compensates for
+                    // AsyncLocal Activity.Current being lost. Baggage
+                    // potentially will suffer from the same issue, but we can’t
+                    // simply add it to context.Items because any change results
+                    // in a new instance. Probably need to save it at the end of
+                    // each OnExecuteRequestStep.
                     Baggage.Current = propagationContext.Baggage;
                 }

// <copyright file="ActivityHelper.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Web;
using OpenTelemetry.Context.Propagation;

namespace OpenTelemetry.Instrumentation.AspNet
{
    /// <summary>
    /// Activity helper class.
    /// </summary>
    internal static class ActivityHelper
    {
        /// <summary>
        /// Key to store the activity in HttpContext.
        /// </summary>
        public const string ActivityKey = "__AspnetActivity__";

        private static readonly ActivitySource AspNetSource = new ActivitySource(TelemetryHttpModule.AspNetSourceName);
        private static readonly Func<HttpRequest, string, IEnumerable<string>> HttpRequestHeaderValuesGetter = (request, name) => request.Headers.GetValues(name);

        /// <summary>
        /// Creates root (first level) activity that describes incoming request.
        /// </summary>
        /// <param name="textMapPropagator"><see cref="TextMapPropagator"/>.</param>
        /// <param name="context">Current HttpContext.</param>
        /// <param name="onRequestStartedCallback">Callback action.</param>
        /// <returns>New root activity.</returns>
        public static Activity StartAspNetActivity(TextMapPropagator textMapPropagator, HttpContext context, Action<Activity, HttpContext> onRequestStartedCallback)
        {
            PropagationContext propagationContext = textMapPropagator.Extract(default, context.Request, HttpRequestHeaderValuesGetter);

            Activity activity = AspNetSource.CreateActivity(TelemetryHttpModule.AspNetActivityName, ActivityKind.Server, propagationContext.ActivityContext);

            if (activity != null)
            {
                context.Items[ActivityKey] = activity;

                if (propagationContext.Baggage != default)
                {
                    Baggage.Current = propagationContext.Baggage;
                }

                try
                {
                    onRequestStartedCallback?.Invoke(activity, context);
                }
                catch (Exception callbackEx)
                {
                    AspNetTelemetryEventSource.Log.CallbackException(activity, "OnStarted", callbackEx);
                }

                AspNetTelemetryEventSource.Log.ActivityStarted(activity);
            }

            return activity;
        }

        /// <summary>
        /// Stops the activity and notifies listeners about it.
        /// </summary>
        /// <param name="context">Current HttpContext.</param>
        /// <param name="onRequestStoppedCallback">Callback action.</param>
        public static void StopAspNetActivity(HttpContext context, Action<Activity, HttpContext> onRequestStoppedCallback)
        {
            var contextItems = context.Items;
            var currentActivity = Activity.Current;
            Activity aspNetActivity = (Activity)contextItems[ActivityKey];

            if (currentActivity != aspNetActivity)
            {
                Activity.Current = aspNetActivity;
            }

            if (aspNetActivity != null)
            {
                aspNetActivity.Stop();
                contextItems[ActivityKey] = null;

                try
                {
                    onRequestStoppedCallback?.Invoke(aspNetActivity, context);
                }
                catch (Exception callbackEx)
                {
                    AspNetTelemetryEventSource.Log.CallbackException(aspNetActivity, "OnStopped", callbackEx);
                }

                AspNetTelemetryEventSource.Log.ActivityStopped(currentActivity);
            }

            if (currentActivity != aspNetActivity)
            {
                Activity.Current = currentActivity;
            }
        }

        public static void WriteActivityException(IDictionary contextItems, Exception exception, Action<Activity, Exception> onExceptionCallback)
        {
            Activity aspNetActivity = (Activity)contextItems[ActivityKey];

            if (aspNetActivity != null)
            {
                try
                {
                    onExceptionCallback?.Invoke(aspNetActivity, exception);
                }
                catch (Exception callbackEx)
                {
                    AspNetTelemetryEventSource.Log.CallbackException(aspNetActivity, "OnException", callbackEx);
                }

                AspNetTelemetryEventSource.Log.ActivityException(aspNetActivity, exception);
            }
        }

        /// <summary>
        /// It's possible that a request is executed in both native threads and managed threads,
        /// in such case Activity.Current will be lost during native thread and managed thread switch.
        /// This method is intended to restore the current activity in order to correlate the child
        /// activities with the root activity of the request.
        /// </summary>
        /// <param name="contextItems">HttpContext.Items dictionary.</param>
        internal static void RestoreActivityIfNeeded(IDictionary contextItems)
        {
            if (Activity.Current == null)
            {
                Activity aspNetActivity = (Activity)contextItems[ActivityKey];
                if (aspNetActivity != null)
                {
                    Activity.Current = aspNetActivity;
                    AspNetTelemetryEventSource.Log.ActivityRestored(aspNetActivity);
                }
            }
        }
    }
}


@@ -55,14 +55,14 @@ namespace OpenTelemetry.Trace.Test
         [Fact]
         public void ThrowsInExporter()
         {
-            this.activityExporter = new TestActivityExporter(_ => throw new ArgumentException("123"));
-            this.openTelemetry = Sdk.CreateTracerProvider(b => b
-                        .AddActivitySource("cijo")
-                        .AddProcessorPipeline(p => p
-                        .SetExporter(this.activityExporter)
-                        .SetExportingProcessor(e => new SimpleActivityProcessor(e))));
-
-            ActivitySource source = new ActivitySource("cijo");
+            var activityExporter = new TestActivityExporter(_ => throw new ArgumentException("123"));
+            using var openTelemetry = Sdk.CreateTracerProviderBuilder()
+                        .AddSource("random")
+                        .SetSampler(new AlwaysOnSampler())
+                        .AddProcessor(new SimpleActivityProcessor(activityExporter))
+                        .Build();
+
+            ActivitySource source = new ActivitySource("random");
             var activity = source.StartActivity("somename");

             // does not throw

// <copyright file="SimpleActivityProcessorTest.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using OpenTelemetry.Testing.Export;
using OpenTelemetry.Trace.Samplers;
using Xunit;

namespace OpenTelemetry.Trace.Test
{
    public class SimpleActivityProcessorTest : IDisposable
    {
        private const string SpanName1 = "MySpanName/1";
        private const string SpanName2 = "MySpanName/2";
        private const string ActivitySourceName = "defaultactivitysource";

        private TestActivityExporter activityExporter;
        private TracerProvider openTelemetry;
        private ActivitySource activitySource;

        public SimpleActivityProcessorTest()
        {
            this.activityExporter = new TestActivityExporter(null);
            this.openTelemetry = Sdk.CreateTracerProvider(b => b
                        .AddActivitySource(ActivitySourceName)
                        .AddProcessorPipeline(p => p
                        .SetExporter(this.activityExporter)
                        .SetExportingProcessor(e => new SimpleActivityProcessor(e)))
                .SetSampler(new AlwaysOnSampler()));
            this.activitySource = new ActivitySource(ActivitySourceName);
        }

        [Fact]
        public void ThrowsOnNullExporter()
        {
            Assert.Throws<ArgumentNullException>(() => new SimpleActivityProcessor(null));
        }

        [Fact]
        public void ThrowsInExporter()
        {
            this.activityExporter = new TestActivityExporter(_ => throw new ArgumentException("123"));
            this.openTelemetry = Sdk.CreateTracerProvider(b => b
                        .AddActivitySource("cijo")
                        .AddProcessorPipeline(p => p
                        .SetExporter(this.activityExporter)
                        .SetExportingProcessor(e => new SimpleActivityProcessor(e))));

            ActivitySource source = new ActivitySource("cijo");
            var activity = source.StartActivity("somename");

            // does not throw
            activity.Stop();
        }

        [Fact]
        public void ProcessorDoesNotBlockOnExporter()
        {
            this.activityExporter = new TestActivityExporter(async _ => await Task.Delay(500));
            this.openTelemetry = Sdk.CreateTracerProvider(b => b
                        .AddActivitySource("cijo")
                        .AddProcessorPipeline(p => p
                        .SetExporter(this.activityExporter)
                        .SetExportingProcessor(e => new SimpleActivityProcessor(e))));

            ActivitySource source = new ActivitySource("cijo");
            var activity = source.StartActivity("somename");

            // does not block
            var sw = Stopwatch.StartNew();
            activity.Stop();
            sw.Stop();

            Assert.InRange(sw.Elapsed, TimeSpan.Zero, TimeSpan.FromMilliseconds(100));

            var exported = this.WaitForSpans(this.activityExporter, 1, TimeSpan.FromMilliseconds(600));

            Assert.Single(exported);
        }

        [Fact]
        public async Task ShutdownTwice()
        {
            var activityProcessor = new SimpleActivityProcessor(new TestActivityExporter(null));

            await activityProcessor.ShutdownAsync(CancellationToken.None).ConfigureAwait(false);

            // does not throw
            await activityProcessor.ShutdownAsync(CancellationToken.None).ConfigureAwait(false);
        }

        [Fact]
        public async Task ForceFlushReturnsCompletedTask()
        {
            var activityProcessor = new SimpleActivityProcessor(new TestActivityExporter(null));

            var forceFlushTask = activityProcessor.ForceFlushAsync(CancellationToken.None);
            await forceFlushTask;

            Assert.True(forceFlushTask.IsCompleted);
        }

        [Fact]
        public void ExportDifferentSampledSpans()
        {
            var span1 = this.CreateSampledEndedSpan(SpanName1);
            var span2 = this.CreateSampledEndedSpan(SpanName2);

            var exported = this.WaitForSpans(this.activityExporter, 2, TimeSpan.FromMilliseconds(100));
            Assert.Equal(2, exported.Length);
            Assert.Contains(span1, exported);
            Assert.Contains(span2, exported);
        }

        [Fact(Skip = "Reenable once AlwaysParentSampler is added")]
        public void ExportNotSampledSpans()
        {
            var span1 = this.CreateNotSampledEndedSpan(SpanName1);
            var span2 = this.CreateSampledEndedSpan(SpanName2);

            // Spans are recorded and exported in the same order as they are ended, we test that a non
            // sampled span is not exported by creating and ending a sampled span after a non sampled span
            // and checking that the first exported span is the sampled span (the non sampled did not get
            // exported).

            var exported = this.WaitForSpans(this.activityExporter, 1, TimeSpan.FromMilliseconds(100));

            // Need to check this because otherwise the variable span1 is unused, other option is to not
            // have a span1 variable.
            Assert.Single(exported);
            Assert.Contains(span2, exported);
        }

        public void Dispose()
        {
            this.activityExporter.ShutdownAsync(CancellationToken.None);
            Activity.Current = null;
        }

        private Activity CreateSampledEndedSpan(string spanName)
        {
            var context = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded);

            var activity = this.activitySource.StartActivity(spanName, ActivityKind.Internal, context);
            activity.Stop();
            return activity;
        }

        private Activity CreateNotSampledEndedSpan(string spanName)
        {
            var context = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None);
            var activity = this.activitySource.StartActivity(spanName, ActivityKind.Internal, context);
            activity.Stop();
            return activity;
        }

        private Activity[] WaitForSpans(TestActivityExporter exporter, int spanCount, TimeSpan timeout)
        {
            Assert.True(
                SpinWait.SpinUntil(
                    () =>
                    {
                        Thread.Sleep(0);
                        return exporter.ExportedActivities.Length >= spanCount;
                    }, timeout + TimeSpan.FromMilliseconds(20)));

            return exporter.ExportedActivities;
        }
    }
}


@@ -96,5 +96,14 @@ namespace SampleApp

             return hostBuilder.Build().RunAsync();
         }
+
+        private static void ShowConfig(IConfiguration config)
+        {
+            foreach (var pair in config.GetChildren())
+            {
+                Console.WriteLine($"{pair.Path} - {pair.Value}");
+                ShowConfig(pair);
+            }
+        }
     }
 }

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace SampleApp
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
        {
            var logger = loggerFactory.CreateLogger("Default");

            app.Run(async context =>
            {
                var connectionFeature = context.Connection;
                logger.LogDebug($"Peer: {connectionFeature.RemoteIpAddress?.ToString()}:{connectionFeature.RemotePort}"
                    + $"{Environment.NewLine}"
                    + $"Sock: {connectionFeature.LocalIpAddress?.ToString()}:{connectionFeature.LocalPort}");

                var response = $"hello, world{Environment.NewLine}";
                context.Response.ContentLength = response.Length;
                context.Response.ContentType = "text/plain";
                await context.Response.WriteAsync(response);
            });
        }

        public static Task Main(string[] args)
        {
            TaskScheduler.UnobservedTaskException += (sender, e) =>
            {
                Console.WriteLine("Unobserved exception: {0}", e.Exception);
            };

            var hostBuilder = new WebHostBuilder()
                .ConfigureLogging((_, factory) =>
                {
                    factory.AddConsole();
                })
                .UseKestrel((context, options) =>
                {
                    var basePort = context.Configuration.GetValue<int?>("BASE_PORT") ?? 5000;

                    // Run callbacks on the transport thread
                    options.ApplicationSchedulingMode = SchedulingMode.Inline;

                    options.Listen(IPAddress.Loopback, basePort, listenOptions =>
                    {
                        // Uncomment the following to enable Nagle's algorithm for this endpoint.
                        //listenOptions.NoDelay = false;

                        listenOptions.UseConnectionLogging();
                    });

                    options.Listen(IPAddress.Loopback, basePort + 1, listenOptions =>
                    {
                        listenOptions.UseHttps("testCert.pfx", "testPassword");
                        listenOptions.UseConnectionLogging();
                    });

                    options.ListenLocalhost(basePort + 2, listenOptions =>
                    {
                        listenOptions.UseHttps("testCert.pfx", "testPassword");
                    });

                    options.ListenAnyIP(basePort + 3);

                    options.UseSystemd();

                    // The following section should be used to demo sockets
                    //options.ListenUnixSocket("/tmp/kestrel-test.sock");
                })
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup<Startup>();

            if (string.Equals(Process.GetCurrentProcess().Id.ToString(), Environment.GetEnvironmentVariable("LISTEN_PID")))
            {
                // Use libuv if activated by systemd, since that's currently the only transport that supports being passed a socket handle.
                hostBuilder.UseLibuv(options =>
                 {
                     // Uncomment the following line to change the default number of libuv threads for all endpoints.
                     // options.ThreadCount = 4;
                 });
            }

            return hostBuilder.Build().RunAsync();
        }
    }
}