1 /* 2 * Copyright (C) 2015 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package dagger.producers.monitoring; 17 18 import com.google.common.util.concurrent.FutureCallback; 19 import com.google.common.util.concurrent.Futures; 20 import com.google.common.util.concurrent.ListenableFuture; 21 import dagger.producers.Produces; 22 23 /** 24 * A hook for monitoring the execution of individual {@linkplain Produces producer methods}. See 25 * {@link ProductionComponentMonitor} for how to install these monitors. 26 * 27 * <p>The lifecycle of the monitor, under normal conditions, is: 28 * <ul> 29 * <li>{@link #methodStarting()} 30 * <li>The method is called 31 * <li>{@link #methodFinished()} 32 * <li>If the method returns a value, then: 33 * <ul> 34 * <li>{@link #succeeded(Object)} if the method returned normally; or 35 * <li>{@link #failed(Throwable)} if the method threw an exception. 36 * </ul> 37 * <li>If the method returns a future, then: 38 * <ul> 39 * <li>{@link #succeeded(Object)} if the method returned normally, and the future succeeded; or 40 * <li>{@link #failed(Throwable)} if the method threw an exception, or returned normally and the 41 * future failed. 42 * </ul> 43 * </ul> 44 * 45 * <p>If any input to the monitored producer fails, {@link #failed(Throwable)} will be called 46 * immediately with the failed input's exception. If more than one input fails, an arbitrary failed 47 * input's exception is used. 48 * 49 * <p>If any of the monitor's methods throw, then the exception will be logged and processing will 50 * continue unaffected. 51 * 52 * @author Jesse Beder 53 */ 54 public abstract class ProducerMonitor { 55 /** 56 * Called when the producer method is about to start executing. 57 * 58 * <p>When multiple monitors are installed, the order that each monitor will call this method is 59 * unspecified, but will remain consistent throughout the course of the execution of a component. 60 */ 61 public void methodStarting() {} 62 63 /** 64 * Called when the producer method has finished executing. 65 * 66 * <p>When multiple monitors are installed, calls to this method will be in the reverse order from 67 * calls to {@link #methodStarting()}. 68 */ 69 public void methodFinished() {} 70 71 /** 72 * Called when the producers future has completed successfully with a value. 73 * 74 * <p>When multiple monitors are installed, calls to this method will be in the reverse order from 75 * calls to {@link #methodStarting()}. 76 */ 77 public void succeeded(Object o) {} 78 79 /** 80 * Called when the producer's future has failed with an exception. 81 * 82 * <p>When multiple monitors are installed, calls to this method will be in the reverse order from 83 * calls to {@link #methodStarting()}. 84 */ 85 public void failed(Throwable t) {} 86 87 /** 88 * Adds this monitor's completion methods as a callback to the future. This is only intended to be 89 * overridden in the framework! 90 */ 91 public <T> void addCallbackTo(ListenableFuture<T> future) { 92 Futures.addCallback( 93 future, 94 new FutureCallback<T>() { 95 @Override 96 public void onSuccess(T value) { 97 succeeded(value); 98 } 99 100 @Override 101 public void onFailure(Throwable t) { 102 failed(t); 103 } 104 }); 105 } 106 } 107