This is an automated email from the ASF dual-hosted git repository.

angela pushed a commit to branch SLING-10164
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-core.git

commit ae4225da79e0b0549fec9dd59fb4e868b2acf784
Author: angela <[email protected]>
AuthorDate: Tue Mar 2 11:18:22 2021 +0100

    SLING-10164 : Add basic metrics to SlingAuthenticator (initial proposal 
with minimal testing)
---
 pom.xml                                            | 17 +++++
 .../auth/core/impl/SlingAuthenticationMetrics.java | 48 ++++++++++++
 .../sling/auth/core/impl/SlingAuthenticator.java   | 21 ++++-
 .../core/impl/SlingAuthenticationMetricsTest.java  | 75 ++++++++++++++++++
 .../auth/core/impl/SlingAuthenticatorOsgiTest.java | 89 ++++++++++++++++++++++
 5 files changed, 248 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index fb78d39..081fb04 100644
--- a/pom.xml
+++ b/pom.xml
@@ -124,6 +124,17 @@
             <version>1.4</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.metrics</artifactId>
+            <version>1.2.8</version>
+        </dependency>
+      <dependency>
+          <groupId>org.jetbrains</groupId>
+          <artifactId>annotations</artifactId>
+          <version>18.0.0</version>
+          <scope>provided</scope>
+      </dependency>
 
         <!-- Test Dependencies -->
         <dependency>
@@ -152,5 +163,11 @@
             <version>15.0</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.osgi-mock</artifactId>
+            <version>3.0.0</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git 
a/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticationMetrics.java 
b/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticationMetrics.java
new file mode 100644
index 0000000..6edbc4f
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticationMetrics.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.auth.core.impl;
+
+import org.apache.sling.commons.metrics.Meter;
+import org.apache.sling.commons.metrics.MetricsService;
+import org.apache.sling.commons.metrics.Timer;
+import org.jetbrains.annotations.NotNull;
+
+class SlingAuthenticationMetrics {
+
+    private final Timer authenticateTimer;
+    private final Meter authenticateSuccess;
+    private final Meter authenticateFailed;
+
+    SlingAuthenticationMetrics(@NotNull MetricsService metricsService) {
+        authenticateTimer = 
metricsService.timer("sling.auth.core.authenticate.timer");
+        authenticateSuccess = 
metricsService.meter("sling.auth.core.authenticate.success");
+        authenticateFailed = 
metricsService.meter("sling.auth.core.authenticate.failed");
+    }
+
+    @NotNull
+    Timer.Context authenticationTimerContext() {
+        return authenticateTimer.time();
+    }
+
+    void authenticateCompleted(boolean failed) {
+        if (failed) {
+            authenticateFailed.mark();
+        } else {
+            authenticateSuccess.mark();
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java 
b/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java
index 6e203cc..6877ea4 100644
--- a/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java
+++ b/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java
@@ -60,6 +60,8 @@ import org.apache.sling.auth.core.spi.AuthenticationHandler;
 import org.apache.sling.auth.core.spi.AuthenticationInfo;
 import org.apache.sling.auth.core.spi.AuthenticationInfoPostProcessor;
 import org.apache.sling.auth.core.spi.DefaultAuthenticationFeedbackHandler;
+import org.apache.sling.commons.metrics.MetricsService;
+import org.apache.sling.commons.metrics.Timer;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
@@ -333,6 +335,10 @@ public class SlingAuthenticator implements Authenticator,
     @Reference(policy=ReferencePolicy.DYNAMIC, cardinality = 
ReferenceCardinality.OPTIONAL)
     private volatile EventAdmin eventAdmin;
 
+    @Reference
+    private MetricsService metricsService;
+    private SlingAuthenticationMetrics metrics;
+
     // ---------- SCR integration
 
     @Activate
@@ -363,6 +369,8 @@ public class SlingAuthenticator implements Authenticator,
             bundleContext, authHandlerCache);
         authInfoPostProcessorTracker = new ServiceTracker(bundleContext, 
AuthenticationInfoPostProcessor.class, null);
         authInfoPostProcessorTracker.open();
+
+        metrics = new SlingAuthenticationMetrics(metricsService);
     }
 
     @Modified
@@ -457,6 +465,13 @@ public class SlingAuthenticator implements Authenticator,
             webConsolePlugin.unregister();
             webConsolePlugin = null;
         }
+
+        if (metricsService != null) {
+            metricsService = null;
+        }
+        if (metrics != null) {
+            metrics = null;
+        }
     }
 
     // --------- AuthenticationSupport interface
@@ -492,15 +507,17 @@ public class SlingAuthenticator implements Authenticator,
             request.removeAttribute(REQUEST_ATTRIBUTE_RESOLVER);
         }
 
