Utility methods relating to monitoring, for use in generated producers code.
| 31 | * Utility methods relating to monitoring, for use in generated producers code. |
| 32 | */ |
| 33 | public final class Monitors { |
| 34 | private static final Logger logger = Logger.getLogger(Monitors.class.getName()); |
| 35 | |
| 36 | /** |
| 37 | * Returns a monitor factory that delegates to the given factories, and ensures that any method |
| 38 | * called on this object, even transitively, does not throw a {@link RuntimeException} or return |
| 39 | * null. |
| 40 | * |
| 41 | * <p>If the delegate monitors throw an {@link Error}, then that will escape this monitor |
| 42 | * implementation. Errors are treated as unrecoverable conditions, and may cause the entire |
| 43 | * component's execution to fail. |
| 44 | */ |
| 45 | public static ProductionComponentMonitor.Factory delegatingProductionComponentMonitorFactory( |
| 46 | Collection<? extends ProductionComponentMonitor.Factory> factories) { |
| 47 | if (factories.isEmpty()) { |
| 48 | return ProductionComponentMonitor.Factory.noOp(); |
| 49 | } else if (factories.size() == 1) { |
| 50 | return new NonThrowingProductionComponentMonitor.Factory(Iterables.getOnlyElement(factories)); |
| 51 | } else { |
| 52 | return new DelegatingProductionComponentMonitor.Factory(factories); |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | /** |
| 57 | * Creates a new monitor for the given component, from a set of monitor factories. This will not |
| 58 | * throw a {@link RuntimeException} or return null. |
| 59 | */ |
| 60 | public static ProductionComponentMonitor createMonitorForComponent( |
| 61 | Provider<?> componentProvider, |
| 62 | Provider<Set<ProductionComponentMonitor.Factory>> monitorFactorySetProvider) { |
| 63 | try { |
| 64 | ProductionComponentMonitor.Factory factory = |
| 65 | delegatingProductionComponentMonitorFactory(monitorFactorySetProvider.get()); |
| 66 | return factory.create(componentProvider.get()); |
| 67 | } catch (RuntimeException e) { |
| 68 | logger.log(Level.SEVERE, "RuntimeException while constructing monitor factories.", e); |
| 69 | return ProductionComponentMonitor.noOp(); |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | /** |
| 74 | * A component monitor that delegates to a single monitor, and catches and logs all exceptions |
| 75 | * that the delegate throws. |
| 76 | */ |
| 77 | private static final class NonThrowingProductionComponentMonitor |
| 78 | extends ProductionComponentMonitor { |
| 79 | private final ProductionComponentMonitor delegate; |
| 80 | |
| 81 | NonThrowingProductionComponentMonitor(ProductionComponentMonitor delegate) { |
| 82 | this.delegate = delegate; |
| 83 | } |
| 84 | |
| 85 | @Override |
| 86 | public ProducerMonitor producerMonitorFor(ProducerToken token) { |
| 87 | try { |
| 88 | ProducerMonitor monitor = delegate.producerMonitorFor(token); |
| 89 | return monitor == null ? ProducerMonitor.noOp() : new NonThrowingProducerMonitor(monitor); |
| 90 | } catch (RuntimeException e) { |