Skip to content

Commit

Permalink
Set default log level of JDK logging to INFO and polish code of SpiLo…
Browse files Browse the repository at this point in the history
…ader (alibaba#1365)

* Improve log info in SpiLoader, improve comment and test case
* Use error level in catch block, init ArrayList with capacity and improve add item to list
  • Loading branch information
cdfive authored Apr 3, 2020
1 parent edb038c commit baa4289
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ protected Handler makeLoggingHandler(String logName, Logger heliumRecordLog) {
if (handler != null) {
disableOtherHandlers(heliumRecordLog, handler);
}
heliumRecordLog.setLevel(Level.ALL);

// Set log level to INFO by default
heliumRecordLog.setLevel(Level.INFO);
return handler;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public ProcessorSlotChain build() {
ProcessorSlotChain chain = new DefaultProcessorSlotChain();

// Note: the instances of ProcessorSlot should be different, since they are not stateless.
List<ProcessorSlot> sortedSlotList = SpiLoader.loadDifferentInstanceListSorted(ProcessorSlot.class);
List<ProcessorSlot> sortedSlotList = SpiLoader.loadPrototypeInstanceListSorted(ProcessorSlot.class);
for (ProcessorSlot slot : sortedSlotList) {
if (!(slot instanceof AbstractLinkedProcessorSlot)) {
RecordLog.warn("The ProcessorSlot(" + slot.getClass().getCanonicalName() + ") is not an instance of AbstractLinkedProcessorSlot, can't be added into ProcessorSlotChain");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ public final class SpiLoader {

private static final Map<String, ServiceLoader> SERVICE_LOADER_MAP = new ConcurrentHashMap<String, ServiceLoader>();

/**
* Load the first-found specific SPI instance
*
* @param clazz class of the SPI interface
* @param <T> SPI type
* @return the first specific SPI instance if exists, or else return null
* @since 1.7.0
*/
public static <T> T loadFirstInstance(Class<T> clazz) {
AssertUtil.notNull(clazz, "SPI class cannot be null");
try {
Expand All @@ -52,7 +60,7 @@ public static <T> T loadFirstInstance(Class<T> clazz) {
return null;
}
} catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadFirstInstance failed", t);
RecordLog.error("[SpiLoader] ERROR: loadFirstInstance failed", t);
t.printStackTrace();
return null;
}
Expand Down Expand Up @@ -87,7 +95,7 @@ public static <T> T loadFirstInstanceOrDefault(Class<T> clazz, Class<? extends T
}
return defaultClass.newInstance();
} catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadFirstInstanceOrDefault failed", t);
RecordLog.error("[SpiLoader] ERROR: loadFirstInstanceOrDefault failed", t);
t.printStackTrace();
return null;
}
Expand All @@ -96,6 +104,8 @@ public static <T> T loadFirstInstanceOrDefault(Class<T> clazz, Class<? extends T
/**
* Load the SPI instance with highest priority.
*
* Note: each call return same instances.
*
* @param clazz class of the SPI
* @param <T> SPI type
* @return the SPI instance with highest priority if exists, or else false
Expand All @@ -114,15 +124,15 @@ public static <T> T loadHighestPriorityInstance(Class<T> clazz) {
SpiOrderWrapper<T> w = null;
for (T spi : serviceLoader) {
int order = SpiOrderResolver.resolveOrder(spi);
RecordLog.info("[SpiLoader] Found {} SPI: {} with order " + order, clazz.getSimpleName(),
spi.getClass().getCanonicalName());
RecordLog.info("[SpiLoader] Found {} SPI: {} with order {}", clazz.getSimpleName(),
spi.getClass().getCanonicalName(), order);
if (w == null || order < w.order) {
w = new SpiOrderWrapper<>(order, spi);
}
}
return w == null ? null : w.spi;
} catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadHighestPriorityInstance failed", t);
RecordLog.error("[SpiLoader] ERROR: loadHighestPriorityInstance failed", t);
t.printStackTrace();
return null;
}
Expand All @@ -132,6 +142,8 @@ public static <T> T loadHighestPriorityInstance(Class<T> clazz) {
* Load and sorted SPI instance list.
* Load the SPI instance list for provided SPI interface.
*
* Note: each call return same instances.
*
* @param clazz class of the SPI
* @param <T> SPI type
* @return sorted SPI instance list
Expand All @@ -149,11 +161,13 @@ public static <T> List<T> loadInstanceList(Class<T> clazz) {

List<T> list = new ArrayList<>();
for (T spi : serviceLoader) {
RecordLog.info("[SpiLoader] Found {} SPI: {}", clazz.getSimpleName(),
spi.getClass().getCanonicalName());
list.add(spi);
}
return list;
} catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadInstanceListSorted failed", t);
RecordLog.error("[SpiLoader] ERROR: loadInstanceList failed", t);
t.printStackTrace();
return new ArrayList<>();
}
Expand All @@ -162,7 +176,7 @@ public static <T> List<T> loadInstanceList(Class<T> clazz) {
/**
* Load the sorted SPI instance list for provided SPI interface.
*
* Note: each call return new instances.
* Note: each call return same instances.
*
* @param clazz class of the SPI
* @param <T> SPI type
Expand All @@ -184,32 +198,32 @@ public static <T> List<T> loadInstanceListSorted(Class<T> clazz) {
int order = SpiOrderResolver.resolveOrder(spi);
// Since SPI is lazy initialized in ServiceLoader, we use online sort algorithm here.
SpiOrderResolver.insertSorted(orderWrappers, spi, order);
RecordLog.info("[SpiLoader] Found {} SPI: {} with order " + order, clazz.getSimpleName(),
spi.getClass().getCanonicalName());
RecordLog.info("[SpiLoader] Found {} SPI: {} with order {}", clazz.getSimpleName(),
spi.getClass().getCanonicalName(), order);
}
List<T> list = new ArrayList<>();
List<T> list = new ArrayList<>(orderWrappers.size());
for (int i = 0; i < orderWrappers.size(); i++) {
list.add(i, orderWrappers.get(i).spi);
list.add(orderWrappers.get(i).spi);
}
return list;
} catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadInstanceListSorted failed", t);
RecordLog.error("[SpiLoader] ERROR: loadInstanceListSorted failed", t);
t.printStackTrace();
return new ArrayList<>();
}
}

/**
* Load the sorted and different SPI instance list for provided SPI interface.
* Load the sorted and prototype SPI instance list for provided SPI interface.
*
* Note: each call return new instances.
* Note: each call return different instances, i.e. prototype instance, not singleton instance.
*
* @param clazz class of the SPI
* @param <T> SPI type
* @return sorted and different SPI instance list
* @since 1.7.2
*/
public static <T> List<T> loadDifferentInstanceListSorted(Class<T> clazz) {
public static <T> List<T> loadPrototypeInstanceListSorted(Class<T> clazz) {
try {
// Not use SERVICE_LOADER_MAP, to make sure the instances loaded are different.
ServiceLoader<T> serviceLoader = ServiceLoaderUtil.getServiceLoader(clazz);
Expand All @@ -219,16 +233,16 @@ public static <T> List<T> loadDifferentInstanceListSorted(Class<T> clazz) {
int order = SpiOrderResolver.resolveOrder(spi);
// Since SPI is lazy initialized in ServiceLoader, we use online sort algorithm here.
SpiOrderResolver.insertSorted(orderWrappers, spi, order);
RecordLog.info("[SpiLoader] Found {0} SPI: {1} with order " + order, clazz.getSimpleName(),
spi.getClass().getCanonicalName());
RecordLog.debug("[SpiLoader] Found {} SPI: {} with order {}", clazz.getSimpleName(),
spi.getClass().getCanonicalName(), order);
}
List<T> list = new ArrayList<>();
List<T> list = new ArrayList<>(orderWrappers.size());
for (int i = 0; i < orderWrappers.size(); i++) {
list.add(i, orderWrappers.get(i).spi);
list.add(orderWrappers.get(i).spi);
}
return list;
} catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadDifferentInstanceListSorted failed", t);
RecordLog.error("[SpiLoader] ERROR: loadPrototypeInstanceListSorted failed", t);
t.printStackTrace();
return new ArrayList<>();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,30 @@ public void testLoadFirstInstance() {
ProcessorSlot processorSlot = SpiLoader.loadFirstInstance(ProcessorSlot.class);
assertNotNull(processorSlot);

ProcessorSlot processorSlot2 = SpiLoader.loadFirstInstance(ProcessorSlot.class);
// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances
assertSame(processorSlot, processorSlot2);

SlotChainBuilder slotChainBuilder = SpiLoader.loadFirstInstance(SlotChainBuilder.class);
assertNotNull(slotChainBuilder);
assertTrue(slotChainBuilder instanceof DefaultSlotChainBuilder);

SlotChainBuilder slotChainBuilder2 = SpiLoader.loadFirstInstance(SlotChainBuilder.class);
// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances
assertSame(slotChainBuilder, slotChainBuilder2);
}

@Test
public void testLoadHighestPriorityInstance() {
ProcessorSlot processorSlot = SpiLoader.loadHighestPriorityInstance(ProcessorSlot.class);
assertNotNull(processorSlot);

// NodeSelectorSlot is highest order with @SpiOrder(-9000), among all slots
// NodeSelectorSlot is highest order with @SpiOrder(-10000), among all slots
assertTrue(processorSlot instanceof NodeSelectorSlot);

ProcessorSlot processorSlot2 = SpiLoader.loadHighestPriorityInstance(ProcessorSlot.class);
// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances
assertSame(processorSlot, processorSlot2);
}

@Test
Expand All @@ -66,14 +78,15 @@ public void testLoadInstanceList() {
// Total 8 default slot in sentinel-core
assertEquals(8, slots.size());

// Store the first slot of slots
// Get the first slot of slots
ProcessorSlot firstSlot = slots.get(0);

// Call loadInstanceList again
List<ProcessorSlot> slots2 = SpiLoader.loadInstanceList(ProcessorSlot.class);
// Note: the return list are different, and the item instances in list are same
assertNotSame(slots, slots2);

// Store the first slot of slots
// Get the first slot of slots2
ProcessorSlot firstSlot2 = slots2.get(0);

// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances
Expand All @@ -100,18 +113,22 @@ public void testLoadInstanceListSorted() {
assertTrue(sortedSlots.get(index++) instanceof DegradeSlot);

// Verify each call return different instances
// Note: the return list are different, and the item instances in list are same
List<ProcessorSlot> sortedSlots2 = SpiLoader.loadInstanceListSorted(ProcessorSlot.class);
assertNotSame(sortedSlots, sortedSlots2);
assertEquals(sortedSlots.size(), sortedSlots2.size());
for (int i = 0; i < sortedSlots.size(); i++) {
ProcessorSlot slot = sortedSlots.get(i);
ProcessorSlot slot2 = sortedSlots2.get(i);
assertEquals(slot.getClass(), slot2.getClass());

// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances
assertSame(slot, slot2);
}
}

@Test
public void testLoadDifferentInstanceListSorted() {
public void testLoadPrototypeInstanceListSorted() {
List<ProcessorSlot> sortedSlots = SpiLoader.loadInstanceListSorted(ProcessorSlot.class);
assertNotNull(sortedSlots);

Expand All @@ -129,8 +146,8 @@ public void testLoadDifferentInstanceListSorted() {
assertTrue(sortedSlots.get(index++) instanceof FlowSlot);
assertTrue(sortedSlots.get(index++) instanceof DegradeSlot);

// Verify each call return different instances
List<ProcessorSlot> sortedSlots2 = SpiLoader.loadDifferentInstanceListSorted(ProcessorSlot.class);
// Verify each call return new instances
List<ProcessorSlot> sortedSlots2 = SpiLoader.loadPrototypeInstanceListSorted(ProcessorSlot.class);
assertNotSame(sortedSlots, sortedSlots2);
assertEquals(sortedSlots.size(), sortedSlots2.size());
for (int i = 0; i < sortedSlots.size(); i++) {
Expand Down

0 comments on commit baa4289

Please sign in to comment.