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 2013-2016 ForgeRock AS. 015 */ 016package org.opends.server.protocols.http; 017 018import java.util.Arrays; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022import java.util.Map.Entry; 023import java.util.concurrent.atomic.AtomicInteger; 024import java.util.concurrent.atomic.AtomicLong; 025 026import org.opends.server.api.MonitorData; 027import org.opends.server.protocols.ldap.LDAPStatistics; 028 029/** 030 * Collects statistics for HTTP. This class inherits from {@link LDAPStatistics} 031 * to show the administrator how the underlying LDAP internal operations are 032 * performing. 033 */ 034public class HTTPStatistics extends LDAPStatistics 035{ 036 /** 037 * Map containing the total number of requests per HTTP methods. 038 * <p> 039 * key: HTTP method => value: number of requests for that method. 040 * </p> 041 * Not using a ConcurrentMap implementation here because the keys are static. 042 * The keys are static because they need to be listed in the schema which is 043 * static. 044 */ 045 private final Map<String, AtomicInteger> requestMethodsTotalCount = new HashMap<>(); 046 /** 047 * Map containing the total execution time for the requests per HTTP methods. 048 * <p> 049 * key: HTTP method => value: total execution time for requests using that 050 * method. 051 * </p> 052 * Not using a ConcurrentMap implementation here because the keys are static. 053 * The keys are static because they need to be listed in the schema which is 054 * static. 055 */ 056 private final Map<String, AtomicLong> requestMethodsTotalTime = new HashMap<>(); 057 /** 058 * Total number of requests. The total number may be different than the sum of 059 * the supported HTTP methods above because clients could use unsupported HTTP 060 * methods. 061 */ 062 private final AtomicInteger requestsTotalCount = new AtomicInteger(0); 063 064 /** 065 * Constructor for this class. 066 * 067 * @param instanceName 068 * The name for this monitor provider instance. 069 */ 070 public HTTPStatistics(String instanceName) 071 { 072 super(instanceName); 073 074 // List the HTTP methods supported by Rest2LDAP 075 final List<String> supportedHttpMethods = 076 Arrays.asList("delete", "get", "patch", "post", "put"); 077 for (String method : supportedHttpMethods) 078 { 079 requestMethodsTotalCount.put(method, new AtomicInteger(0)); 080 requestMethodsTotalTime.put(method, new AtomicLong(0)); 081 } 082 } 083 084 /** {@inheritDoc} */ 085 @Override 086 public void clearStatistics() 087 { 088 this.requestMethodsTotalCount.clear(); 089 this.requestMethodsTotalTime.clear(); 090 this.requestsTotalCount.set(0); 091 092 super.clearStatistics(); 093 } 094 095 @Override 096 public MonitorData getMonitorData() 097 { 098 final MonitorData results = super.getMonitorData(); 099 addAll(results, requestMethodsTotalCount, "ds-mon-http-", "-requests-total-count"); 100 addAll(results, requestMethodsTotalTime, "ds-mon-resident-time-http-", "-requests-total-time"); 101 results.add("ds-mon-http-requests-total-count", requestsTotalCount.get()); 102 return results; 103 } 104 105 private void addAll(final MonitorData results, 106 final Map<String, ?> toOutput, String prefix, String suffix) 107 { 108 for (Entry<String, ?> entry : toOutput.entrySet()) 109 { 110 final String httpMethod = entry.getKey(); 111 final String nb = entry.getValue().toString(); 112 results.add(prefix + httpMethod + suffix, nb); 113 } 114 } 115 116 /** 117 * Adds to the total time of an HTTP request method. 118 * 119 * @param httpMethod 120 * the method of the HTTP request to add to the stats 121 * @param time 122 * the time to add to the total 123 * @throws NullPointerException 124 * if the httpMethod is null 125 */ 126 public void updateRequestMonitoringData(String httpMethod, long time) 127 throws NullPointerException 128 { 129 AtomicLong nb = this.requestMethodsTotalTime.get(httpMethod.toLowerCase()); 130 if (nb != null) 131 { 132 nb.addAndGet(time); 133 } // else this is an unsupported HTTP method 134 } 135}