Home | History | Annotate | Download | only in monitoring
      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