Repository: metron Updated Branches: refs/heads/Metron_0.4.1 f0ae85fb7 -> 269d42e92
METRON-1162 Apply Live Messages to the Profile Debugger (nickwallen) closes apache/metron#736 Project: http://git-wip-us.apache.org/repos/asf/metron/repo Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/6ff39ae3 Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/6ff39ae3 Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/6ff39ae3 Branch: refs/heads/Metron_0.4.1 Commit: 6ff39ae380d82fb5805f4092806b846332c3c8b8 Parents: f0ae85f Author: nickwallen <[email protected]> Authored: Fri Sep 8 17:15:22 2017 -0400 Committer: nickallen <[email protected]> Committed: Fri Sep 8 17:15:22 2017 -0400 ---------------------------------------------------------------------- .../client/stellar/ProfilerFunctions.java | 113 ++++++++++++++----- .../client/stellar/ProfilerFunctionsTest.java | 53 ++++++++- 2 files changed, 129 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metron/blob/6ff39ae3/metron-analytics/metron-profiler-client/src/main/java/org/apache/metron/profiler/client/stellar/ProfilerFunctions.java ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-profiler-client/src/main/java/org/apache/metron/profiler/client/stellar/ProfilerFunctions.java b/metron-analytics/metron-profiler-client/src/main/java/org/apache/metron/profiler/client/stellar/ProfilerFunctions.java index 8df5ca8..d6f2c6a 100644 --- a/metron-analytics/metron-profiler-client/src/main/java/org/apache/metron/profiler/client/stellar/ProfilerFunctions.java +++ b/metron-analytics/metron-profiler-client/src/main/java/org/apache/metron/profiler/client/stellar/ProfilerFunctions.java @@ -20,6 +20,7 @@ package org.apache.metron.profiler.client.stellar; +import org.apache.commons.collections4.ListUtils; import org.apache.metron.common.configuration.profiler.ProfilerConfig; import org.apache.metron.common.utils.JSONUtils; import org.apache.metron.profiler.ProfileMeasurement; @@ -41,6 +42,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -109,7 +111,7 @@ public class ProfilerFunctions { name="APPLY", description="Apply a message to a local profile runner.", params={ - "message(s)", "The message to apply. A JSON list can be used to apply multiple messages.", + "message(s)", "The message to apply; a JSON string or list of JSON strings.", "profiler", "A local profile runner returned by PROFILER_INIT." }, returns="The local profile runner." @@ -131,50 +133,99 @@ public class ProfilerFunctions { @Override public Object apply(List<Object> args, Context context) throws ParseException { - // user must provide the message as a string - String arg0 = Util.getArg(0, String.class, args); - if(arg0 == null) { - throw new IllegalArgumentException(format("expected string, found null")); + // the use can pass in one or more messages in a few different forms + Object arg0 = Util.getArg(0, Object.class, args); + List<JSONObject> messages = getMessages(arg0); + + // user must provide the stand alone profiler + StandAloneProfiler profiler = Util.getArg(1, StandAloneProfiler.class, args); + try { + for (JSONObject message : messages) { + profiler.apply(message); + } + + } catch (ExecutionException e) { + throw new IllegalArgumentException(format("Failed to apply message; error=%s", e.getMessage()), e); + } + + return profiler; + } + + /** + * Gets a message or messages from the function arguments. + * + * @param arg The function argument containing the message(s). + * @return A list of messages + */ + private List<JSONObject> getMessages(Object arg) { + List<JSONObject> messages; + + if (arg instanceof String) { + messages = getMessagesFromString((String) arg); + + } else if (arg instanceof Iterable) { + messages = getMessagesFromIterable((Iterable<String>) arg); + + } else if (arg instanceof JSONObject) { + messages = Collections.singletonList((JSONObject) arg); + + } else { + throw new IllegalArgumentException(format("invalid message: found '%s', expected String, List, or JSONObject", + ClassUtils.getShortClassName(arg, "null"))); } - // there could be one or more messages + return messages; + } + + /** + * Gets a message or messages from a List + * + * @param strings The function argument that is a bunch of strings. + * @return A list of messages. + */ + private List<JSONObject> getMessagesFromIterable(Iterable<String> strings) { List<JSONObject> messages = new ArrayList<>(); + + // the user pass in a list of strings + for (String str : strings) { + messages.addAll(getMessagesFromString(str)); + } + + return messages; + } + + /** + * Gets a message or messages from a String argument. + * + * @param arg0 The function argument is just a List. + * @return A list of messages. + */ + private List<JSONObject> getMessagesFromString(String arg0) { + List<JSONObject> messages = new ArrayList<>(); + try { Object parsedArg0 = parser.parse(arg0); - if(parsedArg0 instanceof JSONObject) { - // if there is only one message + if (parsedArg0 instanceof JSONObject) { + // if the string only contains one message messages.add((JSONObject) parsedArg0); - } else if(parsedArg0 instanceof JSONArray) { - // there are multiple messages + } else if (parsedArg0 instanceof JSONArray) { + // if the string contains multiple messages JSONArray jsonArray = (JSONArray) parsedArg0; - for(Object json: jsonArray) { - if(json instanceof JSONObject) { - messages.add((JSONObject) json); - - } else { - throw new IllegalArgumentException(format("invalid message: found '%s', expected JSONObject", - ClassUtils.getShortClassName(json, "null"))); - } + for (Object item : jsonArray) { + messages.addAll(getMessages(item)); } - } - } catch(org.json.simple.parser.ParseException e) { - throw new IllegalArgumentException("invalid message", e); - } - - // user must provide the stand alone profiler - StandAloneProfiler profiler = Util.getArg(1, StandAloneProfiler.class, args); - try { - for(JSONObject message : messages) { - profiler.apply(message); + } else { + throw new IllegalArgumentException(format("invalid message: found '%s', expected JSONObject or JSONArray", + ClassUtils.getShortClassName(parsedArg0, "null"))); } - } catch(ExecutionException e) { - throw new IllegalArgumentException(format("Failed to apply message; error=%s", e.getMessage()), e); + } catch (org.json.simple.parser.ParseException e) { + throw new IllegalArgumentException(format("invalid message: '%s'", e.getMessage()), e); } - return profiler; + return messages; } } http://git-wip-us.apache.org/repos/asf/metron/blob/6ff39ae3/metron-analytics/metron-profiler-client/src/test/java/org/apache/metron/profiler/client/stellar/ProfilerFunctionsTest.java ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-profiler-client/src/test/java/org/apache/metron/profiler/client/stellar/ProfilerFunctionsTest.java b/metron-analytics/metron-profiler-client/src/test/java/org/apache/metron/profiler/client/stellar/ProfilerFunctionsTest.java index bad3efe..e1c6aa8 100644 --- a/metron-analytics/metron-profiler-client/src/test/java/org/apache/metron/profiler/client/stellar/ProfilerFunctionsTest.java +++ b/metron-analytics/metron-profiler-client/src/test/java/org/apache/metron/profiler/client/stellar/ProfilerFunctionsTest.java @@ -21,13 +21,13 @@ package org.apache.metron.profiler.client.stellar; import org.adrianwalker.multilinestring.Multiline; -import org.apache.metron.profiler.ProfileMeasurement; import org.apache.metron.profiler.StandAloneProfiler; import org.apache.metron.stellar.common.DefaultStellarStatefulExecutor; import org.apache.metron.stellar.common.StellarStatefulExecutor; -import org.apache.metron.stellar.common.shell.StellarExecutor; import org.apache.metron.stellar.dsl.Context; import org.apache.metron.stellar.dsl.functions.resolver.SimpleFunctionResolver; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; import org.junit.Before; import org.junit.Test; @@ -176,7 +176,7 @@ public class ProfilerFunctionsTest { } @Test - public void testProfilerApply() { + public void testProfilerApplyWithString() { // initialize the profiler state.put("config", helloWorldProfilerDef); @@ -195,7 +195,28 @@ public class ProfilerFunctionsTest { } @Test - public void testProfilerApplyWithMultipleMessages() { + public void testProfilerApplyWithJSONObject() throws Exception { + + // initialize the profiler + state.put("config", helloWorldProfilerDef); + StandAloneProfiler profiler = run("PROFILER_INIT(config)", StandAloneProfiler.class); + state.put("profiler", profiler); + + // apply a message to the profiler + JSONParser parser = new JSONParser(); + JSONObject jsonObject = (JSONObject) parser.parse(message); + state.put("jsonObj", jsonObject); + StandAloneProfiler result = run("PROFILER_APPLY(jsonObj, profiler)", StandAloneProfiler.class); + + // validate + assertSame(profiler, result); + assertEquals(1, profiler.getProfileCount()); + assertEquals(1, profiler.getMessageCount()); + assertEquals(1, profiler.getRouteCount()); + } + + @Test + public void testProfilerApplyWithMultipleMessagesInJSONString() { // initialize the profiler state.put("config", helloWorldProfilerDef); @@ -214,6 +235,26 @@ public class ProfilerFunctionsTest { } @Test + public void testProfilerApplyWithListOfMessages() { + + // initialize the profiler + state.put("config", helloWorldProfilerDef); + StandAloneProfiler profiler = run("PROFILER_INIT(config)", StandAloneProfiler.class); + state.put("profiler", profiler); + + // apply a message to the profiler + state.put("msg", message); + StandAloneProfiler result = run("PROFILER_APPLY([msg, msg, msg], profiler)", StandAloneProfiler.class); + + // validate + assertSame(profiler, result); + assertEquals(1, profiler.getProfileCount()); + assertEquals(3, profiler.getMessageCount()); + assertEquals(3, profiler.getRouteCount()); + } + + + @Test public void testProfilerApplyWithEmptyList() { // initialize the profiler @@ -250,8 +291,8 @@ public class ProfilerFunctionsTest { StandAloneProfiler profiler = run("PROFILER_INIT(config)", StandAloneProfiler.class); state.put("profiler", profiler); - // there is no 'messages' variable - StandAloneProfiler result = run("PROFILER_APPLY(messages, profiler)", StandAloneProfiler.class); + // there is no 'messages' variable - should throw exception + run("PROFILER_APPLY(messages, profiler)", StandAloneProfiler.class); } @Test
