Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Getting pool statistics #1173

Answered by bgrainger
NiKiZe asked this question in Q&A
Discussion options

Hi,
I use this hack for MySql.Data to get stats on the connection pool thru reflection.
Totally understanding that this is in no way supported, I still wonder if I could get some pointers on where similar values might exist in MySqlConnector ?

Logic psuedo explained:

  • Grab ConnectionPool object using connection string, since that is the unique key
  • Pull out Available "pool slots", inUse connections in pool, idle connections in pool
 public int[] GetPoolStatsViaReflection()
 {
 var asm = typeof(MySqlConnectionStringBuilder).Assembly;
 var poolManagerType = asm.GetType("MySql.Data.MySqlClient.MySqlPoolManager"); // internal sealed
 var poolType = asm.GetType("MySql.Data.MySqlClient.MySqlPool"); // internal sealed
 var pool = poolManagerType.InvokeMember("GetPool", System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, null, null, new object[] { this.connectionStringBuilder });
 const System.Reflection.BindingFlags nonPublicInstanceField = System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
 var totalAvailable = (int)poolType.InvokeMember("available", nonPublicInstanceField, null, pool, new object[] { });
 // List<Driver>
 var inUsePool = (System.Collections.ICollection)poolType.InvokeMember("inUsePool", nonPublicInstanceField, null, pool, new object[] { });
 // Queue<Driver>
 var idlePool = (System.Collections.ICollection)poolType.InvokeMember("idlePool", nonPublicInstanceField, null, pool, new object[] { });
 return new[] {totalAvailable, inUsePool.Count, idlePool.Count};
 }

I guess this lives in MySqlConnector.Core.ConnectionPool and maybe m_leasedSessions is similar to inUsePool?

You must be logged in to vote

MySqlConnector.Core.ConnectionPool.s_pools will contain all known connection pools:

private static readonly ConcurrentDictionary<string, ConnectionPool?> s_pools = new();

MySqlConnector.Core.ConnectionPool.m_sessions.Count has the number of idle (pooled) sessions:

private readonly LinkedList<ServerSession> m_sessions;

MySqlConnector.Core.ConnectionPool.m_leasedSessions.Count has the number of active (in-use) sessions:

Replies: 2 comments 1 reply

Comment options

Related: #491

You must be logged in to vote
0 replies
Comment options

MySqlConnector.Core.ConnectionPool.s_pools will contain all known connection pools:

private static readonly ConcurrentDictionary<string, ConnectionPool?> s_pools = new();

MySqlConnector.Core.ConnectionPool.m_sessions.Count has the number of idle (pooled) sessions:

private readonly LinkedList<ServerSession> m_sessions;

MySqlConnector.Core.ConnectionPool.m_leasedSessions.Count has the number of active (in-use) sessions:

private readonly Dictionary<string, ServerSession> m_leasedSessions;

MySqlConnector.Core.ConnectionPool.ConnectionSettings.MaximumPoolSize contains the maximum number of active connections that can be created:

public ConnectionSettings ConnectionSettings { get; }
public int MaximumPoolSize { get; }

I'm sure it goes without saying but this is completely unsupported. Moreover, this is highly concurrent code, and some of these properties are not safe to read when there are concurrent writers.

You must be logged in to vote
1 reply
Comment options

Fantastic, thanks!
I have not yet seen any issue with getting counts without locks (not thinking about getting missmatching values)
Saying it again absolutely unsupported, The usecase is to grab some data on exceptions. So should be rare.

Initial implementation:

 var asm = typeof(MySqlConnectionStringBuilder).Assembly;
 const string MySqlCoreName = "MySqlConnector." + nameof(MySqlConnector.Core);
 var poolType = asm.GetType(MySqlCoreName + ".ConnectionPool"); // internal sealed
 var settingType = asm.GetType(MySqlCoreName + ".ConnectionSettings"); // internal sealed
 var pool = poolType.InvokeMember("GetPool", System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, null, null, new object[] { this.connectionStringBuilder.ConnectionString });
 const System.Reflection.BindingFlags nonPublicInstanceField = System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
 var settings = poolType.InvokeMember("ConnectionSettings", nonPublicInstanceField | System.Reflection.BindingFlags.GetProperty, null, pool, new object[] { });
 var maxPoolSize = (int)settingType.InvokeMember("MaximumPoolSize", nonPublicInstanceField | System.Reflection.BindingFlags.GetProperty, null, settings, new object[] { });
 // Dictionary<string, ServerSession> // has the number of active (in-use) sessions:
 var inUse = (System.Collections.ICollection)poolType.InvokeMember("m_leasedSessions", nonPublicInstanceField, null, pool, new object[] { });
 // LinkedList<ServerSession> // has the number of idle (pooled) sessions:
 var idle = (System.Collections.ICollection)poolType.InvokeMember("m_sessions", nonPublicInstanceField, null, pool, new object[] { });
 var inUseCount = inUse.Count;
 var idleCount = idle.Count;
 return new[] { maxPoolSize - inUseCount, inUseCount, idleCount };
Answer selected by NiKiZe
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants

AltStyle によって変換されたページ (->オリジナル) /