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.audit.monitor; 018 019import java.util.LinkedHashMap; 020import java.util.Set; 021import java.util.concurrent.ConcurrentHashMap; 022import java.util.concurrent.atomic.AtomicLong; 023 024import org.forgerock.http.Handler; 025import org.forgerock.http.protocol.Request; 026import org.forgerock.http.protocol.Response; 027import org.forgerock.http.protocol.Status; 028import org.forgerock.openig.heap.GenericHeapObject; 029import org.forgerock.openig.util.EnumUtil; 030import org.forgerock.services.context.Context; 031import org.forgerock.util.promise.NeverThrowsException; 032import org.forgerock.util.promise.Promise; 033import org.forgerock.util.promise.Promises; 034 035 036/** 037 * Sample statistic endpoint provider that returns JSON-formatted collected statistic values. 038 */ 039@Deprecated 040public class MonitorEndpointHandler extends GenericHeapObject implements org.forgerock.openig.audit.AuditEventListener, 041 Handler { 042 043 private static final Set<String> STANDARD_TAG_NAMES = EnumUtil.names(org.forgerock.openig.audit.Tag.class); 044 045 private ConcurrentHashMap<String, TagMetric> metrics = new ConcurrentHashMap<>(); 046 047 @Override 048 public Promise<Response, NeverThrowsException> handle(final Context context, final Request request) { 049 Response response = new Response(); 050 response.getEntity().setJson(metrics); 051 response.setStatus(Status.OK); 052 return Promises.newResultPromise(response); 053 } 054 055 @Override 056 public void onAuditEvent(final org.forgerock.openig.audit.AuditEvent event) { 057 // Extract the set of additional tags 058 Set<String> tags = event.getTags(); 059 060 // Manage counter for each of the additional tags, effectively performing correlations 061 for (String tag : tags) { 062 // Ignore tag if it is a standard one 063 if (STANDARD_TAG_NAMES.contains(tag)) { 064 continue; 065 } 066 TagMetric metric = getMetric(tag); 067 if (tags.contains(org.forgerock.openig.audit.Tag.request.name())) { 068 metric.active.incrementAndGet(); 069 } 070 if (tags.contains(org.forgerock.openig.audit.Tag.response.name())) { 071 metric.active.decrementAndGet(); 072 if (tags.contains(org.forgerock.openig.audit.Tag.completed.name())) { 073 metric.completed.incrementAndGet(); 074 } 075 if (tags.contains(org.forgerock.openig.audit.Tag.exception.name())) { 076 metric.errors.incrementAndGet(); 077 } 078 } 079 } 080 } 081 082 private TagMetric getMetric(final String name) { 083 TagMetric counter = metrics.get(name); 084 if (counter != null) { 085 return counter; 086 } 087 TagMetric newCounter = new TagMetric(); 088 TagMetric oldCounter = metrics.putIfAbsent(name, newCounter); 089 return oldCounter != null ? oldCounter : newCounter; 090 } 091 092 /** 093 * TagMetric extends a Map implementation to benefit of the natural mapping into a JSON object. 094 * Still have 'in progress', 'completed' and 'internal errors' fields for easy programmatic access. 095 * TagMetric is thread-safe because no additional fields are put in the structure after creation. 096 */ 097 private static class TagMetric extends LinkedHashMap<String, AtomicLong> { 098 099 public static final long serialVersionUID = 1L; 100 101 final AtomicLong active = new AtomicLong(); 102 final AtomicLong completed = new AtomicLong(); 103 final AtomicLong errors = new AtomicLong(); 104 105 public TagMetric() { 106 put("in progress", active); 107 put("completed", completed); 108 put("internal errors", errors); 109 } 110 } 111 112 /** 113 * Creates and initializes a MonitorEndpointHandler in a heap environment. 114 */ 115 @Deprecated 116 public static class Heaplet extends 117 org.forgerock.openig.audit.ConditionalAuditEventListener.ConditionalListenerHeaplet { 118 @Override 119 protected org.forgerock.openig.audit.AuditEventListener createListener() { 120 return new MonitorEndpointHandler(); 121 } 122 } 123 124}