From cb82ab271e8d137812df6d131a9135dff09d6afa Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Sat, 25 Apr 2020 07:31:53 +0200 Subject: [PATCH] Allow specification of rootNameFilter via regular expression --- tools/docs/Insight-Embedding.md | 2 +- tools/docs/Insight-Manual.md | 12 ++--- tools/docs/Insight-Tracing.md | 6 +-- .../agentscript/test/AgentObjectFactory.java | 2 +- .../agentscript/test/AgentObjectTest.java | 6 +-- .../tools/agentscript/test/InsightAPI.java | 7 ++- .../tools/agentscript/impl/AgentObject.java | 10 ++-- .../agentscript/impl/RegexNameFilter.java | 46 +++++++++++++++++++ .../org/graalvm/tools/insight/Insight.java | 2 +- .../all/agentscript/EmbeddingDoubled.java | 2 +- vm/tests/all/agentscript/agent-exception.js | 2 +- vm/tests/all/agentscript/agent-exception.test | 4 +- vm/tests/all/agentscript/agent-limit.js | 2 +- vm/tests/all/agentscript/agent-opentracing.js | 2 +- 14 files changed, 80 insertions(+), 25 deletions(-) create mode 100644 tools/src/com.oracle.truffle.tools.agentscript/src/com/oracle/truffle/tools/agentscript/impl/RegexNameFilter.java diff --git a/tools/docs/Insight-Embedding.md b/tools/docs/Insight-Embedding.md index 8489d84f6bb9..e97730be9e2e 100644 --- a/tools/docs/Insight-Embedding.md +++ b/tools/docs/Insight-Embedding.md @@ -93,7 +93,7 @@ For example following script is going to observe who calls `process.exit`: ```bash $ curl --data \ 'insight.on("enter", (ctx, frame) => { console.log(new Error("call to exit").stack); }, \ - { roots: true, rootNameFilter: n => n === "exit" });' \ + { roots: true, rootNameFilter: "exit" });' \ -X POST http://localhost:9999/ ``` diff --git a/tools/docs/Insight-Manual.md b/tools/docs/Insight-Manual.md index 46ed1649300b..61e1641fb29f 100644 --- a/tools/docs/Insight-Manual.md +++ b/tools/docs/Insight-Manual.md @@ -333,7 +333,7 @@ insight.on('enter', function(ctx, frame) { print('fib for ' + frame.n); }, { roots: true, - rootNameFilter: (name) => 'fib' === name + rootNameFilter: 'fib' }); ``` @@ -458,7 +458,7 @@ insight.on('enter', (ev, frame) => { } }, { roots: true, - rootNameFilter: (n) => n === 'log' + rootNameFilter: 'log' }); ``` @@ -521,7 +521,7 @@ insight.on('enter', function(ctx, frame) { } }, { roots: true, - rootNameFilter: (n) => n === 'nextNatural' + rootNameFilter: 'nextNatural' }); ``` @@ -585,7 +585,7 @@ insight.on('enter', (ctx, frame) => { } }, { roots: true, - rootNameFilter: (name) => name === 'Filter' + rootNameFilter: 'Filter' }); insight.on('return', (ctx, frame) => { @@ -594,7 +594,7 @@ insight.on('return', (ctx, frame) => { max = 0; }, { roots: true, - rootNameFilter: (name) => name === 'measure' + rootNameFilter: 'measure' }); ``` @@ -622,7 +622,7 @@ insight.on('enter', (ctx, frame) => { } }, { roots: true, - rootNameFilter: (name) => name === 'Filter' + rootNameFilter: 'Filter' }); ``` diff --git a/tools/docs/Insight-Tracing.md b/tools/docs/Insight-Tracing.md index 1b53aaad7b4e..eda28044fed5 100644 --- a/tools/docs/Insight-Tracing.md +++ b/tools/docs/Insight-Tracing.md @@ -36,7 +36,7 @@ let initialize = function(tracer) { console.log(`agent: handling #${res.id} request for ${req.url}`); }, { roots: true, - rootNameFilter: name => name === 'emit', + rootNameFilter: 'emit', sourceFilter: src => src.name === 'events.js' }); @@ -50,7 +50,7 @@ let initialize = function(tracer) { } }, { roots: true, - rootNameFilter: name => name === 'end', + rootNameFilter: 'end', sourceFilter: src => src.name === '_http_outgoing.js' }); console.log('agent: ready'); @@ -118,7 +118,7 @@ let initializeJaeger = function (ctx, frame) { insight.on('return', initializeJaeger, { roots: true, - rootNameFilter: name => name === 'jaegerAvailable' + rootNameFilter: 'jaegerAvailable' }); ``` diff --git a/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/AgentObjectFactory.java b/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/AgentObjectFactory.java index 9082458a88e9..fb2aa9795a0b 100644 --- a/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/AgentObjectFactory.java +++ b/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/AgentObjectFactory.java @@ -53,7 +53,7 @@ final class AgentObjectFactory extends ProxyLanguage { static InsightAPI.OnConfig createConfig( boolean expressions, boolean statements, boolean roots, - Predicate rootNameFilter, Predicate sourceFilter) { + String rootNameFilter, Predicate sourceFilter) { InsightAPI.OnConfig config = new InsightAPI.OnConfig(); config.expressions = expressions; config.statements = statements; diff --git a/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/AgentObjectTest.java b/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/AgentObjectTest.java index 00609cfa8cb5..2778e49e483d 100644 --- a/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/AgentObjectTest.java +++ b/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/AgentObjectTest.java @@ -324,7 +324,7 @@ public void onEnterCallbackWithFilterOnRootName() throws Exception { agentAPI.on("enter", (ctx, frame) -> { assertNull("No function entered yet", functionName[0]); functionName[0] = ctx.name(); - }, AgentObjectFactory.createConfig(false, false, true, (name) -> "foo".equals(name), null)); + }, AgentObjectFactory.createConfig(false, false, true, "foo", null)); agentAPI.on("close", () -> { finished[0] = true; }); @@ -587,7 +587,7 @@ public void accessFrameVariables() throws Exception { assertTrue(names.isEmpty()); names.addAll(frame.keySet()); }; - agentAPI.on("enter", captureNames, createConfig(true, false, false, (name) -> "mul".equals(name), null)); + agentAPI.on("enter", captureNames, createConfig(true, false, false, "mul.*", null)); c.eval(sampleScript); agentAPI.off("enter", captureNames); @@ -597,7 +597,7 @@ public void accessFrameVariables() throws Exception { agentAPI.on("enter", (ctx, frame) -> { values[0] = frame.get("a"); values[1] = frame.get("b"); - }, AgentObjectFactory.createConfig(true, false, false, (name) -> "mul".equals(name), null)); + }, AgentObjectFactory.createConfig(true, false, false, "mul", null)); Value mul = c.getBindings(InstrumentationTestLanguage.ID).getMember("mul"); assertNotNull("mul function found", mul); diff --git a/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/InsightAPI.java b/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/InsightAPI.java index 3a719440b21f..802843465bdd 100644 --- a/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/InsightAPI.java +++ b/tools/src/com.oracle.truffle.tools.agentscript.test/src/com/oracle/truffle/tools/agentscript/test/InsightAPI.java @@ -170,7 +170,12 @@ class OnConfig { public boolean expressions; public boolean statements; public boolean roots; - public Predicate rootNameFilter; + + /** String with a regular expression to match name of functions. + * Prior to version 0.6 this had to be a + * {@code Function}. + */ + public String rootNameFilter; /* @since 0.4 */ public Predicate sourceFilter; } diff --git a/tools/src/com.oracle.truffle.tools.agentscript/src/com/oracle/truffle/tools/agentscript/impl/AgentObject.java b/tools/src/com.oracle.truffle.tools.agentscript/src/com/oracle/truffle/tools/agentscript/impl/AgentObject.java index b4334220ad2a..b75b44653728 100644 --- a/tools/src/com.oracle.truffle.tools.agentscript/src/com/oracle/truffle/tools/agentscript/impl/AgentObject.java +++ b/tools/src/com.oracle.truffle.tools.agentscript/src/com/oracle/truffle/tools/agentscript/impl/AgentObject.java @@ -218,10 +218,14 @@ private static SourceSectionFilter createFilter(AgentObject obj, Object[] args) try { Object fn = iop.readMember(config, "rootNameFilter"); if (fn != null && !iop.isNull(fn)) { - if (!iop.isExecutable(fn)) { - throw new IllegalArgumentException("rootNameFilter has to be a function!"); + if (iop.isString(fn)) { + builder.rootNameIs(new RegexNameFilter(iop.asString(fn))); + } else { + if (!iop.isExecutable(fn)) { + throw new IllegalArgumentException("rootNameFilter should be a string, a regular expression!"); + } + builder.rootNameIs(new RootNameFilter(fn)); } - builder.rootNameIs(new RootNameFilter(fn)); } } catch (UnknownIdentifierException ex) { // OK diff --git a/tools/src/com.oracle.truffle.tools.agentscript/src/com/oracle/truffle/tools/agentscript/impl/RegexNameFilter.java b/tools/src/com.oracle.truffle.tools.agentscript/src/com/oracle/truffle/tools/agentscript/impl/RegexNameFilter.java new file mode 100644 index 000000000000..812e982c38ff --- /dev/null +++ b/tools/src/com.oracle.truffle.tools.agentscript/src/com/oracle/truffle/tools/agentscript/impl/RegexNameFilter.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.tools.agentscript.impl; + +import com.oracle.truffle.api.CompilerDirectives; +import java.util.function.Predicate; +import java.util.regex.Pattern; + +final class RegexNameFilter implements Predicate { + private final Pattern regex; + + RegexNameFilter(String fn) { + this.regex = Pattern.compile(fn); + } + + @CompilerDirectives.TruffleBoundary + @Override + public boolean test(String rootName) { + if (rootName == null) { + return false; + } + return regex.matcher(rootName).matches(); + } +} diff --git a/tools/src/org.graalvm.tools.insight/src/org/graalvm/tools/insight/Insight.java b/tools/src/org.graalvm.tools.insight/src/org/graalvm/tools/insight/Insight.java index 6d84110ac32c..ccf0468a7088 100644 --- a/tools/src/org.graalvm.tools.insight/src/org/graalvm/tools/insight/Insight.java +++ b/tools/src/org.graalvm.tools.insight/src/org/graalvm/tools/insight/Insight.java @@ -63,6 +63,6 @@ private Insight() { * * @since 20.1 */ - public static final String VERSION = "0.5"; + public static final String VERSION = "0.6"; } diff --git a/vm/tests/all/agentscript/EmbeddingDoubled.java b/vm/tests/all/agentscript/EmbeddingDoubled.java index 60542d67e45d..25aad4e57f5c 100644 --- a/vm/tests/all/agentscript/EmbeddingDoubled.java +++ b/vm/tests/all/agentscript/EmbeddingDoubled.java @@ -40,7 +40,7 @@ public static void main(String... args) throws Exception { + "}\n" + "insight.on('return', fibreturn, {\n" + " roots: true,\n" - + " rootNameFilter: (n) => n.indexOf('fib') >= 0\n" + + " rootNameFilter: '.*fib.*'\n" + "});\n" + "\n"; diff --git a/vm/tests/all/agentscript/agent-exception.js b/vm/tests/all/agentscript/agent-exception.js index 800fa2ff1994..6e6cafc94b6b 100644 --- a/vm/tests/all/agentscript/agent-exception.js +++ b/vm/tests/all/agentscript/agent-exception.js @@ -15,5 +15,5 @@ insight.on('return', function checkLogging(ev, frame) { } }, { roots: true, - rootNameFilter: (n) => n === 'log' + rootNameFilter: 'log' }); diff --git a/vm/tests/all/agentscript/agent-exception.test b/vm/tests/all/agentscript/agent-exception.test index 592aedf99bc1..c9b289a296dd 100644 --- a/vm/tests/all/agentscript/agent-exception.test +++ b/vm/tests/all/agentscript/agent-exception.test @@ -36,10 +36,10 @@ insight: Unknown attribute misnamedAttribute >[1] js --jvm --experimental-options --insight=agent-error3.js log.js insight: Unknown event type 'enterOrLeave'.* >[7] js --jvm --experimental-options --insight=agent-error.js log.js -Error while initializing {id: "insight", version: "0.5"} +Error while initializing {id: "insight", version: "0.6"} .*at :anonymous.*agent-error.js.* >[7] js --experimental-options --insight=agent-error.js log.js -Error while initializing {id: "insight", version: "0.5"} +Error while initializing {id: "insight", version: "0.6"} .*at :anonymous.*agent-error.js.* >[7] js --jvm --experimental-options --insight=agent-error4.js -f log.js Error loading of source log.js.* diff --git a/vm/tests/all/agentscript/agent-limit.js b/vm/tests/all/agentscript/agent-limit.js index ef3cde074dca..3c52e33cd0d5 100644 --- a/vm/tests/all/agentscript/agent-limit.js +++ b/vm/tests/all/agentscript/agent-limit.js @@ -8,6 +8,6 @@ insight.on('enter', function(ctx, frame) { } }, { roots: true, - rootNameFilter: (n) => n === 'nextNatural' + rootNameFilter: 'n...Natural' }); diff --git a/vm/tests/all/agentscript/agent-opentracing.js b/vm/tests/all/agentscript/agent-opentracing.js index 4582fed45465..93105986c614 100644 --- a/vm/tests/all/agentscript/agent-opentracing.js +++ b/vm/tests/all/agentscript/agent-opentracing.js @@ -19,7 +19,7 @@ let initializeTracer = function (tracer) { console.log(`agent: handling #${res.id} request for ${req.url}`); }, { roots: true, - rootNameFilter: name => name === 'emit', + rootNameFilter: 'emit', sourceFilter: src => src.name === 'events.js' });