Browse Source

new v2 statistics rest api

Jason Rivard 7 years ago
parent
commit
89edf91937

+ 2 - 0
server/src/main/java/password/pwm/AppProperty.java

@@ -334,6 +334,8 @@ public enum AppProperty
     WORDLIST_CHAR_LENGTH_MIN                        ( "wordlist.minCharLength" ),
     WORDLIST_CHAR_LENGTH_MIN                        ( "wordlist.minCharLength" ),
     WS_REST_CLIENT_PWRULE_HALTONERROR               ( "ws.restClient.pwRule.haltOnError" ),
     WS_REST_CLIENT_PWRULE_HALTONERROR               ( "ws.restClient.pwRule.haltOnError" ),
     WS_REST_SERVER_SIGNING_FORM_TIMEOUT_SECONDS     ( "ws.restServer.signing.form.timeoutSeconds" ),
     WS_REST_SERVER_SIGNING_FORM_TIMEOUT_SECONDS     ( "ws.restServer.signing.form.timeoutSeconds" ),
+    WS_REST_SERVER_STATISTICS_DEFAULT_HISTORY       ( "ws.restServer.statistics.defaultHistoryDays" ),
+    WS_REST_SERVER_STATISTICS_DEFAULT_VERSION       ( "ws.restServer.statistics.defaultVersion" ),
     ALLOW_MACRO_IN_REGEX_SETTING                    ( "password.policy.allowMacroInRegexSetting" ),;
     ALLOW_MACRO_IN_REGEX_SETTING                    ( "password.policy.allowMacroInRegexSetting" ),;
 
 
     public static final String VALUE_SEPARATOR = ";;;";
     public static final String VALUE_SEPARATOR = ";;;";

+ 5 - 10
server/src/main/java/password/pwm/http/servlet/admin/AdminServlet.java

@@ -555,16 +555,16 @@ public class AdminServlet extends ControlledPwmServlet
         final String days = pwmRequest.readParameterAsString( "days" );
         final String days = pwmRequest.readParameterAsString( "days" );
 
 
         final StatisticsManager statisticsManager = pwmRequest.getPwmApplication().getStatisticsManager();
         final StatisticsManager statisticsManager = pwmRequest.getPwmApplication().getStatisticsManager();
-        final RestStatisticsServer.JsonOutput jsonOutput = new RestStatisticsServer.JsonOutput();
-        jsonOutput.EPS = RestStatisticsServer.addEpsStats( statisticsManager );
+        final RestStatisticsServer.OutputVersion1.JsonOutput jsonOutput = new RestStatisticsServer.OutputVersion1.JsonOutput();
+        jsonOutput.EPS = RestStatisticsServer.OutputVersion1.addEpsStats( statisticsManager );
 
 
         if ( statName != null && statName.length() > 0 )
         if ( statName != null && statName.length() > 0 )
         {
         {
-            jsonOutput.nameData = RestStatisticsServer.doNameStat( statisticsManager, statName, days );
+            jsonOutput.nameData = RestStatisticsServer.OutputVersion1.doNameStat( statisticsManager, statName, days );
         }
         }
         else
         else
         {
         {
-            jsonOutput.keyData = RestStatisticsServer.doKeyStat( statisticsManager, statKey );
+            jsonOutput.keyData = RestStatisticsServer.OutputVersion1.doKeyStat( statisticsManager, statKey );
         }
         }
 
 
         final RestResultBean restResultBean = RestResultBean.withData( jsonOutput );
         final RestResultBean restResultBean = RestResultBean.withData( jsonOutput );
@@ -589,12 +589,7 @@ public class AdminServlet extends ControlledPwmServlet
             final AdminBean adminBean = pwmRequest.getPwmApplication().getSessionStateService().getBean( pwmRequest, AdminBean.class );
             final AdminBean adminBean = pwmRequest.getPwmApplication().getSessionStateService().getBean( pwmRequest, AdminBean.class );
             adminBean.setLastUserDebug( userIdentity );
             adminBean.setLastUserDebug( userIdentity );
         }
         }
