Browse Source

add debug output for cacheservice

Jason Rivard 7 years ago
parent
commit
fb2045811b

+ 27 - 1
server/src/main/java/password/pwm/http/servlet/configmanager/DebugItemGenerator.java

@@ -38,6 +38,7 @@ import password.pwm.http.servlet.admin.UserDebugDataBean;
 import password.pwm.http.servlet.admin.UserDebugDataReader;
 import password.pwm.ldap.LdapDebugDataGenerator;
 import password.pwm.svc.PwmService;
+import password.pwm.svc.cache.CacheService;
 import password.pwm.svc.cluster.ClusterService;
 import password.pwm.util.LDAPPermissionCalculator;
 import password.pwm.util.java.FileSystemUtility;
@@ -100,7 +101,8 @@ public class DebugItemGenerator
             LocalDBDebugGenerator.class,
             SessionDataGenerator.class,
             LdapRecentUserDebugGenerator.class,
-            ClusterInfoDebugGenerator.class
+            ClusterInfoDebugGenerator.class,
+            CacheServiceDebugItemGenerator.class
     ) );
 
     static void outputZipDebugFile(
@@ -687,6 +689,30 @@ public class DebugItemGenerator
         }
     }
 
+    static class CacheServiceDebugItemGenerator implements Generator
+    {
+        @Override
+        public String getFilename( )
+        {
+            return "cache-service-info.json";
+        }
+
+        @Override
+        public void outputItem(
+                final PwmApplication pwmApplication,
+                final PwmRequest pwmRequest,
+                final OutputStream outputStream
+        )
+                throws Exception
+        {
+            final CacheService cacheService = pwmApplication.getCacheService();
+
+            final Map<String, Serializable> debugOutput = new LinkedHashMap<>( cacheService.debugInfo() );
+            outputStream.write( JsonUtil.serializeMap( debugOutput, JsonUtil.Flag.PrettyPrint ).getBytes( PwmConstants.DEFAULT_CHARSET ) );
+        }
+
+    }
+
 
     interface Generator
     {

+ 35 - 0
server/src/main/java/password/pwm/svc/cache/CacheDebugItem.java

@@ -0,0 +1,35 @@
+/*
+ * Password Management Servlets (PWM)
+ * http://www.pwm-project.org
+ *
+ * Copyright (c) 2006-2009 Novell, Inc.
+ * Copyright (c) 2009-2018 The PWM Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+package password.pwm.svc.cache;
+
+import lombok.Value;
+
+import java.io.Serializable;
+
+@Value
+class CacheDebugItem implements Serializable
+{
+    private String key;
+    private String age;
+    private int chars;
+}

+ 14 - 0
server/src/main/java/password/pwm/svc/cache/CacheService.java

@@ -34,9 +34,13 @@ import password.pwm.util.java.TimeDuration;
 import password.pwm.util.localdb.LocalDB;
 import password.pwm.util.logging.PwmLogger;
 
+import java.io.Serializable;
 import java.time.Instant;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 public class CacheService implements PwmService
 {
@@ -110,6 +114,16 @@ public class CacheService implements PwmService
         return new ServiceInfoBean( Collections.emptyList() );
     }
 
+    public Map<String, Serializable> debugInfo( )
+    {
+        final Map<String, Serializable> debugInfo = new LinkedHashMap<>( );
+        debugInfo.put( "memory-statistics", memoryCacheStore.getCacheStoreInfo() );
+        debugInfo.put( "memory-items", new ArrayList<Serializable>( memoryCacheStore.getCacheDebugItems() ) );
+        debugInfo.put( "localdb-statistics", localDBCacheStore.getCacheStoreInfo() );
+        debugInfo.put( "localdb-items", new ArrayList<Serializable>( localDBCacheStore.getCacheDebugItems() ) );
+        return Collections.unmodifiableMap( debugInfo );
+    }
+
     public void put( final CacheKey cacheKey, final CachePolicy cachePolicy, final String payload )
             throws PwmUnrecoverableException
     {

+ 3 - 0
server/src/main/java/password/pwm/svc/cache/CacheStore.java

@@ -25,6 +25,7 @@ package password.pwm.svc.cache;
 import password.pwm.error.PwmUnrecoverableException;
 
 import java.time.Instant;
+import java.util.List;
 
 public interface CacheStore
 {
@@ -35,4 +36,6 @@ public interface CacheStore
     CacheStoreInfo getCacheStoreInfo( );
 
     int itemCount( );
+
+    List<CacheDebugItem> getCacheDebugItems( );
 }

+ 31 - 0
server/src/main/java/password/pwm/svc/cache/LocalDBCacheStore.java

@@ -30,8 +30,10 @@ import password.pwm.util.localdb.LocalDB;
 import password.pwm.util.localdb.LocalDBException;
 import password.pwm.util.logging.PwmLogger;
 
+import java.time.Duration;
 import java.time.Instant;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.TimerTask;
 import java.util.concurrent.ExecutorService;
@@ -226,4 +228,33 @@ public class LocalDBCacheStore implements CacheStore
         }
         return 0;
     }
+
+    @Override
+    public List<CacheDebugItem> getCacheDebugItems( )
+    {
+        final List<CacheDebugItem> items = new ArrayList<>();
+        try ( LocalDB.LocalDBIterator<String> iter = localDB.iterator( DB ) )
+        {
+            while ( iter.hasNext() )
+            {
+                final String nextKey = iter.next();
+                final String storedValue = localDB.get( DB, nextKey );
+                if ( storedValue != null )
+                {
+                    final CacheValueWrapper valueWrapper = JsonUtil.deserialize( storedValue, CacheValueWrapper.class );
+                    final String hash = valueWrapper.getCacheKey().getStorageValue();
+                    final int chars = valueWrapper.getPayload().length();
+                    final Instant storeDate = valueWrapper.getExpirationDate();
+                    final String age = Duration.between( storeDate, Instant.now() ).toString();
+                    final CacheDebugItem cacheDebugItem = new CacheDebugItem( hash, age, chars );
+                    items.add( cacheDebugItem );
+                }
+            }
+        }
+        catch ( LocalDBException e )
+        {
+            LOGGER.error( "unexpected error reading debug items: " + e.getMessage(), e );
+        }
+        return Collections.unmodifiableList( items );
+    }
 }

+ 25 - 0
server/src/main/java/password/pwm/svc/cache/MemoryCacheStore.java

@@ -25,11 +25,18 @@ package password.pwm.svc.cache;
 import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
 import password.pwm.error.PwmUnrecoverableException;
+import password.pwm.util.logging.PwmLogger;
 
+import java.time.Duration;
 import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
 
 class MemoryCacheStore implements CacheStore
 {
+    private static final PwmLogger LOGGER = PwmLogger.forClass( MemoryCacheStore.class );
     private final Cache<String, CacheValueWrapper> memoryStore;
     private final CacheStoreInfo cacheStoreInfo = new CacheStoreInfo();
 
@@ -81,4 +88,22 @@ class MemoryCacheStore implements CacheStore
     {
         return ( int ) memoryStore.estimatedSize();
     }
+
+    @Override
+    public List<CacheDebugItem> getCacheDebugItems( )
+    {
+        final List<CacheDebugItem> items = new ArrayList<>();
+        final Iterator<CacheValueWrapper> iter = memoryStore.asMap().values().iterator();
+        while ( iter.hasNext() )
+        {
+            final CacheValueWrapper valueWrapper = iter.next();
+            final String hash = valueWrapper.getCacheKey().getStorageValue();
+            final int chars = valueWrapper.getPayload().length();
+            final Instant storeDate = valueWrapper.getExpirationDate();
+            final String age = Duration.between( storeDate, Instant.now() ).toString();
+            final CacheDebugItem cacheDebugItem = new CacheDebugItem( hash, age, chars );
+            items.add( cacheDebugItem );
+        }
+        return Collections.unmodifiableList( items );
+    }
 }