pub struct ConnectionCounters {
pub create_calls: usize,
pub open_calls: usize,
pub close_calls: usize,
}Expand description
Statistics tracking connection lifecycle operations per connection plugin name.
ConnectionCounters provides a simple counter-based mechanism for monitoring connection
operations in the ConnectionManager. Each connection plugin name (e.g., “ssh”, “netconf”, “http”)
has its own set of counters that track how many times connections of that type have been
created, opened, and closed.
These counters are useful for:
- Performance Monitoring: Identify connection pool efficiency and reuse patterns
- Debugging: Detect connection leaks, excessive creation, or improper cleanup
- Testing: Verify connection lifecycle behavior in unit and integration tests
- Metrics: Export connection statistics for observability systems
§Counter Semantics
-
create_calls- Incremented when a new connection instance is created by the factory. This happens on the first call toget_or_create()for a uniqueConnectionKey. Multiple calls with the same key do not increment this counter. -
open_calls- Incremented whenopen()is called on a connection. This happens whenopen_connection()is called and the connection’sis_alive()returnsfalse. Callingopen_connection()on an already-alive connection does not increment this counter. -
close_calls- Incremented when a connection is closed viaclose_connection()orclose_all_connections(). Each connection is counted only once when it’s removed from the pool.
§Thread Safety
The counters are stored in a DashMap<String, ConnectionCounters> in the ConnectionManager,
providing thread-safe concurrent access. Multiple threads can increment counters for different
connection plugin names simultaneously without blocking each other.
§Usage Patterns
§Ideal Pattern (Efficient Connection Reuse)
create_calls: 1
open_calls: 1
close_calls: 1This indicates a connection was created once, opened once, and properly cleaned up. Multiple operations reused the same connection without reopening it.
§Connection Leak Pattern
create_calls: 5
open_calls: 5
close_calls: 0This indicates connections are being created but never closed, suggesting a resource leak.
§Excessive Recreation Pattern
create_calls: 100
open_calls: 100
close_calls: 100This indicates connections are being created and destroyed repeatedly instead of being reused, suggesting inefficient connection pooling.
§Examples
§Monitoring Connection Usage
let manager = ConnectionManager::with_connection_factory(factory);
let key = ConnectionKey::new("router1", "ssh");
let params = ResolvedConnectionParams {
hostname: "10.0.0.1".to_string(),
port: Some(22),
username: Some("admin".to_string()),
password: None,
platform: None,
extras: None,
};
// Perform operations
let runtime = Builder::new_current_thread().enable_all().build().unwrap();
runtime.block_on(async {
manager.open_connection(&key, ¶ms).await?;
manager.open_connection(&key, ¶ms).await?; // Reuses existing connection
Ok::<(), String>(())
})?;
manager.close_connection(&key);
// Check counters
let counters = manager.connection_counters_for("ssh").unwrap();
assert_eq!(counters.create_calls, 1); // Created once
assert_eq!(counters.open_calls, 1); // Opened once (second call reused)
assert_eq!(counters.close_calls, 1); // Closed once§Detecting Connection Leaks in Tests
let manager = ConnectionManager::with_connection_factory(factory);
let params = ResolvedConnectionParams {
hostname: "10.0.0.1".to_string(),
port: Some(22),
username: Some("admin".to_string()),
password: None,
platform: None,
extras: None,
};
// Open multiple connections
let runtime = Builder::new_current_thread().enable_all().build().unwrap();
for i in 1..=5 {
let key = ConnectionKey::new(format!("router{}", i), "ssh");
runtime.block_on(async { manager.open_connection(&key, ¶ms).await })?;
}
// Verify all connections were created
let counters = manager.connection_counters_for("ssh").unwrap();
assert_eq!(counters.create_calls, 5);
assert_eq!(counters.open_calls, 5);
// Clean up and verify no leaks
manager.close_all_connections();
let counters = manager.connection_counters_for("ssh").unwrap();
assert_eq!(counters.close_calls, 5); // All connections closed§Comparing Multiple Connection Types
let manager = ConnectionManager::with_connection_factory(factory);
let params = ResolvedConnectionParams {
hostname: "10.0.0.1".to_string(),
port: Some(22),
username: Some("admin".to_string()),
password: None,
platform: None,
extras: None,
};
// Open different connection plugin names
let runtime = Builder::new_current_thread().enable_all().build().unwrap();
runtime.block_on(async {
manager.open_connection(&ConnectionKey::new("router1", "ssh"), ¶ms).await?;
manager.open_connection(&ConnectionKey::new("router1", "netconf"), ¶ms).await?;
Ok::<(), String>(())
})?;
// Get snapshot of all counters
let snapshot = manager.connection_counters_snapshot();
let ssh_counters = snapshot.get("ssh").unwrap();
let netconf_counters = snapshot.get("netconf").unwrap();
assert_eq!(ssh_counters.create_calls, 1);
assert_eq!(netconf_counters.create_calls, 1);Fields§
§create_calls: usize§open_calls: usize§close_calls: usizeTrait Implementations§
Source§impl Clone for ConnectionCounters
impl Clone for ConnectionCounters
Source§fn clone(&self) -> ConnectionCounters
fn clone(&self) -> ConnectionCounters
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for ConnectionCounters
Source§impl Debug for ConnectionCounters
impl Debug for ConnectionCounters
Source§impl Default for ConnectionCounters
impl Default for ConnectionCounters
Source§fn default() -> ConnectionCounters
fn default() -> ConnectionCounters
impl Eq for ConnectionCounters
Source§impl PartialEq for ConnectionCounters
impl PartialEq for ConnectionCounters
Source§fn eq(&self, other: &ConnectionCounters) -> bool
fn eq(&self, other: &ConnectionCounters) -> bool
self and other values to be equal, and is used by ==.impl StructuralPartialEq for ConnectionCounters
Auto Trait Implementations§
impl Freeze for ConnectionCounters
impl RefUnwindSafe for ConnectionCounters
impl Send for ConnectionCounters
impl Sync for ConnectionCounters
impl Unpin for ConnectionCounters
impl UnsafeUnpin for ConnectionCounters
impl UnwindSafe for ConnectionCounters
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.