diff --git a/src/Agent/NewRelic/Agent/Core/Agent.cs b/src/Agent/NewRelic/Agent/Core/Agent.cs index 966b98251..d2724bb01 100644 --- a/src/Agent/NewRelic/Agent/Core/Agent.cs +++ b/src/Agent/NewRelic/Agent/Core/Agent.cs @@ -28,8 +28,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net.Mime; -using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -65,7 +63,6 @@ public class Agent : IAgent // any changes to api, update the interface in exten private readonly ILogEventAggregator _logEventAggregator; private readonly ILogContextDataFilter _logContextDataFilter; private Extensions.Logging.ILogger _logger; - private volatile IStackExchangeRedisCache _stackExchangeRedisCache; private readonly ISimpleSchedulingService _simpleSchedulingService; public Agent(ITransactionService transactionService, ITransactionTransformer transactionTransformer, @@ -419,11 +416,7 @@ public ISimpleSchedulingService SimpleSchedulingService get { return _simpleSchedulingService; } } - public IStackExchangeRedisCache StackExchangeRedisCache - { - get { return _stackExchangeRedisCache; } - set { _stackExchangeRedisCache = value; } - } + public IStackExchangeRedisCache StackExchangeRedisCache { get; set; } public void RecordSupportabilityMetric(string metricName, long count = 1) { diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/StackExchangeRedis2Plus/ConnectWrapperV2.cs b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/StackExchangeRedis2Plus/ConnectWrapperV2.cs index b2211ed16..db0862b4b 100644 --- a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/StackExchangeRedis2Plus/ConnectWrapperV2.cs +++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/StackExchangeRedis2Plus/ConnectWrapperV2.cs @@ -1,4 +1,4 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. +// Copyright 2020 New Relic, Inc. All rights reserved. // SPDX-License-Identifier: Apache-2.0 using System.Runtime.CompilerServices; @@ -14,6 +14,7 @@ public class ConnectWrapperV2 : IWrapper public bool IsTransactionRequired => false; private const string WrapperName = "stackexchangeredis-connect"; + private static readonly object _lock = new(); public CanWrapResponse CanWrap(InstrumentedMethodInfo methodInfo) { @@ -23,22 +24,26 @@ public CanWrapResponse CanWrap(InstrumentedMethodInfo methodInfo) public AfterWrappedMethodDelegate BeforeWrappedMethod(InstrumentedMethodCall instrumentedMethodCall, IAgent agent, Agent.Api.ITransaction transaction) { return Delegates.GetDelegateFor( - onSuccess: muxer => - { - RegisterProfIler(muxer); - }); + onSuccess: RegisterProfiler); - void RegisterProfIler(IConnectionMultiplexer multiplexer) + void RegisterProfiler(IConnectionMultiplexer multiplexer) { var xAgent = (IAgentExperimental)agent; // The SessionCache is not connection-specific. This checks for an existing cache and creates one if there is none. - if (((IAgentExperimental)agent).StackExchangeRedisCache == null) + if (xAgent.StackExchangeRedisCache == null) { - // We only need the hashcode since nothing will change for the methodCall - var hashCode = RuntimeHelpers.GetHashCode(multiplexer); - var sessionCache = new SessionCache(agent, hashCode); - xAgent.StackExchangeRedisCache = sessionCache; + lock (_lock) + { + if (xAgent.StackExchangeRedisCache == null) + { + // We only need the hashcode since nothing will change for the methodCall + var hashCode = RuntimeHelpers.GetHashCode(multiplexer); + var sessionCache = new SessionCache(agent, hashCode); + + xAgent.StackExchangeRedisCache = sessionCache; + } + } } // Registers the profiling function from the shared SessionCache. diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/StackExchangeRedis2Plus/SessionCache.cs b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/StackExchangeRedis2Plus/SessionCache.cs index 78edc24bc..89f54774f 100644 --- a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/StackExchangeRedis2Plus/SessionCache.cs +++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/StackExchangeRedis2Plus/SessionCache.cs @@ -1,4 +1,4 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. +// Copyright 2020 New Relic, Inc. All rights reserved. // SPDX-License-Identifier: Apache-2.0 using System; @@ -10,6 +10,7 @@ using NewRelic.Agent.Extensions.Helpers; using NewRelic.Agent.Extensions.Parsing; using NewRelic.Agent.Extensions.Providers.Wrapper; +using NewRelic.Core.Logging; using NewRelic.Parsing.ConnectionString; using StackExchange.Redis.Profiling; @@ -81,10 +82,10 @@ public void Harvest(ISegment hostSegment) private void CleanUp() { - var cleanedSessions = 0; - try { + var cleanedSessions = 0; + foreach (var pair in _sessionCache) { // This can happen outside the lock since the object transaction was garbage collected. @@ -107,10 +108,11 @@ private void CleanUp() } } } + + Log.Finest($"SessionCache.Cleanup() removed {cleanedSessions}"); + _agent.RecordSupportabilityMetric(SessionCacheCleanupSupportabilityMetricName, cleanedSessions); } catch { } // Don't want to log here, just want to prevent collection problems from breaking things. - - _agent.RecordSupportabilityMetric(SessionCacheCleanupSupportabilityMetricName, cleanedSessions); } private ConnectionInfo GetConnectionInfo(EndPoint endpoint)