001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2014-2015 ForgeRock AS. 015 */ 016 017package org.forgerock.openig.decoration.timer; 018 019import static org.forgerock.openig.heap.Keys.LOGSINK_HEAP_KEY; 020 021import org.forgerock.http.Filter; 022import org.forgerock.http.Handler; 023import org.forgerock.json.JsonValue; 024import org.forgerock.openig.decoration.Context; 025import org.forgerock.openig.decoration.Decorator; 026import org.forgerock.openig.decoration.helper.AbstractHandlerAndFilterDecorator; 027import org.forgerock.openig.decoration.helper.DecoratorHeaplet; 028import org.forgerock.openig.heap.Heap; 029import org.forgerock.openig.heap.HeapException; 030import org.forgerock.openig.heap.Name; 031import org.forgerock.openig.log.LogSink; 032import org.forgerock.openig.log.Logger; 033 034/** 035 * The {@literal timer} decorator can decorate both {@link Filter} and {@link Handler} instances. 036 * It will log {@literal started}, {@literal elapsed} and {@literal elapsed-within} events into the {@link LogSink} 037 * of the decorated heap object. 038 * <p> 039 * It has to be declared inside of the heap objects section: 040 * <pre> 041 * {@code 042 * { 043 * "name": "timer", 044 * "type": "TimerDecorator" 045 * } 046 * } 047 * </pre> 048 * <p> 049 * To decorate a component, just add the decorator declaration next to the {@code config} element: 050 * <pre> 051 * {@code 052 * { 053 * "type": "...", 054 * "timer": true, 055 * "config": { ... } 056 * } 057 * } 058 * </pre> 059 * 060 * There is no special configuration required for this decorator. 061 * 062 * A default {@literal timer} decorator is automatically created when OpenIG starts. 063 */ 064public class TimerDecorator extends AbstractHandlerAndFilterDecorator { 065 066 @Override 067 protected Filter decorateFilter(final Filter delegate, final JsonValue decoratorConfig, final Context context) 068 throws HeapException { 069 if (decoratorConfig.asBoolean()) { 070 return new TimerFilter(delegate, getLogger(context)); 071 } 072 return delegate; 073 } 074 075 @Override 076 protected Handler decorateHandler(final Handler delegate, final JsonValue decoratorConfig, final Context context) 077 throws HeapException { 078 if (decoratorConfig.asBoolean()) { 079 return new TimerHandler(delegate, getLogger(context)); 080 } 081 return delegate; 082 } 083 084 /** 085 * Builds a new Logger dedicated for the heap object context. 086 * 087 * @param context 088 * Context of the heap object 089 * @return a new Logger dedicated for the heap object context. 090 * @throws HeapException 091 * when no logSink can be resolved (very unlikely to happen). 092 */ 093 private static Logger getLogger(final Context context) throws HeapException { 094 // Use the sink of the decorated component 095 Heap heap = context.getHeap(); 096 LogSink sink = heap.resolve(context.getConfig().get("logSink").defaultTo(LOGSINK_HEAP_KEY), LogSink.class); 097 Name name = context.getName(); 098 return new Logger(sink, name.decorated("Timer")); 099 } 100 101 /** 102 * Creates and initializes a TimerDecorator in a heap environment. 103 */ 104 public static class Heaplet extends DecoratorHeaplet { 105 @Override 106 public Decorator create() throws HeapException { 107 return new TimerDecorator(); 108 } 109 } 110}