From 23b348040e21a4ede72c94862131d773f1b2b7c9 Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Fri, 7 Aug 2015 14:48:49 -0400 Subject: [PATCH] Add script compilation stats This commit adds basic support to track the number of times scripts are compiled and compiled scripts are evicted from the script cache. These statistics are tracked at the node level. Closes #12673 --- .../admin/cluster/node/stats/NodeStats.java | 18 +++- .../cluster/node/stats/NodesStatsRequest.java | 14 ++++ .../node/stats/NodesStatsRequestBuilder.java | 5 ++ .../node/stats/TransportNodesStatsAction.java | 2 +- .../stats/TransportClusterStatsAction.java | 2 +- .../node/service/NodeService.java | 21 ++++- .../node/stats/RestNodesStatsAction.java | 1 + .../rest/action/cat/RestNodesAction.java | 10 ++- .../elasticsearch/script/ScriptMetrics.java | 39 +++++++++ .../elasticsearch/script/ScriptService.java | 12 ++- .../org/elasticsearch/script/ScriptStats.java | 82 +++++++++++++++++++ .../allocation/decider/MockDiskUsagesIT.java | 3 +- .../script/ScriptServiceTests.java | 67 +++++++++++++++ .../test/InternalTestCluster.java | 2 +- docs/reference/cat/nodes.asciidoc | 2 + 15 files changed, 269 insertions(+), 11 deletions(-) create mode 100644 core/src/main/java/org/elasticsearch/script/ScriptMetrics.java create mode 100644 core/src/main/java/org/elasticsearch/script/ScriptStats.java diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodeStats.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodeStats.java index ea8c3bc106f..c437a4455b6 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodeStats.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodeStats.java @@ -33,6 +33,7 @@ import org.elasticsearch.monitor.fs.FsInfo; import org.elasticsearch.monitor.jvm.JvmStats; import org.elasticsearch.monitor.os.OsStats; import org.elasticsearch.monitor.process.ProcessStats; +import org.elasticsearch.script.ScriptStats; import org.elasticsearch.threadpool.ThreadPoolStats; import org.elasticsearch.transport.TransportStats; @@ -73,13 +74,17 @@ public class NodeStats extends BaseNodeResponse implements ToXContent { @Nullable private AllCircuitBreakerStats breaker; + @Nullable + private ScriptStats scriptStats; + NodeStats() { } public NodeStats(DiscoveryNode node, long timestamp, @Nullable NodeIndicesStats indices, @Nullable OsStats os, @Nullable ProcessStats process, @Nullable JvmStats jvm, @Nullable ThreadPoolStats threadPool, @Nullable FsInfo fs, @Nullable TransportStats transport, @Nullable HttpStats http, - @Nullable AllCircuitBreakerStats breaker) { + @Nullable AllCircuitBreakerStats breaker, + @Nullable ScriptStats scriptStats) { super(node); this.timestamp = timestamp; this.indices = indices; @@ -91,6 +96,7 @@ public class NodeStats extends BaseNodeResponse implements ToXContent { this.transport = transport; this.http = http; this.breaker = breaker; + this.scriptStats = scriptStats; } public long getTimestamp() { @@ -165,6 +171,11 @@ public class NodeStats extends BaseNodeResponse implements ToXContent { return this.breaker; } + @Nullable + public ScriptStats getScriptStats() { + return this.scriptStats; + } + public static NodeStats readNodeStats(StreamInput in) throws IOException { NodeStats nodeInfo = new NodeStats(); nodeInfo.readFrom(in); @@ -200,6 +211,7 @@ public class NodeStats extends BaseNodeResponse implements ToXContent { http = HttpStats.readHttpStats(in); } breaker = AllCircuitBreakerStats.readOptionalAllCircuitBreakerStats(in); + scriptStats = in.readOptionalStreamable(new ScriptStats()); } @@ -256,6 +268,7 @@ public class NodeStats extends BaseNodeResponse implements ToXContent { http.writeTo(out); } out.writeOptionalStreamable(breaker); + out.writeOptionalStreamable(scriptStats); } @Override @@ -303,6 +316,9 @@ public class NodeStats extends BaseNodeResponse implements ToXContent { if (getBreaker() != null) { getBreaker().toXContent(builder, params); } + if (getScriptStats() != null) { + getScriptStats().toXContent(builder, params); + } return builder; } diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java index 4fa654e7259..bd4f08fc6cd 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java @@ -41,6 +41,7 @@ public class NodesStatsRequest extends BaseNodesRequest { private boolean transport; private boolean http; private boolean breaker; + private boolean script; protected NodesStatsRequest() { } @@ -67,6 +68,7 @@ public class NodesStatsRequest extends BaseNodesRequest { this.transport = true; this.http = true; this.breaker = true; + this.script = true; return this; } @@ -84,6 +86,7 @@ public class NodesStatsRequest extends BaseNodesRequest { this.transport = false; this.http = false; this.breaker = false; + this.script = false; return this; } @@ -240,6 +243,15 @@ public class NodesStatsRequest extends BaseNodesRequest { return this; } + public boolean script() { + return script; + } + + public NodesStatsRequest script(boolean script) { + this.script = script; + return this; + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); @@ -253,6 +265,7 @@ public class NodesStatsRequest extends BaseNodesRequest { transport = in.readBoolean(); http = in.readBoolean(); breaker = in.readBoolean(); + script = in.readBoolean(); } @Override @@ -268,6 +281,7 @@ public class NodesStatsRequest extends BaseNodesRequest { out.writeBoolean(transport); out.writeBoolean(http); out.writeBoolean(breaker); + out.writeBoolean(script); } } diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequestBuilder.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequestBuilder.java index 992505ef16a..db8d774b39d 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequestBuilder.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequestBuilder.java @@ -62,6 +62,11 @@ public class NodesStatsRequestBuilder extends NodesOperationRequestBuilder shardsStats = new ArrayList<>(); for (IndexService indexService : indicesService) { for (IndexShard indexShard : indexService) { diff --git a/core/src/main/java/org/elasticsearch/node/service/NodeService.java b/core/src/main/java/org/elasticsearch/node/service/NodeService.java index e50fd3e7ee2..5be6bf11e56 100644 --- a/core/src/main/java/org/elasticsearch/node/service/NodeService.java +++ b/core/src/main/java/org/elasticsearch/node/service/NodeService.java @@ -36,6 +36,7 @@ import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.breaker.CircuitBreakerService; import org.elasticsearch.monitor.MonitorService; import org.elasticsearch.plugins.PluginsService; +import org.elasticsearch.script.ScriptService; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; @@ -51,6 +52,8 @@ public class NodeService extends AbstractComponent { private final IndicesService indicesService; private final PluginsService pluginService; private final CircuitBreakerService circuitBreakerService; + private ScriptService scriptService; + @Nullable private HttpServer httpServer; @@ -63,7 +66,8 @@ public class NodeService extends AbstractComponent { @Inject public NodeService(Settings settings, ThreadPool threadPool, MonitorService monitorService, Discovery discovery, TransportService transportService, IndicesService indicesService, - PluginsService pluginService, CircuitBreakerService circuitBreakerService, Version version) { + PluginsService pluginService, CircuitBreakerService circuitBreakerService, + Version version) { super(settings); this.threadPool = threadPool; this.monitorService = monitorService; @@ -76,6 +80,12 @@ public class NodeService extends AbstractComponent { this.circuitBreakerService = circuitBreakerService; } + // can not use constructor injection or there will be a circular dependency + @Inject(optional = true) + public void setScriptService(ScriptService scriptService) { + this.scriptService = scriptService; + } + public void setHttpServer(@Nullable HttpServer httpServer) { this.httpServer = httpServer; } @@ -134,12 +144,14 @@ public class NodeService extends AbstractComponent { monitorService.fsService().stats(), transportService.stats(), httpServer == null ? null : httpServer.stats(), - circuitBreakerService.stats() + circuitBreakerService.stats(), + scriptService.stats() ); } public NodeStats stats(CommonStatsFlags indices, boolean os, boolean process, boolean jvm, boolean threadPool, boolean network, - boolean fs, boolean transport, boolean http, boolean circuitBreaker) { + boolean fs, boolean transport, boolean http, boolean circuitBreaker, + boolean script) { // for indices stats we want to include previous allocated shards stats as well (it will // only be applied to the sensible ones to use, like refresh/merge/flush/indexing stats) return new NodeStats(discovery.localNode(), System.currentTimeMillis(), @@ -151,7 +163,8 @@ public class NodeService extends AbstractComponent { fs ? monitorService.fsService().stats() : null, transport ? transportService.stats() : null, http ? (httpServer == null ? null : httpServer.stats()) : null, - circuitBreaker ? circuitBreakerService.stats() : null + circuitBreaker ? circuitBreakerService.stats() : null, + script ? scriptService.stats() : null ); } } diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/node/stats/RestNodesStatsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/node/stats/RestNodesStatsAction.java index d5bb383c33a..3c231de534e 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/node/stats/RestNodesStatsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/node/stats/RestNodesStatsAction.java @@ -76,6 +76,7 @@ public class RestNodesStatsAction extends BaseRestHandler { nodesStatsRequest.indices(metrics.contains("indices")); nodesStatsRequest.process(metrics.contains("process")); nodesStatsRequest.breaker(metrics.contains("breaker")); + nodesStatsRequest.script(metrics.contains("script")); // check for index specific metrics if (metrics.contains("indices")) { diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java index 91e0235f54b..fe447b2d9d8 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java @@ -57,6 +57,7 @@ import org.elasticsearch.rest.*; import org.elasticsearch.rest.action.support.RestActionListener; import org.elasticsearch.rest.action.support.RestResponseListener; import org.elasticsearch.rest.action.support.RestTable; +import org.elasticsearch.script.ScriptStats; import org.elasticsearch.search.suggest.completion.CompletionStats; import java.util.Locale; @@ -92,7 +93,7 @@ public class RestNodesAction extends AbstractCatAction { @Override public void processResponse(final NodesInfoResponse nodesInfoResponse) { NodesStatsRequest nodesStatsRequest = new NodesStatsRequest(); - nodesStatsRequest.clear().jvm(true).os(true).fs(true).indices(true).process(true); + nodesStatsRequest.clear().jvm(true).os(true).fs(true).indices(true).process(true).script(true); client.admin().cluster().nodesStats(nodesStatsRequest, new RestResponseListener(channel) { @Override public RestResponse buildResponse(NodesStatsResponse nodesStatsResponse) throws Exception { @@ -183,6 +184,9 @@ public class RestNodesAction extends AbstractCatAction { table.addCell("refresh.total", "alias:rto,refreshTotal;default:false;text-align:right;desc:total refreshes"); table.addCell("refresh.time", "alias:rti,refreshTime;default:false;text-align:right;desc:time spent in refreshes"); + table.addCell("script.compilations", "alias:scrcc,scriptCompilations;default:false;text-align:right;desc:script compilations"); + table.addCell("script.cache_evictions", "alias:scrce,scriptCacheEvictions;default:false;text-align:right;desc:script cache evictions"); + table.addCell("search.fetch_current", "alias:sfc,searchFetchCurrent;default:false;text-align:right;desc:current fetch phase ops"); table.addCell("search.fetch_time", "alias:sfti,searchFetchTime;default:false;text-align:right;desc:time spent in fetch phase"); table.addCell("search.fetch_total", "alias:sfto,searchFetchTotal;default:false;text-align:right;desc:total fetch ops"); @@ -317,6 +321,10 @@ public class RestNodesAction extends AbstractCatAction { table.addCell(refreshStats == null ? null : refreshStats.getTotal()); table.addCell(refreshStats == null ? null : refreshStats.getTotalTime()); + ScriptStats scriptStats = stats == null ? null : stats.getScriptStats(); + table.addCell(scriptStats == null ? null : scriptStats.getCompilations()); + table.addCell(scriptStats == null ? null : scriptStats.getCacheEvictions()); + SearchStats searchStats = indicesStats == null ? null : indicesStats.getSearch(); table.addCell(searchStats == null ? null : searchStats.getTotal().getFetchCurrent()); table.addCell(searchStats == null ? null : searchStats.getTotal().getFetchTime()); diff --git a/core/src/main/java/org/elasticsearch/script/ScriptMetrics.java b/core/src/main/java/org/elasticsearch/script/ScriptMetrics.java new file mode 100644 index 00000000000..c779c196290 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/script/ScriptMetrics.java @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.script; + +import org.elasticsearch.common.metrics.CounterMetric; + +public class ScriptMetrics { + final CounterMetric compilationsMetric = new CounterMetric(); + final CounterMetric cacheEvictionsMetric = new CounterMetric(); + + public ScriptStats stats() { + return new ScriptStats(compilationsMetric.count(), cacheEvictionsMetric.count()); + } + + public void onCompilation() { + compilationsMetric.inc(); + } + + public void onCacheEviction() { + cacheEvictionsMetric.inc(); + } +} diff --git a/core/src/main/java/org/elasticsearch/script/ScriptService.java b/core/src/main/java/org/elasticsearch/script/ScriptService.java index f6d8132d6c6..c63cf47f4ae 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptService.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptService.java @@ -84,6 +84,7 @@ public class ScriptService extends AbstractComponent implements Closeable { public static final String DEFAULT_SCRIPTING_LANGUAGE_SETTING = "script.default_lang"; public static final String SCRIPT_CACHE_SIZE_SETTING = "script.cache.max_size"; + public static final int SCRIPT_CACHE_SIZE_DEFAULT = 100; public static final String SCRIPT_CACHE_EXPIRE_SETTING = "script.cache.expire"; public static final String SCRIPT_INDEX = ".scripts"; public static final String DEFAULT_LANG = GroovyScriptEngineService.NAME; @@ -107,6 +108,8 @@ public class ScriptService extends AbstractComponent implements Closeable { private Client client = null; + private final ScriptMetrics scriptMetrics = new ScriptMetrics(); + /** * @deprecated Use {@link org.elasticsearch.script.Script.ScriptField} instead. This should be removed in * 2.0 @@ -140,7 +143,7 @@ public class ScriptService extends AbstractComponent implements Closeable { this.scriptEngines = scriptEngines; this.scriptContextRegistry = scriptContextRegistry; - int cacheMaxSize = settings.getAsInt(SCRIPT_CACHE_SIZE_SETTING, 100); + int cacheMaxSize = settings.getAsInt(SCRIPT_CACHE_SIZE_SETTING, SCRIPT_CACHE_SIZE_DEFAULT); TimeValue cacheExpire = settings.getAsTime(SCRIPT_CACHE_EXPIRE_SETTING, null); logger.debug("using script cache with max_size [{}], expire [{}]", cacheMaxSize, cacheExpire); @@ -306,6 +309,7 @@ public class ScriptService extends AbstractComponent implements Closeable { //Since the cache key is the script content itself we don't need to //invalidate/check the cache if an indexed script changes. + scriptMetrics.onCompilation(); cache.put(cacheKey, compiledScript); } @@ -474,6 +478,10 @@ public class ScriptService extends AbstractComponent implements Closeable { } } + public ScriptStats stats() { + return scriptMetrics.stats(); + } + /** * A small listener for the script cache that calls each * {@code ScriptEngineService}'s {@code scriptRemoved} method when the @@ -486,6 +494,7 @@ public class ScriptService extends AbstractComponent implements Closeable { if (logger.isDebugEnabled()) { logger.debug("notifying script services of script removal due to: [{}]", notification.getCause()); } + scriptMetrics.onCacheEviction(); for (ScriptEngineService service : scriptEngines) { try { service.scriptRemoved(notification.getValue()); @@ -532,6 +541,7 @@ public class ScriptService extends AbstractComponent implements Closeable { String script = Streams.copyToString(reader); String cacheKey = getCacheKey(engineService, scriptNameExt.v1(), null); staticCache.put(cacheKey, new CompiledScript(ScriptType.FILE, scriptNameExt.v1(), engineService.types()[0], engineService.compile(script))); + scriptMetrics.onCompilation(); } } else { logger.warn("skipping compile of script file [{}] as all scripted operations are disabled for file scripts", file.toAbsolutePath()); diff --git a/core/src/main/java/org/elasticsearch/script/ScriptStats.java b/core/src/main/java/org/elasticsearch/script/ScriptStats.java new file mode 100644 index 00000000000..0bad4b27de0 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/script/ScriptStats.java @@ -0,0 +1,82 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.script; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.io.stream.Streamable; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentBuilderString; + +import java.io.IOException; + +public class ScriptStats implements Streamable, ToXContent { + private long compilations; + private long cacheEvictions; + + public ScriptStats() { + } + + public ScriptStats(long compilations, long cacheEvictions) { + this.compilations = compilations; + this.cacheEvictions = cacheEvictions; + } + + public void add(ScriptStats stats) { + this.compilations += stats.compilations; + this.cacheEvictions += stats.cacheEvictions; + } + + public long getCompilations() { + return compilations; + } + + public long getCacheEvictions() { + return cacheEvictions; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + compilations = in.readVLong(); + cacheEvictions = in.readVLong(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeVLong(compilations); + out.writeVLong(cacheEvictions); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(Fields.SCRIPT_STATS); + builder.field(Fields.COMPILATIONS, getCompilations()); + builder.field(Fields.CACHE_EVICTIONS, getCacheEvictions()); + builder.endObject(); + return builder; + } + + static final class Fields { + static final XContentBuilderString SCRIPT_STATS = new XContentBuilderString("script"); + static final XContentBuilderString COMPILATIONS = new XContentBuilderString("compilations"); + static final XContentBuilderString CACHE_EVICTIONS = new XContentBuilderString("cache_evictions"); + } +} diff --git a/core/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/MockDiskUsagesIT.java b/core/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/MockDiskUsagesIT.java index 863031a3499..a24e980f236 100644 --- a/core/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/MockDiskUsagesIT.java +++ b/core/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/MockDiskUsagesIT.java @@ -179,7 +179,8 @@ public class MockDiskUsagesIT extends ESIntegTestCase { System.currentTimeMillis(), null, null, null, null, null, fsInfo, - null, null, null); + null, null, null, + null); } /** diff --git a/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java b/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java index 96f2a45b2b9..6f6f5e53ab1 100644 --- a/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java +++ b/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java @@ -387,6 +387,73 @@ public class ScriptServiceTests extends ESTestCase { } } + @Test + public void testCompileCountedInCompilationStats() throws IOException { + buildScriptService(Settings.EMPTY); + scriptService.compile(new Script("1+1", ScriptType.INLINE, "test", null), randomFrom(scriptContexts)); + assertEquals(1L, scriptService.stats().getCompilations()); + } + + @Test + public void testExecutableCountedInCompilationStats() throws IOException { + buildScriptService(Settings.EMPTY); + scriptService.executable(new Script("1+1", ScriptType.INLINE, "test", null), randomFrom(scriptContexts)); + assertEquals(1L, scriptService.stats().getCompilations()); + } + + @Test + public void testSearchCountedInCompilationStats() throws IOException { + buildScriptService(Settings.EMPTY); + scriptService.search(null, new Script("1+1", ScriptType.INLINE, "test", null), randomFrom(scriptContexts)); + assertEquals(1L, scriptService.stats().getCompilations()); + } + + @Test + public void testMultipleCompilationsCountedInCompilationStats() throws IOException { + buildScriptService(Settings.EMPTY); + int numberOfCompilations = randomIntBetween(1, 1024); + for (int i = 0; i < numberOfCompilations; i++) { + scriptService.compile(new Script(String.format("%d+%d", i, i), ScriptType.INLINE, "test", null), randomFrom(scriptContexts)); + } + assertEquals(numberOfCompilations, scriptService.stats().getCompilations()); + } + + @Test + public void testCompilationStatsOnCacheHit() throws IOException { + Settings.Builder builder = Settings.builder(); + builder.put(ScriptService.SCRIPT_CACHE_SIZE_SETTING, 1); + buildScriptService(builder.build()); + scriptService.executable(new Script("1+1", ScriptType.INLINE, "test", null), randomFrom(scriptContexts)); + scriptService.executable(new Script("1+1", ScriptType.INLINE, "test", null), randomFrom(scriptContexts)); + assertEquals(1L, scriptService.stats().getCompilations()); + } + + @Test + public void testFileScriptCountedInCompilationStats() throws IOException { + buildScriptService(Settings.EMPTY); + createFileScripts("test"); + scriptService.compile(new Script("file_script", ScriptType.FILE, "test", null), randomFrom(scriptContexts)); + assertEquals(1L, scriptService.stats().getCompilations()); + } + + @Test + public void testIndexedScriptCountedInCompilationStats() throws IOException { + buildScriptService(Settings.EMPTY); + scriptService.compile(new Script("script", ScriptType.INDEXED, "test", null), randomFrom(scriptContexts)); + assertEquals(1L, scriptService.stats().getCompilations()); + } + + @Test + public void testCacheEvictionCountedInCacheEvictionsStats() throws IOException { + Settings.Builder builder = Settings.builder(); + builder.put(ScriptService.SCRIPT_CACHE_SIZE_SETTING, 1); + buildScriptService(builder.build()); + scriptService.executable(new Script("1+1", ScriptType.INLINE, "test", null), randomFrom(scriptContexts)); + scriptService.executable(new Script("2+2", ScriptType.INLINE, "test", null), randomFrom(scriptContexts)); + assertEquals(2L, scriptService.stats().getCompilations()); + assertEquals(1L, scriptService.stats().getCacheEvictions()); + } + private void createFileScripts(String... langs) throws IOException { for (String lang : langs) { Path scriptPath = scriptsFilePath.resolve("file_script." + lang); diff --git a/core/src/test/java/org/elasticsearch/test/InternalTestCluster.java b/core/src/test/java/org/elasticsearch/test/InternalTestCluster.java index 19fe03ce988..189a813bbf0 100644 --- a/core/src/test/java/org/elasticsearch/test/InternalTestCluster.java +++ b/core/src/test/java/org/elasticsearch/test/InternalTestCluster.java @@ -1855,7 +1855,7 @@ public final class InternalTestCluster extends TestCluster { } NodeService nodeService = getInstanceFromNode(NodeService.class, nodeAndClient.node); - NodeStats stats = nodeService.stats(CommonStatsFlags.ALL, false, false, false, false, false, false, false, false, false); + NodeStats stats = nodeService.stats(CommonStatsFlags.ALL, false, false, false, false, false, false, false, false, false, false); assertThat("Fielddata size must be 0 on node: " + stats.getNode(), stats.getIndices().getFieldData().getMemorySizeInBytes(), equalTo(0l)); assertThat("Query cache size must be 0 on node: " + stats.getNode(), stats.getIndices().getQueryCache().getMemorySizeInBytes(), equalTo(0l)); assertThat("FixedBitSet cache size must be 0 on node: " + stats.getNode(), stats.getIndices().getSegments().getBitsetMemoryInBytes(), equalTo(0l)); diff --git a/docs/reference/cat/nodes.asciidoc b/docs/reference/cat/nodes.asciidoc index 0eccba76827..ab9ffd9a384 100644 --- a/docs/reference/cat/nodes.asciidoc +++ b/docs/reference/cat/nodes.asciidoc @@ -168,6 +168,8 @@ percolating |0s |`percolate.total` |`pto`, `percolateTotal` |No |Total percolations |0 |`refresh.total` |`rto`, `refreshTotal` |No |Number of refreshes |16 |`refresh.time` |`rti`, `refreshTime` |No |Time spent in refreshes |91ms +|`script.compilations` |`scrcc`, `scriptCompilations` |No |Total script compilations |17 +|`script.cache_evictions` |`scrce`, `scriptCacheEvictions` |No |Total compiled scripts evicted from cache |6 |`search.fetch_current` |`sfc`, `searchFetchCurrent` |No |Current fetch phase operations |0 |`search.fetch_time` |`sfti`, `searchFetchTime` |No |Time spent in fetch