mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
19.05.2007 e46c6d744ad40707335478e539edba1935f8c39a
Add a new monitor provider that can be used to monitor memory usage within the
JVM, including:

- The total number of garbage collections (per memory pool)
- The total duration of all garbage collections (per memory pool)
- The averge duration for a garbage collection (per memory pool)
- The duration of the most recent garbage collection (per memory pool)
- The current size of each memory region
- The size of each memory region after the last garbage collection
2 files added
2 files modified
423 ■■■■■ changed files
opends/resource/config/config.ldif 24 ●●●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif 3 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/MemoryUsageMonitorProviderConfiguration.xml 61 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/monitors/MemoryUsageMonitorProvider.java 335 ●●●●● patch | view | raw | blame | history
opends/resource/config/config.ldif
@@ -1155,6 +1155,22 @@
ds-cfg-monitor-provider-class: org.opends.server.monitors.ClientConnectionMonitorProvider
ds-cfg-monitor-provider-enabled: true
dn: cn=Entry Cache,cn=Monitor Providers,cn=config
objectClass: top
objectClass: ds-cfg-monitor-provider
objectClass: ds-cfg-entry-cache-monitor-provider
cn: Entry Cache
ds-cfg-monitor-provider-class: org.opends.server.monitors.EntryCacheMonitorProvider
ds-cfg-monitor-provider-enabled: true
dn: cn=JVM Memory Usage,cn=Monitor Providers,cn=config
objectClass: top
objectClass: ds-cfg-monitor-provider
objectClass: ds-cfg-memory-usage-monitor-provider
cn: JVM Memory Usage
ds-cfg-monitor-provider-class: org.opends.server.monitors.MemoryUsageMonitorProvider
ds-cfg-monitor-provider-enabled: true
dn: cn=JVM Stack Trace,cn=Monitor Providers,cn=config
objectClass: top
objectClass: ds-cfg-monitor-provider
@@ -1179,14 +1195,6 @@
ds-cfg-monitor-provider-class: org.opends.server.monitors.VersionMonitorProvider
ds-cfg-monitor-provider-enabled: true
dn: cn=Entry Cache,cn=Monitor Providers,cn=config
objectClass: top
objectClass: ds-cfg-monitor-provider
objectClass: ds-cfg-entry-cache-monitor-provider
cn: Entry Cache
ds-cfg-monitor-provider-class: org.opends.server.monitors.EntryCacheMonitorProvider
ds-cfg-monitor-provider-enabled: true
dn: cn=Password Generators,cn=config
objectClass: top
objectClass: ds-cfg-branch
opends/resource/schema/02-config.ldif
@@ -2509,4 +2509,7 @@
objectClasses: ( 1.3.6.1.4.1.26027.1.2.173
  NAME 'ds-cfg-entry-cache-monitor-provider' SUP ds-cfg-monitor-provider
  STRUCTURAL X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.174
  NAME 'ds-cfg-memory-usage-monitor-provider' SUP ds-cfg-monitor-provider
  STRUCTURAL X-ORIGIN 'OpenDS Directory Server' )
opends/src/admin/defn/org/opends/server/admin/std/MemoryUsageMonitorProviderConfiguration.xml
New file
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
! CDDL HEADER START
!
! The contents of this file are subject to the terms of the
! Common Development and Distribution License, Version 1.0 only
! (the "License").  You may not use this file except in compliance
! with the License.
!
! You can obtain a copy of the license at
! trunk/opends/resource/legal-notices/OpenDS.LICENSE
! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
! See the License for the specific language governing permissions
! and limitations under the License.
!
! When distributing Covered Code, include this CDDL HEADER in each
! file and include the License file at
! trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
! add the following below this CDDL HEADER, with the fields enclosed
! by brackets "[]" replaced with your own identifying information:
!      Portions Copyright [yyyy] [name of copyright owner]
!
! CDDL HEADER END
!
!
!      Portions Copyright 2007 Sun Microsystems, Inc.
! -->
<adm:managed-object
  name="memory-usage-monitor-provider"
  plural-name="memory-usage-monitor-providers"
  package="org.opends.server.admin.std"
  extends="monitor-provider"
  xmlns:adm="http://www.opends.org/admin"
  xmlns:ldap="http://www.opends.org/admin-ldap">
  <adm:synopsis>
    The <adm:user-friendly-name /> may be used to publish information about
    memory consumption and garbage collection activity in the JVM.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.174</ldap:oid>
      <ldap:name>ds-cfg-memory-usage-monitor-provider</ldap:name>
      <ldap:superior>ds-cfg-monitor-provider</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property-override name="monitor-class">
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          org.opends.server.monitors.MemoryUsageMonitorProvider
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
  </adm:property-override>
