Skip to content

Commit

Permalink
Add timers to record different entry points
Browse files Browse the repository at this point in the history
  • Loading branch information
sebr72 committed Sep 30, 2024
1 parent 36ba7c5 commit 0b40028
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 36 deletions.
141 changes: 111 additions & 30 deletions core/src/main/java/org/mapfish/print/servlet/MapPrinterServlet.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package org.mapfish.print.servlet;

import static com.codahale.metrics.MetricRegistry.name;
import static org.mapfish.print.servlet.ServletMapPrinterFactory.DEFAULT_CONFIGURATION_FILE_KEY;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import io.sentry.Sentry;
import java.io.ByteArrayOutputStream;
import java.io.File;
Expand Down Expand Up @@ -81,17 +84,25 @@ public class MapPrinterServlet extends BaseMapServlet {
/** The url path to get a sample print request. */
public static final String EXAMPLE_REQUEST_URL = "/exampleRequest.json";

private static final String BUILDREPORT = "buildreport";

/** The url path to create and get a report. */
public static final String CREATE_AND_GET_URL = "/buildreport";
public static final String CREATE_AND_GET_URL = "/" + BUILDREPORT;

private static final String STATUS = "status";

/** The url path to get the status for a print task. */
public static final String STATUS_URL = "/status";
public static final String STATUS_URL = "/" + STATUS;

private static final String CANCEL = "cancel";

/** The url path to cancel a print task. */
public static final String CANCEL_URL = "/cancel";
public static final String CANCEL_URL = "/" + CANCEL;

private static final String REPORT = "report";

/** The url path to create a print task and to get a finished print. */
public static final String REPORT_URL = "/report";
public static final String REPORT_URL = "/" + REPORT;

/** The url path to get the list of fonts available to geotools. */
public static final String FONTS_URL = "/fonts";
Expand Down Expand Up @@ -125,7 +136,7 @@ public class MapPrinterServlet extends BaseMapServlet {
* Part of the {@link #getStatus(String, String, javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)} response
*/
public static final String JSON_STATUS = "status";
public static final String JSON_STATUS = STATUS;

/**
* The elapsed time in ms from the point the job started. If the job is finished, this is the
Expand Down Expand Up @@ -218,6 +229,16 @@ public class MapPrinterServlet extends BaseMapServlet {
private final ServletInfo servletInfo;
private final MapPrinterFactory mapPrinterFactory;

private final Timer buildReportTimer;
private final Timer buildReportTimerNoAppId;
private final Timer reportTimer;
private final Timer reportTimerNoAppId;
private final Timer statusTimer;
private final Timer statusTimerNoAppId;
private final Timer cancelTimer;
private final Timer cancelTimerNoAppId;
private final Timer getReportTimer;
private final Timer getReportTimerNoAppId;
private long maxCreateAndGetWaitTimeInSeconds = ThreadPoolJobManager.DEFAULT_TIMEOUT_IN_SECONDS;

@Autowired
Expand All @@ -227,14 +248,31 @@ public MapPrinterServlet(
final MapPrinterFactory printerFactory,
final ApplicationContext context,
final ServletInfo servletInfo,
final MapPrinterFactory mapPrinterFactory) {
final MapPrinterFactory mapPrinterFactory,
final MetricRegistry metricRegistry) {
this.jobManager = jobManager;
this.reportLoaders = reportLoaders;
this.printerFactory = printerFactory;
this.context = context;
this.servletInfo = servletInfo;
this.mapPrinterFactory = mapPrinterFactory;

buildReportTimer = metricRegistry.timer(name(MapPrinterServlet.class, BUILDREPORT));
buildReportTimerNoAppId =
metricRegistry.timer(name(MapPrinterServlet.class, BUILDREPORT, "NoAppId"));
reportTimer = metricRegistry.timer(name(MapPrinterServlet.class, "generate", REPORT));
reportTimerNoAppId =
metricRegistry.timer(name(MapPrinterServlet.class, "generate", REPORT, "NoAppId"));
statusTimer = metricRegistry.timer(name(MapPrinterServlet.class, STATUS, "report"));
statusTimerNoAppId =
metricRegistry.timer(name(MapPrinterServlet.class, STATUS, "report", "NoAppId"));
cancelTimer = metricRegistry.timer(name(MapPrinterServlet.class, CANCEL, "report"));
cancelTimerNoAppId =
metricRegistry.timer(name(MapPrinterServlet.class, CANCEL, "report", "NoAppId"));
getReportTimer = metricRegistry.timer(name(MapPrinterServlet.class, "download", REPORT));
getReportTimerNoAppId =
metricRegistry.timer(name(MapPrinterServlet.class, "download", REPORT, "NoAppId"));

boolean enableSentry = System.getProperties().contains("sentry.dsn");
enableSentry |= System.getenv().containsKey("SENTRY_URL");
enableSentry |= System.getenv().containsKey("SENTRY_DSN");
Expand Down Expand Up @@ -352,7 +390,9 @@ public final void getStatusSpecificAppId(
@Nonnull @PathVariable final String referenceId,
final HttpServletRequest statusRequest,
final HttpServletResponse statusResponse) {
getStatus(appId, referenceId, statusRequest, statusResponse);
try (final Timer.Context ignored = statusTimer.time()) {
getStatus(appId, referenceId, statusRequest, statusResponse);
}
}

/**
Expand All @@ -371,7 +411,9 @@ public final void getStatusPath(
@Nonnull @PathVariable final String referenceId,
final HttpServletRequest statusRequest,
final HttpServletResponse statusResponse) {
getStatus("default", referenceId, statusRequest, statusResponse);
try (final Timer.Context ignored = statusTimerNoAppId.time()) {
getStatus("default", referenceId, statusRequest, statusResponse);
}
}

/**
Expand All @@ -386,7 +428,7 @@ public final void getStatusPath(
* @param statusRequest the request object
* @param statusResponse the response object
*/
public final void getStatus(
private void getStatus(
@Nonnull final String applicationId,
@Nonnull final String referenceId,
final HttpServletRequest statusRequest,
Expand Down Expand Up @@ -438,7 +480,9 @@ public final void cancelSpecificAppId(
@Nonnull @PathVariable final String appId,
@Nonnull @PathVariable final String referenceId,
final HttpServletResponse statusResponse) {
cancel(appId, referenceId, statusResponse);
try (final Timer.Context ignored = cancelTimer.time()) {
cancel(appId, referenceId, statusResponse);
}
}

/**
Expand All @@ -453,7 +497,9 @@ public final void cancelSpecificAppId(
@RequestMapping(value = CANCEL_URL + "/{referenceId:\\S+}", method = RequestMethod.DELETE)
public final void cancelPath(
@Nonnull @PathVariable final String referenceId, final HttpServletResponse statusResponse) {
cancel("default", referenceId, statusResponse);
try (final Timer.Context ignored = cancelTimerNoAppId.time()) {
cancel("default", referenceId, statusResponse);
}
}

/**
Expand All @@ -466,7 +512,7 @@ public final void cancelPath(
* @param referenceId the job reference
* @param statusResponse the response object
*/
public final void cancel(
private void cancel(
@Nonnull final String applicationId,
@Nonnull final String referenceId,
final HttpServletResponse statusResponse) {
Expand Down Expand Up @@ -498,7 +544,19 @@ public final void createReport(
final HttpServletRequest createReportRequest,
final HttpServletResponse createReportResponse)
throws NoSuchAppException {
setNoCache(createReportResponse);
try (final Timer.Context ignored = reportTimer.time()) {
setNoCache(createReportResponse);
doCreateReport(appId, format, requestData, createReportRequest, createReportResponse);
}
}

private void doCreateReport(
String appId,
String format,
String requestData,
HttpServletRequest createReportRequest,
HttpServletResponse createReportResponse)
throws NoSuchAppException {
String ref =
createAndSubmitPrintJob(
appId, format, requestData, createReportRequest, createReportResponse);
Expand Down Expand Up @@ -540,7 +598,9 @@ public final void getReportSpecificAppId(
@RequestParam(value = "inline", defaultValue = "false") final boolean inline,
final HttpServletResponse getReportResponse)
throws IOException, ServletException {
getReport(appId, referenceId, inline, getReportResponse);
try (final Timer.Context ignored = getReportTimer.time()) {
getReport(appId, referenceId, inline, getReportResponse);
}
}

/**
Expand All @@ -556,7 +616,9 @@ public final void getReportPath(
@RequestParam(value = "inline", defaultValue = "false") final boolean inline,
final HttpServletResponse getReportResponse)
throws IOException, ServletException {
getReport("default", referenceId, inline, getReportResponse);
try (final Timer.Context ignored = getReportTimerNoAppId.time()) {
getReport("default", referenceId, inline, getReportResponse);
}
}

/**
Expand All @@ -567,7 +629,7 @@ public final void getReportPath(
* @param inline whether to inline the
* @param getReportResponse the response object
*/
public final void getReport(
private void getReport(
@Nonnull final String applicationId,
@Nonnull final String referenceId,
final boolean inline,
Expand Down Expand Up @@ -595,16 +657,25 @@ public final void createReport(
final HttpServletRequest createReportRequest,
final HttpServletResponse createReportResponse)
throws NoSuchAppException {
setNoCache(createReportResponse);
try (final Timer.Context ignored = reportTimerNoAppId.time()) {
setNoCache(createReportResponse);
final String appId = getAppId(requestData, createReportResponse);
if (appId == null) return;
doCreateReport(appId, format, requestData, createReportRequest, createReportResponse);
}
}

private static String getAppId(String requestData, HttpServletResponse createReportResponse)
throws NoSuchAppException {
PJsonObject spec = parseJson(requestData, createReportResponse);
if (spec == null) {
return;
return null;
}
final String appId = spec.optString(JSON_APP, DEFAULT_CONFIGURATION_FILE_KEY);
if (appId == null) {
throw new NoSuchAppException("No app specified");
}
createReport(appId, format, requestData, createReportRequest, createReportResponse);
return appId;
}

/**
Expand All @@ -629,8 +700,22 @@ public final void createReportAndGet(
final HttpServletRequest createReportRequest,
final HttpServletResponse createReportResponse)
throws IOException, ServletException, InterruptedException, NoSuchAppException {
setNoCache(createReportResponse);

try (final Timer.Context ignored = buildReportTimer.time()) {
setNoCache(createReportResponse);
doCreateReportAndGet(
appId, format, requestData, inline, createReportRequest, createReportResponse);
}
}

private void doCreateReportAndGet(
String appId,
String format,
String requestData,
boolean inline,
HttpServletRequest createReportRequest,
HttpServletResponse createReportResponse)
throws NoSuchAppException, InterruptedException, IOException, ServletException {
String ref =
createAndSubmitPrintJob(
appId, format, requestData, createReportRequest, createReportResponse);
Expand Down Expand Up @@ -668,17 +753,13 @@ public final void createReportAndGetNoAppId(
final HttpServletRequest createReportRequest,
final HttpServletResponse createReportResponse)
throws IOException, ServletException, InterruptedException, NoSuchAppException {
setNoCache(createReportResponse);
PJsonObject spec = parseJson(requestData, createReportResponse);
if (spec == null) {
return;
}
String appId = spec.optString(JSON_APP, DEFAULT_CONFIGURATION_FILE_KEY);
if (appId == null) {
throw new NoSuchAppException("No app specified");
try (final Timer.Context ignored = buildReportTimerNoAppId.time()) {
setNoCache(createReportResponse);
final String appId = getAppId(requestData, createReportResponse);
if (appId == null) return;
doCreateReportAndGet(
appId, format, requestData, inline, createReportRequest, createReportResponse);
}
createReportAndGet(
appId, format, requestData, inline, createReportRequest, createReportResponse);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.net.URISyntaxException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Objects;
import org.json.JSONObject;
import org.junit.After;
import org.junit.Test;
Expand Down Expand Up @@ -104,7 +105,7 @@ public void testCreateReportAndGet_RequestAllowed_OtherGetDenied() throws Except
while (!done) {
MockHttpServletRequest servletStatusRequest = new MockHttpServletRequest("GET", statusURL);
MockHttpServletResponse servletStatusResponse = new MockHttpServletResponse();
servlet.getStatus("test", ref, servletStatusRequest, servletStatusResponse);
servlet.getStatusSpecificAppId("test", ref, servletStatusRequest, servletStatusResponse);

String contentAsString = servletStatusResponse.getContentAsString();

Expand All @@ -120,7 +121,7 @@ public void testCreateReportAndGet_RequestAllowed_OtherGetDenied() throws Except
try {
AccessAssertionTestUtil.setCreds("ROLE_USER");
final MockHttpServletResponse getResponse1 = new MockHttpServletResponse();
this.servlet.getReport("test", ref, false, getResponse1);
this.servlet.getReportSpecificAppId("test", ref, false, getResponse1);
fail("Expected an AccessDeniedException");
} catch (AccessDeniedException e) {
// good
Expand All @@ -129,15 +130,15 @@ public void testCreateReportAndGet_RequestAllowed_OtherGetDenied() throws Except

try {
final MockHttpServletResponse getResponse2 = new MockHttpServletResponse();
this.servlet.getReport("test", ref, false, getResponse2);
this.servlet.getReportSpecificAppId("test", ref, false, getResponse2);
assertEquals(HttpStatus.UNAUTHORIZED.value(), servletCreateResponse.getStatus());
fail("Expected an AuthenticationCredentialsNotFoundException");
} catch (AuthenticationCredentialsNotFoundException e) {
// good
}
}

private byte[] assertCorrectResponse(MockHttpServletResponse servletGetReportResponse)
private void assertCorrectResponse(MockHttpServletResponse servletGetReportResponse)
throws IOException {
byte[] report;
report = servletGetReportResponse.getContentAsByteArray();
Expand All @@ -146,12 +147,13 @@ private byte[] assertCorrectResponse(MockHttpServletResponse servletGetReportRes
assertEquals("image/png", contentType);
final Calendar instance = Calendar.getInstance();
int year = instance.get(Calendar.YEAR);
String fileName = servletGetReportResponse.getHeader("Content-disposition").split("=")[1];
String fileName =
Objects.requireNonNull(servletGetReportResponse.getHeader("Content-disposition"))
.split("=")[1];
assertEquals("test_report-" + year + ".png", fileName);

new ImageSimilarity(getFile(MapPrinterServletSecurityTest.class, "expectedSimpleImage.png"))
.assertSimilarity(report, 0);
return report;
}

private void setUpConfigFiles() throws URISyntaxException {
Expand Down

0 comments on commit 0b40028

Please sign in to comment.