Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Prevent multiple SessionCache instances from being created. (#2180) #2186

Merged
merged 1 commit into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions src/Agent/NewRelic/Agent/Core/Agent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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)
{
Expand All @@ -23,22 +24,26 @@ public CanWrapResponse CanWrap(InstrumentedMethodInfo methodInfo)
public AfterWrappedMethodDelegate BeforeWrappedMethod(InstrumentedMethodCall instrumentedMethodCall, IAgent agent, Agent.Api.ITransaction transaction)
{
return Delegates.GetDelegateFor<ConnectionMultiplexer>(
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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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.
Expand All @@ -107,10 +108,11 @@ private void CleanUp()
}
}
}

Log.Finest($"SessionCache.Cleanup() removed {cleanedSessions}");
_agent.RecordSupportabilityMetric(SessionCacheCleanupSupportabilityMetricName, cleanedSessions);
chynesNR marked this conversation as resolved.
Show resolved Hide resolved
}
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)
Expand Down
Loading