</adm:managed-object>
opends/src/server/org/opends/server/monitors/MemoryUsageMonitorProvider.java
New file
@@ -0,0 +1,335 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.monitors;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import org.opends.server.admin.std.server.MemoryUsageMonitorProviderCfg;
import org.opends.server.api.MonitorProvider;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.InitializationException;
/**
 * This class defines a monitor provider that reports information about
 * Directory Server memory usage.
 */
public class MemoryUsageMonitorProvider
       extends MonitorProvider<MemoryUsageMonitorProviderCfg>
{
  // A map of the last GC counts seen by this monitor for calculating recent
  // stats.
  private HashMap<String,Long> lastGCCounts = new HashMap<String,Long>();
  // A map of the last GC times seen by this monitor for calculating recent
  // stats.
  private HashMap<String,Long> lastGCTimes = new HashMap<String,Long>();
  // A map of the most recent GC durations seen by this monitor.
  private HashMap<String,Long> recentGCDurations = new HashMap<String,Long>();
  // A map of the memory manager names to names that are safe for use in
  // attribute names.
  private HashMap<String,String> gcSafeNames = new HashMap<String,String>();
  /**
   * Initializes this monitor provider.
   */
  public MemoryUsageMonitorProvider()
  {
    super("JVM Memory Usage Monitor Provider");
    // No initialization should be performed here.
  }
  /**
   * {@inheritDoc}
   */
  public void initializeMonitorProvider(
                   MemoryUsageMonitorProviderCfg configuration)
         throws ConfigException, InitializationException
  {
    // No initialization is required.
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public String getMonitorInstanceName()
  {
    return "JVM Memory Usage";
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public long getUpdateInterval()
  {
    // Update the information once every second.
    return 1000;
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public void updateMonitorData()
  {
    for (GarbageCollectorMXBean gc :
         ManagementFactory.getGarbageCollectorMXBeans())
    {
      String gcName  = gc.getName();
      long   gcCount = gc.getCollectionCount();
      long   gcTime  = gc.getCollectionTime();
      long lastGCCount      = 0L;
      long lastGCTime       = 0L;
      long recentGCDuration = 0L;
      if (lastGCCounts.containsKey(gcName))
      {
        lastGCCount      = lastGCCounts.get(gcName);
        lastGCTime       = lastGCTimes.get(gcName);
        recentGCDuration = recentGCDurations.get(gcName);
      }
      if (gcCount > lastGCCount)
      {
        long recentGCCount = gcCount - lastGCCount;
        long recentGCTime  = gcTime  - lastGCTime;
        recentGCDuration   = (recentGCTime / recentGCCount);
      }
      lastGCCounts.put(gcName, gcCount);
      lastGCTimes.put(gcName, gcTime);
      recentGCDurations.put(gcName, recentGCDuration);
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public ArrayList<Attribute> getMonitorData()
  {
    ArrayList<Attribute> attrs = new ArrayList<Attribute>();
    for (GarbageCollectorMXBean gc :
         ManagementFactory.getGarbageCollectorMXBeans())
    {
      String gcName  = gc.getName();
      long   gcCount = gc.getCollectionCount();
      long   gcTime  = gc.getCollectionTime();
      long avgGCDuration = 0L;
      if (gcCount > 0)
      {
        avgGCDuration = gcTime / gcCount;
      }
      long recentGCDuration = 0L;
      if (recentGCDurations.containsKey(gcName))
      {
        recentGCDuration = recentGCDurations.get(gcName);
      }
      String safeName = gcSafeNames.get(gcName);
      if (safeName == null)
      {
        safeName = generateSafeName(gcName);
        gcSafeNames.put(gcName, safeName);
      }
      attrs.add(createAttribute(safeName + "-total-collection-count",
                                String.valueOf(gcCount)));
      attrs.add(createAttribute(safeName + "-total-collection-duration",
                                String.valueOf(gcTime)));
      attrs.add(createAttribute(safeName + "-average-collection-duration",
                                String.valueOf(avgGCDuration)));
      attrs.add(createAttribute(safeName + "-recent-collection-duration",
                                String.valueOf(recentGCDuration)));
    }
    for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans())
    {
      String      poolName        = mp.getName();
      MemoryUsage currentUsage    = mp.getUsage();
      MemoryUsage collectionUsage = mp.getCollectionUsage();
      String safeName = gcSafeNames.get(poolName);
      if (safeName == null)
      {
        safeName = generateSafeName(poolName);
        gcSafeNames.put(poolName, safeName);
      }
      if (currentUsage == null)
      {
        attrs.add(createAttribute(safeName + "-current-bytes-used", "0"));
      }
      else
      {
        attrs.add(createAttribute(safeName + "-current-bytes-used",
                                  String.valueOf(currentUsage.getUsed())));
      }
      if (collectionUsage == null)
      {
        attrs.add(createAttribute(safeName +
                                       "-bytes-used-after-last-collection",
                                  "0"));
      }
      else
      {
        attrs.add(createAttribute(safeName +
                                       "-bytes-used-after-last-collection",
                                  String.valueOf(collectionUsage.getUsed())));
      }
    }
    return attrs;
  }
  /**
   * Constructs an attribute using the provided information.  It will have the
   * default syntax.
   *
   * @param  name   The name to use for the attribute.
   * @param  value  The value to use for the attribute.
   *
   * @return  The attribute created from the provided information.
   */
  private Attribute createAttribute(String name, String value)
  {
    AttributeType attrType = DirectoryServer.getDefaultAttributeType(name);
    ASN1OctetString encodedValue = new ASN1OctetString(value);
    LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1);
    try
    {
      values.add(new AttributeValue(encodedValue,
                                    attrType.normalize(encodedValue)));
    }
    catch (Exception e)
    {
      values.add(new AttributeValue(encodedValue, encodedValue));
    }
    return new Attribute(attrType, name, values);
  }
  /**
   * Creates a "safe" version of the provided name, which is acceptable for
   * use as part of an attribute name.
   *
   * @param  name  The name for which to obtain the safe name.
   *
   * @return  The calculated safe name.
   */
  private String generateSafeName(String name)
  {
    StringBuilder buffer = new StringBuilder();
    boolean lastWasUppercase = false;
    boolean lastWasDash      = false;
    for (int i=0; i  < name.length(); i++)
    {
      char c = name.charAt(i);
      if (Character.isLetter(c))
      {
        if (Character.isUpperCase(c))
        {
          char lowerCaseCharacter = Character.toLowerCase(c);
          if ((buffer.length() > 0) && (! lastWasUppercase) && (! lastWasDash))
          {
            buffer.append('-');
          }
          buffer.append(lowerCaseCharacter);
          lastWasUppercase = true;
          lastWasDash = false;
        }
        else
        {
          buffer.append(c);
          lastWasUppercase = false;
          lastWasDash = false;
        }
      }
      else if (Character.isDigit(c))
      {
        buffer.append(c);
        lastWasUppercase = false;
        lastWasDash = false;
      }
      else if ((c == ' ') || (c == '_') || (c == '-'))
      {
        if (! lastWasDash)
        {
          buffer.append('-');
        }
        lastWasUppercase = false;
        lastWasDash = true;
      }
    }
    return buffer.toString();
  }
}