Log context cache statistics in the TCF
Prior to this commit, finding out how many application contexts had been loaded within a test suite required the use of reflection and a bit of hacking. This commit addresses this issue by logging ContextCache statistics whenever an application context is loaded by the Spring TestContext Framework (TCF). The log output can be enabled by setting the "org.springframework.test.context.cache" logging category to DEBUG. Issue: SPR-12409
This commit is contained in:
parent
8b5fda5ad9
commit
da04362a5e
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -22,6 +22,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
@ -64,9 +65,9 @@ class ContextCache {
|
||||||
private final Map<MergedContextConfiguration, Set<MergedContextConfiguration>> hierarchyMap = new ConcurrentHashMap<MergedContextConfiguration, Set<MergedContextConfiguration>>(
|
private final Map<MergedContextConfiguration, Set<MergedContextConfiguration>> hierarchyMap = new ConcurrentHashMap<MergedContextConfiguration, Set<MergedContextConfiguration>>(
|
||||||
64);
|
64);
|
||||||
|
|
||||||
private int hitCount;
|
private final AtomicInteger hitCount = new AtomicInteger();
|
||||||
|
|
||||||
private int missCount;
|
private final AtomicInteger missCount = new AtomicInteger();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -84,8 +85,8 @@ class ContextCache {
|
||||||
* Clears hit and miss count statistics for the cache (i.e., resets counters to zero).
|
* Clears hit and miss count statistics for the cache (i.e., resets counters to zero).
|
||||||
*/
|
*/
|
||||||
void clearStatistics() {
|
void clearStatistics() {
|
||||||
this.hitCount = 0;
|
this.hitCount.set(0);
|
||||||
this.missCount = 0;
|
this.missCount.set(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -116,45 +117,31 @@ class ContextCache {
|
||||||
synchronized (monitor) {
|
synchronized (monitor) {
|
||||||
ApplicationContext context = this.contextMap.get(key);
|
ApplicationContext context = this.contextMap.get(key);
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
incrementMissCount();
|
this.missCount.incrementAndGet();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
incrementHitCount();
|
this.hitCount.incrementAndGet();
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increment the hit count by one. A <em>hit</em> is an access to the cache, which
|
* Get the overall hit count for this cache.
|
||||||
* returned a non-null context for a queried key.
|
* <p>A <em>hit</em> is an access to the cache, which returned a non-null context for
|
||||||
*/
|
* a queried key.
|
||||||
private void incrementHitCount() {
|
|
||||||
this.hitCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment the miss count by one. A <em>miss</em> is an access to the cache, which
|
|
||||||
* returned a {@code null} context for a queried key.
|
|
||||||
*/
|
|
||||||
private void incrementMissCount() {
|
|
||||||
this.missCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the overall hit count for this cache. A <em>hit</em> is an access to the cache,
|
|
||||||
* which returned a non-null context for a queried key.
|
|
||||||
*/
|
*/
|
||||||
int getHitCount() {
|
int getHitCount() {
|
||||||
return this.hitCount;
|
return this.hitCount.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the overall miss count for this cache. A <em>miss</em> is an access to the
|
* Get the overall miss count for this cache.
|
||||||
* cache, which returned a {@code null} context for a queried key.
|
* <p>A <em>miss</em> is an access to the cache, which returned a {@code null} context
|
||||||
|
* for a queried key.
|
||||||
*/
|
*/
|
||||||
int getMissCount() {
|
int getMissCount() {
|
||||||
return this.missCount;
|
return this.missCount.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContextLoaderD
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(DefaultCacheAwareContextLoaderDelegate.class);
|
private static final Log logger = LogFactory.getLog(DefaultCacheAwareContextLoaderDelegate.class);
|
||||||
|
|
||||||
|
private static final Log statsLogger = LogFactory.getLog("org.springframework.test.context.cache");
|
||||||
|
|
||||||
private final ContextCache contextCache;
|
private final ContextCache contextCache;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -98,6 +100,11 @@ class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContextLoaderD
|
||||||
mergedContextConfiguration));
|
mergedContextConfiguration));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statsLogger.isDebugEnabled()) {
|
||||||
|
statsLogger.debug(String.format("Spring test ApplicationContext cache statistics: %s", contextCache));
|
||||||
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ log4j.logger.org.springframework.test.context.ContextLoaderUtils=WARN
|
||||||
log4j.logger.org.springframework.test.context.transaction.TransactionalTestExecutionListener=WARN
|
log4j.logger.org.springframework.test.context.transaction.TransactionalTestExecutionListener=WARN
|
||||||
log4j.logger.org.springframework.test.context.web=WARN
|
log4j.logger.org.springframework.test.context.web=WARN
|
||||||
log4j.logger.org.springframework.test.context=WARN
|
log4j.logger.org.springframework.test.context=WARN
|
||||||
|
log4j.logger.org.springframework.test.context.cache=WARN
|
||||||
|
|
||||||
#log4j.logger.org.springframework.test.context.support=INFO
|
#log4j.logger.org.springframework.test.context.support=INFO
|
||||||
#log4j.logger.org.springframework.test.context.support.DelegatingSmartContextLoader=INFO
|
#log4j.logger.org.springframework.test.context.support.DelegatingSmartContextLoader=INFO
|
||||||
|
|
|
||||||
|
|
@ -20851,6 +20851,12 @@ framework will not be able to cache application contexts between test classes an
|
||||||
build process will run significantly slower as a result.
|
build process will run significantly slower as a result.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
Since having a large number of application contexts loaded within a given test suite can
|
||||||
|
cause the suite to take an unnecessarily long time to execute, it is often beneficial to
|
||||||
|
know exactly how many contexts have been loaded and cached. To view the statistics for
|
||||||
|
the underlying context cache, simply set the log level for the
|
||||||
|
`org.springframework.test.context.cache` logging category to `DEBUG`.
|
||||||
|
|
||||||
In the unlikely case that a test corrupts the application context and requires reloading
|
In the unlikely case that a test corrupts the application context and requires reloading
|
||||||
-- for example, by modifying a bean definition or the state of an application object --
|
-- for example, by modifying a bean definition or the state of an application object --
|
||||||
you can annotate your test class or test method with `@DirtiesContext` (see the
|
you can annotate your test class or test method with `@DirtiesContext` (see the
|
||||||
|
|
@ -20860,6 +20866,7 @@ context before executing the next test. Note that support for the `@DirtiesConte
|
||||||
annotation is provided by the `DirtiesContextTestExecutionListener` which is enabled by
|
annotation is provided by the `DirtiesContextTestExecutionListener` which is enabled by
|
||||||
default.
|
default.
|
||||||
|
|
||||||
|
|
||||||
[[testcontext-ctx-management-ctx-hierarchies]]
|
[[testcontext-ctx-management-ctx-hierarchies]]
|
||||||
====== Context hierarchies
|
====== Context hierarchies
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue