diff options
8 files changed, 43 insertions, 9 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/JettyHttpServer.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/JettyHttpServer.java index 8c31eabfde0..d84884665ef 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/JettyHttpServer.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/JettyHttpServer.java @@ -23,6 +23,7 @@ public class JettyHttpServer extends SimpleComponent implements ServerConfig.Pro private final ContainerCluster<?> cluster; private volatile boolean isHostedVespa; private final List<ConnectorFactory> connectorFactories = new ArrayList<>(); + private final List<String> ignoredUserAgentsList = new ArrayList<>(); public JettyHttpServer(String componentId, ContainerCluster<?> cluster, boolean isHostedVespa) { super(new ComponentModel(componentId, com.yahoo.jdisc.http.server.jetty.JettyHttpServer.class.getName(), null)); @@ -44,10 +45,15 @@ public class JettyHttpServer extends SimpleComponent implements ServerConfig.Pro return Collections.unmodifiableList(connectorFactories); } + public void addIgnoredUserAgent(String userAgent) { + ignoredUserAgentsList.add(userAgent); + } + @Override public void getConfig(ServerConfig.Builder builder) { builder.metric(new ServerConfig.Metric.Builder() .monitoringHandlerPaths(List.of("/state/v1", "/status.html", "/metrics/v2")) + .ignoredUserAgents(ignoredUserAgentsList) .searchHandlerPaths(List.of("/search")) ); if (isHostedVespa) { diff --git a/container-core/abi-spec.json b/container-core/abi-spec.json index a6783d1e5f5..c3c946ab537 100644 --- a/container-core/abi-spec.json +++ b/container-core/abi-spec.json @@ -1990,11 +1990,14 @@ "public com.yahoo.jdisc.http.ServerConfig$Metric$Builder monitoringHandlerPaths(java.util.Collection)", "public com.yahoo.jdisc.http.ServerConfig$Metric$Builder searchHandlerPaths(java.lang.String)", "public com.yahoo.jdisc.http.ServerConfig$Metric$Builder searchHandlerPaths(java.util.Collection)", + "public com.yahoo.jdisc.http.ServerConfig$Metric$Builder ignoredUserAgents(java.lang.String)", + "public com.yahoo.jdisc.http.ServerConfig$Metric$Builder ignoredUserAgents(java.util.Collection)", "public com.yahoo.jdisc.http.ServerConfig$Metric build()" ], "fields": [ "public java.util.List monitoringHandlerPaths", - "public java.util.List searchHandlerPaths" + "public java.util.List searchHandlerPaths", + "public java.util.List ignoredUserAgents" ] }, "com.yahoo.jdisc.http.ServerConfig$Metric": { @@ -2009,7 +2012,9 @@ "public java.util.List monitoringHandlerPaths()", "public java.lang.String monitoringHandlerPaths(int)", "public java.util.List searchHandlerPaths()", - "public java.lang.String searchHandlerPaths(int)" + "public java.lang.String searchHandlerPaths(int)", + "public java.util.List ignoredUserAgents()", + "public java.lang.String ignoredUserAgents(int)" ], "fields": [] }, diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpResponseStatisticsCollector.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpResponseStatisticsCollector.java index 0aa2820f959..631f4080c7e 100644 --- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpResponseStatisticsCollector.java +++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpResponseStatisticsCollector.java @@ -3,6 +3,7 @@ package com.yahoo.jdisc.http.server.jetty; import com.yahoo.jdisc.Metric; import com.yahoo.jdisc.http.HttpRequest; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.AsyncContextEvent; import org.eclipse.jetty.server.Handler; @@ -21,6 +22,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -106,12 +108,25 @@ class HttpResponseStatisticsCollector extends HandlerWrapper implements Graceful } } - private void observeEndOfRequest(Request request, HttpServletResponse flushableResponse) throws IOException { - var metrics = StatusCodeMetric.of(request, monitoringHandlerPaths, searchHandlerPaths); - metrics.forEach(metric -> - statistics.computeIfAbsent(metric, __ -> new LongAdder()) - .increment()); + void ignoreUserAgent(String agentName) { + ignoredUserAgents.add(agentName); + } + private Set<String> ignoredUserAgents = new HashSet<>(); + + private boolean shouldLogMetricsFor(Request request) { + String agent = request.getHeader(HttpHeader.USER_AGENT.toString()); + if (agent == null) return true; + return ! ignoredUserAgents.contains(agent); + } + + private void observeEndOfRequest(Request request, HttpServletResponse flushableResponse) throws IOException { + if (shouldLogMetricsFor(request)) { + var metrics = StatusCodeMetric.of(request, monitoringHandlerPaths, searchHandlerPaths); + metrics.forEach(metric -> + statistics.computeIfAbsent(metric, __ -> new LongAdder()) + .increment()); + } long live = inFlight.decrementAndGet(); FutureCallback shutdownCb = shutdown.get(); if (shutdownCb != null) { diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java index fca34f3bbd7..006d6cc84da 100644 --- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java +++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java @@ -159,6 +159,9 @@ public class JettyHttpServer extends AbstractServerProvider { new HttpResponseStatisticsCollector(serverConfig.metric().monitoringHandlerPaths(), serverConfig.metric().searchHandlerPaths()); statisticsCollector.setHandler(gzipHandler); + for (String agent : serverConfig.metric().ignoredUserAgents()) { + statisticsCollector.ignoreUserAgent(agent); + } StatisticsHandler statisticsHandler = newStatisticsHandler(); statisticsHandler.setHandler(statisticsCollector); diff --git a/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.server.def b/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.server.def index db7322c76f2..7e1404bbc5e 100644 --- a/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.server.def +++ b/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.server.def @@ -57,6 +57,9 @@ metric.monitoringHandlerPaths[] string # Paths that should be reported with search dimensions where applicable metric.searchHandlerPaths[] string +# User-agent names to ignore wrt statistics (crawlers etc) +metric.ignoredUserAgents[] string + # HTTP request headers that contain remote address accessLog.remoteAddressHeaders[] string diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterNodesTimeseries.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterNodesTimeseries.java index 5ad4ef2e263..dd35eb7b54d 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterNodesTimeseries.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterNodesTimeseries.java @@ -31,7 +31,7 @@ public class ClusterNodesTimeseries { // If none can be detected we assume the node is new/was down. // If either this is the case, or there is a generation change, we ignore // the first warmupWindow metrics - var timeseries = db.getNodeTimeseries(period.plus(warmupDuration.multipliedBy(4)), clusterNodes); + var timeseries = db.getNodeTimeseries(period.plus(warmupDuration.multipliedBy(8)), clusterNodes); if (cluster.lastScalingEvent().isPresent()) { long currentGeneration = cluster.lastScalingEvent().get().generation(); timeseries = keepCurrentGenerationAfterWarmup(timeseries, currentGeneration); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/NodeTimeseries.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/NodeTimeseries.java index 4a5f8972e11..c58b08cb3b5 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/NodeTimeseries.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/NodeTimeseries.java @@ -85,7 +85,7 @@ public class NodeTimeseries { if (snapshot.generation() < 0) return true; // Content nodes do not yet send generation if (snapshot.generation() < currentGeneration) return false; if (generationChange.isEmpty()) return true; - return ! snapshot.at().isBefore(generationChange.get().plus(warmupDuration)); + return ! snapshot.at().isBefore(generationChange.get().plus(warmupDuration.multipliedBy(2))); } } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java index d9037181f59..9052ee30506 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java @@ -211,6 +211,7 @@ public class AutoscalingMaintainerTest { tester.deploy(app1, cluster1, capacity); // fast completion tester.addMeasurements(1.0f, 0.3f, 0.3f, 0, 1, app1); + tester.clock().advance(Duration.ofSeconds(150)); tester.addMeasurements(1.0f, 0.3f, 0.3f, 0, 1, app1); tester.maintainer().maintain(); assertEquals("Scale up: " + tester.cluster(app1, cluster1).autoscalingStatus(), @@ -219,6 +220,7 @@ public class AutoscalingMaintainerTest { // fast completion, with initially overloaded cpu tester.addMeasurements(3.0f, 0.3f, 0.3f, 1, 1, app1); + tester.clock().advance(Duration.ofSeconds(150)); tester.addMeasurements(0.2f, 0.3f, 0.3f, 1, 1, app1); tester.maintainer().maintain(); assertEquals("No autoscaling since we ignore the (first) data point in the warup period", |