-        catch ( PwmUnrecoverableException e )
-        {
-            setLastError( pwmRequest, e.getErrorInformation() );
-            return;
-        }
-        catch ( PwmOperationalException e )
+        catch ( PwmUnrecoverableException | PwmOperationalException e )
         {
         {
             setLastError( pwmRequest, e.getErrorInformation() );
             setLastError( pwmRequest, e.getErrorInformation() );
             return;
             return;

+ 78 - 78
server/src/main/java/password/pwm/svc/stats/Statistic.java

@@ -38,83 +38,83 @@ import java.util.TreeSet;
 
 
 public enum Statistic
 public enum Statistic
 {
 {
-    AUDIT_EVENTS( Type.INCREMENTOR, "AuditEvents", null ),
-    AUTHENTICATIONS( Type.INCREMENTOR, "Authentications", null ),
-    AUTHENTICATION_FAILURES( Type.INCREMENTOR, "AuthenticationFailures", null ),
-    AUTHENTICATION_EXPIRED( Type.INCREMENTOR, "Authentications_Expired", null ),
-    AUTHENTICATION_PRE_EXPIRED( Type.INCREMENTOR, "Authentications_PreExpired", null ),
-    AUTHENTICATION_EXPIRED_WARNING( Type.INCREMENTOR, "Authentications_ExpiredWarning", null ),
-    PWM_STARTUPS( Type.INCREMENTOR, "PWM_Startups", null ),
-    PWM_UNKNOWN_ERRORS( Type.INCREMENTOR, "PWM_UnknownErrors", null ),
-    PASSWORD_CHANGES( Type.INCREMENTOR, "PasswordChanges", null ),
-    FORGOTTEN_USERNAME_FAILURES( Type.INCREMENTOR, "ForgottenUsernameFailures", null ),
-    FORGOTTEN_USERNAME_SUCCESSES( Type.INCREMENTOR, "ForgottenUsernameSuccesses", null ),
-    EMAIL_SEND_SUCCESSES( Type.INCREMENTOR, "EmailSendSuccesses", null ),
-    EMAIL_SEND_FAILURES( Type.INCREMENTOR, "EmailSendFailures", null ),
-    EMAIL_SEND_DISCARDS( Type.INCREMENTOR, "EmailSendDiscards", null ),
-    SMS_SEND_SUCCESSES( Type.INCREMENTOR, "SmsSendSuccesses", null ),
-    SMS_SEND_FAILURES( Type.INCREMENTOR, "SmsSendFailures", null ),
-    SMS_SEND_DISCARDS( Type.INCREMENTOR, "SmsSendDiscards", null ),
-    PASSWORD_RULE_CHECKS( Type.INCREMENTOR, "PasswordRuleChecks", null ),
-    HTTP_REQUESTS( Type.INCREMENTOR, "HttpRequests", null ),
-    HTTP_RESOURCE_REQUESTS( Type.INCREMENTOR, "HttpResourceRequests", null ),
-    HTTP_SESSIONS( Type.INCREMENTOR, "HttpSessions", null ),
-    ACTIVATED_USERS( Type.INCREMENTOR, "ActivatedUsers", null ),
-    NEW_USERS( Type.INCREMENTOR, "NewUsers", new ConfigSettingDetail( PwmSetting.NEWUSER_ENABLE ) ),
-    GUESTS( Type.INCREMENTOR, "Guests", new ConfigSettingDetail( PwmSetting.GUEST_ENABLE ) ),
-    UPDATED_GUESTS( Type.INCREMENTOR, "UpdatedGuests", new ConfigSettingDetail( PwmSetting.GUEST_ENABLE ) ),
-    LOCKED_USERS( Type.INCREMENTOR, "LockedUsers", null ),
-    LOCKED_ADDRESSES( Type.INCREMENTOR, "LockedAddresses", null ),
-    LOCKED_USERIDS( Type.INCREMENTOR, "LockedUserDNs", null ),
-    LOCKED_ATTRIBUTES( Type.INCREMENTOR, "LockedAttributes", null ),
-    LOCKED_TOKENDESTS( Type.INCREMENTOR, "LockedTokenDests", null ),
-    CAPTCHA_SUCCESSES( Type.INCREMENTOR, "CaptchaSuccessess", null ),
-    CAPTCHA_FAILURES( Type.INCREMENTOR, "CaptchaFailures", null ),
-    CAPTCHA_PRESENTATIONS( Type.INCREMENTOR, "CaptchaPresentations", null ),
-    LDAP_UNAVAILABLE_COUNT( Type.INCREMENTOR, "LdapUnavailableCount", null ),
-    DB_UNAVAILABLE_COUNT( Type.INCREMENTOR, "DatabaseUnavailableCount", null ),
-    SETUP_RESPONSES( Type.INCREMENTOR, "SetupResponses", null ),
-    SETUP_OTP_SECRET( Type.INCREMENTOR, "SetupOtpSecret", null ),
-    UPDATE_ATTRIBUTES( Type.INCREMENTOR, "UpdateAttributes", new ConfigSettingDetail( PwmSetting.UPDATE_PROFILE_ENABLE ) ),
-    SHORTCUTS_SELECTED( Type.INCREMENTOR, "ShortcutsSelected", new ConfigSettingDetail( PwmSetting.SHORTCUT_ENABLE ) ),
-    GENERATED_PASSWORDS( Type.INCREMENTOR, "GeneratedPasswords", null ),
-    RECOVERY_SUCCESSES( Type.INCREMENTOR, "RecoverySuccesses", null ),
-    RECOVERY_FAILURES( Type.INCREMENTOR, "RecoveryFailures", null ),
-    TOKENS_SENT( Type.INCREMENTOR, "TokensSent", null ),
-    TOKENS_PASSSED( Type.INCREMENTOR, "TokensPassed", null ),
-    RECOVERY_TOKENS_SENT( Type.INCREMENTOR, "RecoveryTokensSent", null ),
-    RECOVERY_TOKENS_PASSED( Type.INCREMENTOR, "RecoveryTokensPassed", null ),
-    RECOVERY_TOKENS_FAILED( Type.INCREMENTOR, "RecoveryTokensFailed", null ),
-    RECOVERY_OTP_PASSED( Type.INCREMENTOR, "RecoveryOTPPassed", null ),
-    RECOVERY_OTP_FAILED( Type.INCREMENTOR, "RecoveryOTPFailed", null ),
-    PEOPLESEARCH_CACHE_HITS( Type.INCREMENTOR, "PeopleSearchCacheHits", new ConfigSettingDetail( PwmSetting.PEOPLE_SEARCH_ENABLE ) ),
-    PEOPLESEARCH_CACHE_MISSES( Type.INCREMENTOR, "PeopleSearchCacheMisses", new ConfigSettingDetail( PwmSetting.PEOPLE_SEARCH_ENABLE ) ),
-    PEOPLESEARCH_SEARCHES( Type.INCREMENTOR, "PeopleSearchSearches", new ConfigSettingDetail( PwmSetting.PEOPLE_SEARCH_ENABLE ) ),
-    PEOPLESEARCH_DETAILS( Type.INCREMENTOR, "PeopleSearchDetails", new ConfigSettingDetail( PwmSetting.PEOPLE_SEARCH_ENABLE ) ),
-    PEOPLESEARCH_ORGCHART( Type.INCREMENTOR, "PeopleSearchOrgChart", new ConfigSettingDetail( PwmSetting.PEOPLE_SEARCH_ENABLE ) ),
-    PWNOTIFY_JOBS ( Type.INCREMENTOR, "PwNotifyJobs", null ),
-    PWNOTIFY_JOB_ERRORS ( Type.INCREMENTOR, "PwNotifyJobErrors", null ),
-    PWNOTIFY_EMAILS_SENT ( Type.INCREMENTOR, "PwNotifyJobEmailsSent", null ),
-    HELPDESK_PASSWORD_SET( Type.INCREMENTOR, "HelpdeskPasswordSet", null ),
-    HELPDESK_USER_LOOKUP( Type.INCREMENTOR, "HelpdeskUserLookup", null ),
-    HELPDESK_TOKENS_SENT( Type.INCREMENTOR, "HelpdeskTokenSent", null ),
-    HELPDESK_UNLOCK( Type.INCREMENTOR, "HelpdeskUnlock", null ),
-    HELPDESK_VERIFY_OTP( Type.INCREMENTOR, "HelpdeskVerifyOTP", null ),
-    REST_STATUS( Type.INCREMENTOR, "RestStatus", null ),
-    REST_CHECKPASSWORD( Type.INCREMENTOR, "RestCheckPassword", null ),
-    REST_SETPASSWORD( Type.INCREMENTOR, "RestSetPassword", null ),
-    REST_RANDOMPASSWORD( Type.INCREMENTOR, "RestRandomPassword", null ),
-    REST_PROFILE( Type.INCREMENTOR, "RestProfile", null ),
-    REST_SIGNING_FORM( Type.INCREMENTOR, "RestSigningForm", null ),
-    REST_CHALLENGES( Type.INCREMENTOR, "RestChallenges", null ),
-    REST_HEALTH( Type.INCREMENTOR, "RestHealth", null ),
-    REST_STATISTICS( Type.INCREMENTOR, "RestStatistics", null ),
-    REST_VERIFYCHALLENGES( Type.INCREMENTOR, "RestVerifyChallenges", null ),
-    REST_VERIFYOTP( Type.INCREMENTOR, "RestVerifyOTP", null ),
-    INTRUDER_ATTEMPTS( Type.INCREMENTOR, "IntruderAttempts", null ),
-    FOREIGN_SESSIONS_ACCEPTED( Type.INCREMENTOR, "ForeignSessionsAccepted", null ),
-    OBSOLETE_URL_REQUESTS( Type.INCREMENTOR, "ObsoleteUrlRequests", null ),
-    SYSLOG_MESSAGES_SENT( Type.INCREMENTOR, "SyslogMessagesSent", null ),
+    AUDIT_EVENTS( Type.INCREMENTER, "AuditEvents", null ),
+    AUTHENTICATIONS( Type.INCREMENTER, "Authentications", null ),
+    AUTHENTICATION_FAILURES( Type.INCREMENTER, "AuthenticationFailures", null ),
+    AUTHENTICATION_EXPIRED( Type.INCREMENTER, "Authentications_Expired", null ),
+    AUTHENTICATION_PRE_EXPIRED( Type.INCREMENTER, "Authentications_PreExpired", null ),
+    AUTHENTICATION_EXPIRED_WARNING( Type.INCREMENTER, "Authentications_ExpiredWarning", null ),
+    PWM_STARTUPS( Type.INCREMENTER, "PWM_Startups", null ),
+    PWM_UNKNOWN_ERRORS( Type.INCREMENTER, "PWM_UnknownErrors", null ),
+    PASSWORD_CHANGES( Type.INCREMENTER, "PasswordChanges", null ),
+    FORGOTTEN_USERNAME_FAILURES( Type.INCREMENTER, "ForgottenUsernameFailures", null ),
+    FORGOTTEN_USERNAME_SUCCESSES( Type.INCREMENTER, "ForgottenUsernameSuccesses", null ),
+    EMAIL_SEND_SUCCESSES( Type.INCREMENTER, "EmailSendSuccesses", null ),
+    EMAIL_SEND_FAILURES( Type.INCREMENTER, "EmailSendFailures", null ),
+    EMAIL_SEND_DISCARDS( Type.INCREMENTER, "EmailSendDiscards", null ),
+    SMS_SEND_SUCCESSES( Type.INCREMENTER, "SmsSendSuccesses", null ),
+    SMS_SEND_FAILURES( Type.INCREMENTER, "SmsSendFailures", null ),
+    SMS_SEND_DISCARDS( Type.INCREMENTER, "SmsSendDiscards", null ),
+    PASSWORD_RULE_CHECKS( Type.INCREMENTER, "PasswordRuleChecks", null ),
+    HTTP_REQUESTS( Type.INCREMENTER, "HttpRequests", null ),
+    HTTP_RESOURCE_REQUESTS( Type.INCREMENTER, "HttpResourceRequests", null ),
+    HTTP_SESSIONS( Type.INCREMENTER, "HttpSessions", null ),
+    ACTIVATED_USERS( Type.INCREMENTER, "ActivatedUsers", null ),
+    NEW_USERS( Type.INCREMENTER, "NewUsers", new ConfigSettingDetail( PwmSetting.NEWUSER_ENABLE ) ),
+    GUESTS( Type.INCREMENTER, "Guests", new ConfigSettingDetail( PwmSetting.GUEST_ENABLE ) ),
+    UPDATED_GUESTS( Type.INCREMENTER, "UpdatedGuests", new ConfigSettingDetail( PwmSetting.GUEST_ENABLE ) ),
+    LOCKED_USERS( Type.INCREMENTER, "LockedUsers", null ),
+    LOCKED_ADDRESSES( Type.INCREMENTER, "LockedAddresses", null ),
+    LOCKED_USERIDS( Type.INCREMENTER, "LockedUserDNs", null ),
+    LOCKED_ATTRIBUTES( Type.INCREMENTER, "LockedAttributes", null ),
+    LOCKED_TOKENDESTS( Type.INCREMENTER, "LockedTokenDests", null ),
+    CAPTCHA_SUCCESSES( Type.INCREMENTER, "CaptchaSuccessess", null ),
+    CAPTCHA_FAILURES( Type.INCREMENTER, "CaptchaFailures", null ),
+    CAPTCHA_PRESENTATIONS( Type.INCREMENTER, "CaptchaPresentations", null ),
+    LDAP_UNAVAILABLE_COUNT( Type.INCREMENTER, "LdapUnavailableCount", null ),
+    DB_UNAVAILABLE_COUNT( Type.INCREMENTER, "DatabaseUnavailableCount", null ),
+    SETUP_RESPONSES( Type.INCREMENTER, "SetupResponses", null ),
+    SETUP_OTP_SECRET( Type.INCREMENTER, "SetupOtpSecret", null ),
+    UPDATE_ATTRIBUTES( Type.INCREMENTER, "UpdateAttributes", new ConfigSettingDetail( PwmSetting.UPDATE_PROFILE_ENABLE ) ),
+    SHORTCUTS_SELECTED( Type.INCREMENTER, "ShortcutsSelected", new ConfigSettingDetail( PwmSetting.SHORTCUT_ENABLE ) ),
+    GENERATED_PASSWORDS( Type.INCREMENTER, "GeneratedPasswords", null ),
+    RECOVERY_SUCCESSES( Type.INCREMENTER, "RecoverySuccesses", null ),
+    RECOVERY_FAILURES( Type.INCREMENTER, "RecoveryFailures", null ),
+    TOKENS_SENT( Type.INCREMENTER, "TokensSent", null ),
+    TOKENS_PASSSED( Type.INCREMENTER, "TokensPassed", null ),
+    RECOVERY_TOKENS_SENT( Type.INCREMENTER, "RecoveryTokensSent", null ),
+    RECOVERY_TOKENS_PASSED( Type.INCREMENTER, "RecoveryTokensPassed", null ),
+    RECOVERY_TOKENS_FAILED( Type.INCREMENTER, "RecoveryTokensFailed", null ),
+    RECOVERY_OTP_PASSED( Type.INCREMENTER, "RecoveryOTPPassed", null ),
+    RECOVERY_OTP_FAILED( Type.INCREMENTER, "RecoveryOTPFailed", null ),
+    PEOPLESEARCH_CACHE_HITS( Type.INCREMENTER, "PeopleSearchCacheHits", new ConfigSettingDetail( PwmSetting.PEOPLE_SEARCH_ENABLE ) ),
+    PEOPLESEARCH_CACHE_MISSES( Type.INCREMENTER, "PeopleSearchCacheMisses", new ConfigSettingDetail( PwmSetting.PEOPLE_SEARCH_ENABLE ) ),
+    PEOPLESEARCH_SEARCHES( Type.INCREMENTER, "PeopleSearchSearches", new ConfigSettingDetail( PwmSetting.PEOPLE_SEARCH_ENABLE ) ),
+    PEOPLESEARCH_DETAILS( Type.INCREMENTER, "PeopleSearchDetails", new ConfigSettingDetail( PwmSetting.PEOPLE_SEARCH_ENABLE ) ),
+    PEOPLESEARCH_ORGCHART( Type.INCREMENTER, "PeopleSearchOrgChart", new ConfigSettingDetail( PwmSetting.PEOPLE_SEARCH_ENABLE ) ),
+    PWNOTIFY_JOBS ( Type.INCREMENTER, "PwNotifyJobs", null ),
+    PWNOTIFY_JOB_ERRORS ( Type.INCREMENTER, "PwNotifyJobErrors", null ),
+    PWNOTIFY_EMAILS_SENT ( Type.INCREMENTER, "PwNotifyJobEmailsSent", null ),
+    HELPDESK_PASSWORD_SET( Type.INCREMENTER, "HelpdeskPasswordSet", null ),
+    HELPDESK_USER_LOOKUP( Type.INCREMENTER, "HelpdeskUserLookup", null ),
+    HELPDESK_TOKENS_SENT( Type.INCREMENTER, "HelpdeskTokenSent", null ),
+    HELPDESK_UNLOCK( Type.INCREMENTER, "HelpdeskUnlock", null ),
+    HELPDESK_VERIFY_OTP( Type.INCREMENTER, "HelpdeskVerifyOTP", null ),
+    REST_STATUS( Type.INCREMENTER, "RestStatus", null ),
+    REST_CHECKPASSWORD( Type.INCREMENTER, "RestCheckPassword", null ),
+    REST_SETPASSWORD( Type.INCREMENTER, "RestSetPassword", null ),
+    REST_RANDOMPASSWORD( Type.INCREMENTER, "RestRandomPassword", null ),
+    REST_PROFILE( Type.INCREMENTER, "RestProfile", null ),
+    REST_SIGNING_FORM( Type.INCREMENTER, "RestSigningForm", null ),
+    REST_CHALLENGES( Type.INCREMENTER, "RestChallenges", null ),
+    REST_HEALTH( Type.INCREMENTER, "RestHealth", null ),
+    REST_STATISTICS( Type.INCREMENTER, "RestStatistics", null ),
+    REST_VERIFYCHALLENGES( Type.INCREMENTER, "RestVerifyChallenges", null ),
+    REST_VERIFYOTP( Type.INCREMENTER, "RestVerifyOTP", null ),
+    INTRUDER_ATTEMPTS( Type.INCREMENTER, "IntruderAttempts", null ),
+    FOREIGN_SESSIONS_ACCEPTED( Type.INCREMENTER, "ForeignSessionsAccepted", null ),
+    OBSOLETE_URL_REQUESTS( Type.INCREMENTER, "ObsoleteUrlRequests", null ),
+    SYSLOG_MESSAGES_SENT( Type.INCREMENTER, "SyslogMessagesSent", null ),
 
 
     AVG_PASSWORD_SYNC_TIME( Type.AVERAGE, "AvgPasswordSyncTime", null ),
     AVG_PASSWORD_SYNC_TIME( Type.AVERAGE, "AvgPasswordSyncTime", null ),
     AVG_AUTHENTICATION_TIME( Type.AVERAGE, "AvgAuthenticationTime", null ),
     AVG_AUTHENTICATION_TIME( Type.AVERAGE, "AvgAuthenticationTime", null ),
@@ -166,7 +166,7 @@ public enum Statistic
 
 
     public enum Type
     public enum Type
     {
     {
-        INCREMENTOR,
+        INCREMENTER,
         AVERAGE,
         AVERAGE,
     }
     }
 
 

+ 2 - 2
server/src/main/java/password/pwm/svc/stats/StatisticsBundle.java

@@ -89,7 +89,7 @@ public class StatisticsBundle
 
 
     public synchronized void incrementValue( final Statistic statistic )
     public synchronized void incrementValue( final Statistic statistic )
     {
     {
-        if ( Statistic.Type.INCREMENTOR != statistic.getType() )
+        if ( Statistic.Type.INCREMENTER != statistic.getType() )
         {
         {
             LOGGER.error( "attempt to increment non-counter/incremental stat " + statistic );
             LOGGER.error( "attempt to increment non-counter/incremental stat " + statistic );
             return;
             return;
@@ -146,7 +146,7 @@ public class StatisticsBundle
     {
     {
         switch ( statistic.getType() )
         switch ( statistic.getType() )
         {
         {
-            case INCREMENTOR:
+            case INCREMENTER:
                 return valueMap.containsKey( statistic ) ? valueMap.get( statistic ) : "0";
                 return valueMap.containsKey( statistic ) ? valueMap.get( statistic ) : "0";
 
 
             case AVERAGE:
             case AVERAGE:

+ 0 - 1
server/src/main/java/password/pwm/ws/server/rest/RestProfileServer.java

@@ -23,7 +23,6 @@
 package password.pwm.ws.server.rest;
 package password.pwm.ws.server.rest;
 
 
 import com.novell.ldapchai.exception.ChaiUnavailableException;
 import com.novell.ldapchai.exception.ChaiUnavailableException;
-import jetbrains.exodus.core.dataStructures.hash.LinkedHashSet;
 import lombok.Data;
 import lombok.Data;
 import password.pwm.PwmConstants;
 import password.pwm.PwmConstants;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.PwmSetting;

+ 252 - 50
server/src/main/java/password/pwm/ws/server/rest/RestStatisticsServer.java

@@ -22,7 +22,10 @@
 
 
 package password.pwm.ws.server.rest;
 package password.pwm.ws.server.rest;
 
 
+import lombok.Builder;
 import lombok.Data;
 import lombok.Data;
+import lombok.Value;
+import password.pwm.AppProperty;
 import password.pwm.PwmConstants;
 import password.pwm.PwmConstants;
 import password.pwm.config.option.WebServiceUsage;
 import password.pwm.config.option.WebServiceUsage;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.ErrorInformation;
@@ -35,6 +38,7 @@ import password.pwm.svc.stats.EpsStatistic;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.StatisticsBundle;
 import password.pwm.svc.stats.StatisticsBundle;
 import password.pwm.svc.stats.StatisticsManager;
 import password.pwm.svc.stats.StatisticsManager;
+import password.pwm.util.java.JavaHelper;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.ws.server.RestMethodHandler;
 import password.pwm.ws.server.RestMethodHandler;
@@ -47,7 +51,15 @@ import javax.servlet.annotation.WebServlet;
 import java.io.Serializable;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.math.RoundingMode;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.TreeMap;
 
 
@@ -61,13 +73,47 @@ public class RestStatisticsServer extends RestServlet
 {
 {
     private static final PwmLogger LOGGER = PwmLogger.forClass( RestStatisticsServer.class );
     private static final PwmLogger LOGGER = PwmLogger.forClass( RestStatisticsServer.class );
 
 
-    @Data
+    private static final String FIELD_VERSION = "version";
+    private static final String FIELD_DAYS = "days";
+    private static final int MAX_DAYS = 365 * 5;
+
+    @Value
+    @Builder
     public static class JsonOutput implements Serializable
     public static class JsonOutput implements Serializable
     {
     {
-        @SuppressWarnings( "checkstyle:MemberName" )
-        public Map<String, String> EPS;
-        public Map<String, Object> nameData;
-        public Map<String, Object> keyData;
+        public List<StatLabelData> labels;
+        public List<StatValue> eventRates;
+        public List<StatValue> current;
+        public List<StatValue> cumulative;
+        public List<HistoryData> history;
+    }
+
+    @Builder
+    @Value static class HistoryData implements Serializable
+    {
+        private String name;
+        private String date;
+        private int year;
+        private int month;
+        private int day;
+        private int daysAgo;
+        private List<StatValue> data;
+    }
+
+    @Value
+    public static class StatValue implements Serializable
+    {
+        private String name;
+        private String value;
+    }
+
+    @Value
+    public static class StatLabelData implements Serializable
+    {
+        final String name;
+        final String label;
+        final String type;
+        final String description;
     }
     }
 
 
     @Override
     @Override
@@ -83,79 +129,235 @@ public class RestStatisticsServer extends RestServlet
     public RestResultBean doPwmStatisticJsonGet( final RestRequest restRequest )
     public RestResultBean doPwmStatisticJsonGet( final RestRequest restRequest )
             throws PwmUnrecoverableException
             throws PwmUnrecoverableException
     {
     {
-        final String statKey = restRequest.readParameterAsString( "statKey", PwmHttpRequestWrapper.Flag.BypassValidation );
-        final String statName = restRequest.readParameterAsString( "statName", PwmHttpRequestWrapper.Flag.BypassValidation );
-        final String days = restRequest.readParameterAsString( "days", PwmHttpRequestWrapper.Flag.BypassValidation );
+        final int defaultVersion = Integer.parseInt( restRequest.getPwmApplication().getConfig().readAppProperty( AppProperty.WS_REST_SERVER_STATISTICS_DEFAULT_VERSION ) );
+        final int version = restRequest.readParameterAsInt( FIELD_VERSION, defaultVersion );
 
 
-        try
+        switch ( version )
         {
         {
+
+            case 1:
+                return OutputVersion1.dataOutput( restRequest );
+
+            case 2:
+                return OutputVersion2.makeData( restRequest );
+
+            default:
+                JavaHelper.unhandledSwitchStatement( version );
+        }
+
+        // unreachable
+        return null;
+    }
+
+    private static class OutputVersion2
+    {
+        private static RestResultBean makeData( final RestRequest restRequest )
+                throws PwmUnrecoverableException
+        {
+            final Locale locale = restRequest.getLocale();
+            final int defaultDays = Integer.parseInt( restRequest.getPwmApplication().getConfig().readAppProperty( AppProperty.WS_REST_SERVER_STATISTICS_DEFAULT_HISTORY ) );
+            final int days = JavaHelper.rangeCheck(
+                    0,
+                    restRequest.readParameterAsInt( FIELD_DAYS, defaultDays ),
+                    MAX_DAYS
+            );
+
             final StatisticsManager statisticsManager = restRequest.getPwmApplication().getStatisticsManager();
             final StatisticsManager statisticsManager = restRequest.getPwmApplication().getStatisticsManager();
-            final JsonOutput jsonOutput = new JsonOutput();
-            jsonOutput.EPS = addEpsStats( statisticsManager );
+            final JsonOutput jsonOutput = RestStatisticsServer.JsonOutput.builder()
+                    .cumulative( makeStatInfos( statisticsManager, StatisticsManager.KEY_CUMULATIVE ) )
+                    .current( makeStatInfos( statisticsManager, StatisticsManager.KEY_CURRENT ) )
+                    .eventRates( makeEpsStatInfos( statisticsManager ) )
+                    .history( makeHistoryStatInfos( statisticsManager, days ) )
+                    .labels( makeLabels( locale ) )
+                    .build();
+            return RestResultBean.withData( jsonOutput );
+        }
 
 
-            if ( statName != null && statName.length() > 0 )
+        private static List<StatValue> makeStatInfos( final StatisticsManager statisticsManager, final String key )
+        {
+            final Map<String, StatValue> output = new TreeMap<>();
+            for ( final Statistic statistic : Statistic.values() )
             {
             {
-                jsonOutput.nameData = doNameStat( statisticsManager, statName, days );
+                final StatisticsBundle bundle = statisticsManager.getStatBundleForKey( key );
+                final String value = bundle.getStatistic( statistic );
+                final StatValue statValue = new StatValue( statistic.name(), value );
+                output.put( statistic.name(), statValue );
             }
             }
-            else
+
+            return Collections.unmodifiableList( new ArrayList<>( output.values() ) );
+        }
+
+        private static List<HistoryData> makeHistoryStatInfos(
+                final StatisticsManager statisticsManager,
+                final int days
+        )
+        {
+            final List<HistoryData> outerOutput = new ArrayList<>();
+
+            StatisticsManager.DailyKey dailyKey = new StatisticsManager.DailyKey( new Date() );
+
+            for ( int daysAgo = 0; daysAgo < days; daysAgo++ )
             {
             {
-                jsonOutput.keyData = doKeyStat( statisticsManager, statKey );
+                final Map<String, StatValue> output = new TreeMap<>();
+                for ( final Statistic statistic : Statistic.values() )
+                {
+                    final StatisticsBundle bundle = statisticsManager.getStatBundleForKey( dailyKey.toString() );
+                    final String value = bundle.getStatistic( statistic );
+                    final StatValue statValue = new StatValue( statistic.name(), value );
+                    output.put( statistic.name(), statValue );
+                }
+                final List<StatValue> statValues = Collections.unmodifiableList( new ArrayList<>( output.values() ) );
+                final HistoryData historyData = HistoryData.builder()
+                        .name( dailyKey.toString() )
+                        .date( DateTimeFormatter.ofPattern( "yyyy-MM-dd" ).withZone( ZoneOffset.UTC )
+                                .format( dailyKey.calendar().toInstant() ) )
+                        .year( dailyKey.calendar().get( Calendar.YEAR ) )
+                        .month( dailyKey.calendar().get( Calendar.MONTH ) )
+                        .day( dailyKey.calendar().get( Calendar.DAY_OF_MONTH ) )
+                        .daysAgo( daysAgo )
+                        .data( statValues )
+                        .build();
+                outerOutput.add( historyData );
+                dailyKey = dailyKey.previous();
             }
             }
 
 
-            StatisticsManager.incrementStat( restRequest.getPwmApplication(), Statistic.REST_STATISTICS );
+            return Collections.unmodifiableList( outerOutput );
+        }
+
+        private static List<StatValue> makeEpsStatInfos( final StatisticsManager statisticsManager )
+        {
+            final Map<String, StatValue> output = new TreeMap<>();
+            for ( final EpsStatistic loopEps : EpsStatistic.values() )
+            {
+                for ( final Statistic.EpsDuration loopDuration : Statistic.EpsDuration.values() )
+                {
+                    final BigDecimal loopValue = statisticsManager.readEps( loopEps, loopDuration );
+                    final BigDecimal outputValue = loopValue.setScale( 3, RoundingMode.UP );
+                    final String name = loopEps.toString() + "_" + loopDuration.toString();
+                    final StatValue statValue = new StatValue( name, outputValue.toString() );
+                    output.put( name, statValue );
+                }
+            }
 
 
-            final RestResultBean resultBean = RestResultBean.withData( jsonOutput );
-            return resultBean;
+            return Collections.unmodifiableList( new ArrayList<>( output.values() ) );
         }
         }
-        catch ( Exception e )
+
+        private static List<StatLabelData> makeLabels( final Locale locale )
         {
         {
-            final String errorMsg = "unexpected error building json response: " + e.getMessage();
-            final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_UNKNOWN, errorMsg );
-            return RestResultBean.fromError( restRequest, errorInformation );
+            final Map<String, StatLabelData> output = new TreeMap<>();
+            for ( final Statistic statistic : Statistic.values() )
+            {
+                final StatLabelData statLabelData = new StatLabelData(
+                        statistic.name(),
+                        statistic.getLabel( locale ),
+                        statistic.getType().name(),
+                        statistic.getDescription( locale ) );
+                output.put( statistic.name(), statLabelData );
+            }
+            for ( final EpsStatistic loopEps : EpsStatistic.values() )
+            {
+                for ( final Statistic.EpsDuration loopDuration : Statistic.EpsDuration.values() )
+                {
+                    final String name = loopEps.toString() + "_" + loopDuration.toString();
+                    final StatLabelData statLabelData = new StatLabelData(
+                            name,
+                            loopEps.getLabel( locale ),
+                            "EPS",
+                            null );
+                    output.put( name, statLabelData );
+                }
+            }
 
 
+            return Collections.unmodifiableList( new ArrayList<>( output.values() ) );
         }
         }
     }
     }
 
 
 
 
-    public static Map<String, Object> doNameStat( final StatisticsManager statisticsManager, final String statName, final String days )
+    public static class OutputVersion1
     {
     {
-        final Statistic statistic = Statistic.valueOf( statName );
-        final int historyDays = StringUtil.convertStrToInt( days, 30 );
+        @Data
+        public static class JsonOutput implements Serializable
+        {
+            @SuppressWarnings( "checkstyle:MemberName" )
+            public Map<String, String> EPS;
+            public Map<String, Object> nameData;
+            public Map<String, Object> keyData;
+        }
 
 
-        final Map<String, Object> results = new HashMap<>();
-        results.putAll( statisticsManager.getStatHistory( statistic, historyDays ) );
-        return results;
-    }
+        private static RestResultBean dataOutput( final RestRequest restRequest )
+                throws PwmUnrecoverableException
+        {
+            final String statKey = restRequest.readParameterAsString( "statKey", PwmHttpRequestWrapper.Flag.BypassValidation );
+            final String statName = restRequest.readParameterAsString( "statName", PwmHttpRequestWrapper.Flag.BypassValidation );
+            final String days = restRequest.readParameterAsString( "days", PwmHttpRequestWrapper.Flag.BypassValidation );
 
 
-    public static Map<String, Object> doKeyStat( final StatisticsManager statisticsManager, final String statKey )
-    {
-        final String key = ( statKey == null )
-                ? StatisticsManager.KEY_CUMULATIVE
-                : statKey;
+            try
+            {
+                final StatisticsManager statisticsManager = restRequest.getPwmApplication().getStatisticsManager();
+                final JsonOutput jsonOutput = new JsonOutput();
+                jsonOutput.EPS = addEpsStats( statisticsManager );
 
 
-        final StatisticsBundle statisticsBundle = statisticsManager.getStatBundleForKey( key );
-        final Map<String, Object> outputValueMap = new TreeMap<>();
-        for ( final Statistic stat : Statistic.values() )
-        {
-            outputValueMap.put( stat.name(), statisticsBundle.getStatistic( stat ) );
+                if ( statName != null && statName.length() > 0 )
+                {
+                    jsonOutput.nameData = doNameStat( statisticsManager, statName, days );
+                }
+                else
+                {
+                    jsonOutput.keyData = doKeyStat( statisticsManager, statKey );
+                }
+
+                StatisticsManager.incrementStat( restRequest.getPwmApplication(), Statistic.REST_STATISTICS );
+
+                final RestResultBean resultBean = RestResultBean.withData( jsonOutput );
+                return resultBean;
+            }
+            catch ( Exception e )
+            {
+                final String errorMsg = "unexpected error building json response: " + e.getMessage();
+                final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_UNKNOWN, errorMsg );
+                return RestResultBean.fromError( restRequest, errorInformation );
+            }
         }
         }
 
 
-        return outputValueMap;
-    }
+        public static Map<String, Object> doNameStat( final StatisticsManager statisticsManager, final String statName, final String days )
+        {
+            final Statistic statistic = Statistic.valueOf( statName );
+            final int historyDays = StringUtil.convertStrToInt( days, 30 );
 
 
-    public static Map<String, String> addEpsStats( final StatisticsManager statisticsManager )
-    {
-        final Map<String, String> outputMap = new TreeMap<>();
-        for ( final EpsStatistic loopEps : EpsStatistic.values() )
+            final Map<String, Object> results = new HashMap<>( statisticsManager.getStatHistory( statistic, historyDays ) );
+            return results;
+        }
+
+        public static Map<String, Object> doKeyStat( final StatisticsManager statisticsManager, final String statKey )
         {
         {
-            for ( final Statistic.EpsDuration loopDuration : Statistic.EpsDuration.values() )
+            final String key = ( statKey == null )
+                    ? StatisticsManager.KEY_CUMULATIVE
+                    : statKey;
+
+            final StatisticsBundle statisticsBundle = statisticsManager.getStatBundleForKey( key );
+            final Map<String, Object> outputValueMap = new TreeMap<>();
+            for ( final Statistic stat : Statistic.values() )
             {
             {
-                final BigDecimal loopValue = statisticsManager.readEps( loopEps, loopDuration );
-                final BigDecimal outputValue = loopValue.setScale( 3, RoundingMode.UP );
-                outputMap.put( loopEps.toString() + "_" + loopDuration.toString(), outputValue.toString() );
+                outputValueMap.put( stat.name(), statisticsBundle.getStatistic( stat ) );
             }
             }
+
+            return outputValueMap;
         }
         }
 
 
-        return outputMap;
+        public static Map<String, String> addEpsStats( final StatisticsManager statisticsManager )
+        {
+            final Map<String, String> outputMap = new TreeMap<>();
+            for ( final EpsStatistic loopEps : EpsStatistic.values() )
+            {
+                for ( final Statistic.EpsDuration loopDuration : Statistic.EpsDuration.values() )
+                {
+                    final BigDecimal loopValue = statisticsManager.readEps( loopEps, loopDuration );
+                    final BigDecimal outputValue = loopValue.setScale( 3, RoundingMode.UP );
+                    outputMap.put( loopEps.toString() + "_" + loopDuration.toString(), outputValue.toString() );
+                }
+            }
+
+            return outputMap;
+        }
     }
     }
 }
 }

+ 2 - 0
server/src/main/resources/password/pwm/AppProperty.properties

@@ -309,4 +309,6 @@ wordlist.maxCharLength=64
 wordlist.minCharLength=2
 wordlist.minCharLength=2
 ws.restClient.pwRule.haltOnError=true
 ws.restClient.pwRule.haltOnError=true
 ws.restServer.signing.form.timeoutSeconds=120
 ws.restServer.signing.form.timeoutSeconds=120
+ws.restServer.statistics.defaultHistoryDays=7
+ws.restServer.statistics.defaultVersion=2
 password.policy.allowMacroInRegexSetting=true
 password.policy.allowMacroInRegexSetting=true

File diff suppressed because it is too large
+ 430 - 430
server/src/main/webapp/public/reference/rest.jsp


Some files were not shown because too many files changed in this diff