+        Timer.Context ctx = metrics.authenticationTimerContext();
         boolean process = doHandleSecurity(request, response);
         if (process && expectAuthenticationHandler(request)) {
             log.warn("handleSecurity: AuthenticationHandler did not block 
request; access denied");
             request.removeAttribute(AuthenticationHandler.FAILURE_REASON);
             request.removeAttribute(AuthenticationHandler.FAILURE_REASON_CODE);
             AuthUtil.sendInvalid(request, response);
-            return false;
+            process = false;
         }
-
+        ctx.stop();
+        metrics.authenticateCompleted(process);
         return process;
     }
 
diff --git 
a/src/test/java/org/apache/sling/auth/core/impl/SlingAuthenticationMetricsTest.java
 
b/src/test/java/org/apache/sling/auth/core/impl/SlingAuthenticationMetricsTest.java
new file mode 100644
index 0000000..50b0f51
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/auth/core/impl/SlingAuthenticationMetricsTest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.auth.core.impl;
+
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.commons.metrics.Meter;
+import org.apache.sling.commons.metrics.MetricsService;
+import org.apache.sling.commons.metrics.Timer;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertSame;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+public class SlingAuthenticationMetricsTest {
+
+    private Meter meter = mock(Meter.class);
+    private Timer.Context ctx = mock(Timer.Context.class);
+    private Timer timer = mock(Timer.class);
+    private final MetricsService metricsService = mock(MetricsService.class);
+
+    private SlingAuthenticationMetrics metrics;
+
+    @Before
+    public void before() {
+        when(timer.time()).thenReturn(ctx);
+        when(metricsService.meter(anyString())).thenReturn(meter);
+        when(metricsService.timer(anyString())).thenReturn(timer);
+
+        metrics = new SlingAuthenticationMetrics(metricsService);
+
+        verify(metricsService).timer(anyString());
+        verify(metricsService, times(2)).meter(anyString());
+    }
+
+    @Test
+    public void testAuthenticationCompleted() {
+        metrics.authenticateCompleted(true);
+        metrics.authenticateCompleted(false);
+        verify(meter, times(2)).mark();
+        verifyNoMoreInteractions(meter);
+        verifyNoInteractions(timer, ctx);
+    }
+
+    @Test
+    public void testAuthenticationTimerContext() {
+        Timer.Context timerContext = metrics.authenticationTimerContext();
+        timerContext.stop();
+
+        verify(timer).time();
+        verify(ctx).stop();
+        verifyNoMoreInteractions(timer, ctx);
+        verifyNoInteractions(meter);
+    }
+}
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/auth/core/impl/SlingAuthenticatorOsgiTest.java 
b/src/test/java/org/apache/sling/auth/core/impl/SlingAuthenticatorOsgiTest.java
new file mode 100644
index 0000000..1a5d4fe
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/auth/core/impl/SlingAuthenticatorOsgiTest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.auth.core.impl;
+
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.auth.core.spi.AuthenticationInfo;
+import org.apache.sling.commons.metrics.Meter;
+import org.apache.sling.commons.metrics.MetricsService;
+import org.apache.sling.commons.metrics.Timer;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+public class SlingAuthenticatorOsgiTest {
+
+    @Rule
+    public final OsgiContext context = new OsgiContext();
+
+    private Meter meter = mock(Meter.class);
+    private Timer.Context ctx = mock(Timer.Context.class);
+    private Timer timer = mock(Timer.class);
+    private final MetricsService metricsService = mock(MetricsService.class);
+
+    private final SlingAuthenticator authenticator = new SlingAuthenticator();
+
+    @Before
+    public void before() throws Exception {
+        ResourceResolver rr = mock(ResourceResolver.class);
+        ResourceResolverFactory resourceResolverFactory = 
mock(ResourceResolverFactory.class);
+        
when(resourceResolverFactory.getResourceResolver(any(AuthenticationInfo.class))).thenReturn(rr);
+
+        when(timer.time()).thenReturn(ctx);
+        when(metricsService.meter(anyString())).thenReturn(meter);
+        when(metricsService.timer(anyString())).thenReturn(timer);
+
+        context.registerService(ResourceResolverFactory.class, 
resourceResolverFactory);
+        context.registerService(MetricsService.class, metricsService);
+        context.registerInjectActivateService(authenticator);
+    }
+
+    @Test
+    public void testHandleSecurity() {
+        HttpServletRequest req = mock(HttpServletRequest.class);
+        when(req.getServletPath()).thenReturn("/");
+        when(req.getServerName()).thenReturn("localhost");
+        when(req.getServerPort()).thenReturn(80);
+        when(req.getScheme()).thenReturn("http");
+        when(req.getRequestURI()).thenReturn("http://localhost:80/";);
+
+        HttpServletResponse resp = mock(HttpServletResponse.class);
+        authenticator.handleSecurity(req, resp);
+
+        verify(timer).time();
+        verify(ctx).stop();
+        verify(meter).mark();
+        verifyNoMoreInteractions(timer, meter, ctx);
+    }
+
+}
\ No newline at end of file

Reply via email to