@Test
  public void testCursorStrategyCopyWithMultipleResults() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .cursorStrategy(COPY)
            .sourceField("msg")
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {
                      new Result("the", "one", 0, 3), new Result("hello", "two", 10, 15),
                    };
                  }
                })
            .build();

    final Message msg = createMessage("message");
    msg.addField("msg", "the great hello");

    extractor.runExtractor(msg);

    // With the copy strategy, the source field will not be modified.
    assertThat(msg.getField("msg")).isEqualTo("the great hello");
  }
  @Test
  public void testWithMultipleTargetValueResultsAndOneValueIsNull() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {
                      new Result(1, "one", -1, -1),
                      new Result(2, "two", -1, -1),
                      new Result(null, "three", -1, -1)
                    };
                  }
                })
            .build();

    final Message msg = createMessage("the hello");

    extractor.runExtractor(msg);

    // If the extractor returns multiple results and one result value is null, all results will be
    // ignored.
    // TODO: This is the current behaviour and it is weird. Will be fixed soon.
    assertThat(msg.hasField("one")).isFalse();
    assertThat(msg.hasField("two")).isFalse();
    assertThat(msg.hasField("three")).isFalse();
  }
  @Test
  public void testCursorStrategyCutWithMultipleResults() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .cursorStrategy(CUT)
            .sourceField("msg")
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {
                      new Result("the", "one", 0, 3), new Result("hello", "two", 10, 15),
                    };
                  }
                })
            .build();

    final Message msg = createMessage("message");
    msg.addField("msg", "the great hello");

    extractor.runExtractor(msg);

    // With the cut strategy the matched data will be removed from the message.
    assertThat(msg.getField("msg")).isEqualTo("great");
  }
  @Test
  public void testCursorStrategyCutIfTargetFieldEqualsSourceField() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .cursorStrategy(CUT)
            .sourceField("msg")
            .targetField("msg")
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result("the", 0, 3)};
                  }
                })
            .build();

    final Message msg = createMessage("message");
    msg.addField("msg", "the hello");

    extractor.runExtractor(msg);

    // If source and target fields are the same, the field is not touched because it already got set
    // to a new value.
    assertThat(msg.getField("msg")).isEqualTo("the");
  }
  @Test
  public void testConvertersWithNonStringFieldValue() throws Exception {
    final Converter converter =
        new TestConverter.Builder()
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    return "converted";
                  }
                })
            .build();

    final TestExtractor extractor =
        new TestExtractor.Builder()
            .converters(Lists.newArrayList(converter))
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result(123, "target", -1, -1)};
                  }
                })
            .build();

    final Message msg = createMessage("message");

    extractor.runExtractor(msg);

    // Only string values will be converted.
    assertThat(msg.getField("target")).isEqualTo(123);
  }
  @Test
  public void testConvertersThatReturnNullValue() throws Exception {
    final Converter converter =
        new TestConverter.Builder()
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    return null;
                  }
                })
            .build();

    final TestExtractor extractor =
        new TestExtractor.Builder()
            .converters(Lists.newArrayList(converter))
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result("1", -1, -1)};
                  }
                })
            .build();

    final Message msg = createMessage("message");

    extractor.runExtractor(msg);

    assertThat(msg.getField("target")).isNull();
  }
  @Test
  public void testWithMultipleTargetValueResults() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {
                      new Result(1, "one", -1, -1),
                      new Result("2", "two", -1, -1),
                      new Result(3, "three", -1, -1)
                    };
                  }
                })
            .build();

    final Message msg = createMessage("the hello");

    extractor.runExtractor(msg);

    assertThat(msg.hasField("target")).isFalse();
    assertThat(msg.getField("one")).isEqualTo(1);
    assertThat(msg.getField("two")).isEqualTo("2");
    assertThat(msg.getField("three")).isEqualTo(3);
  }
  @Test
  public void testConvertersAreExecutedInOrder() throws Exception {
    final Converter converter1 =
        new TestConverter.Builder()
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    return ((String) input) + "1";
                  }
                })
            .build();

    final Converter converter2 =
        new TestConverter.Builder()
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    return ((String) input) + "2";
                  }
                })
            .build();

    final Converter converter3 =
        new TestConverter.Builder()
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    return ((String) input) + "3";
                  }
                })
            .build();

    final TestExtractor extractor =
        new TestExtractor.Builder()
            .converters(Lists.newArrayList(converter1, converter2, converter3))
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result("converter", -1, -1)};
                  }
                })
            .build();

    final Message msg = createMessage("message");

    extractor.runExtractor(msg);

    assertThat(msg.getField("target")).isEqualTo("converter123");
  }
  @Test
  public void testSuccessfulMatch() {
    StreamRule rule = getSampleRule();
    rule.setValue("^foo");

    Message msg = getSampleMessage();
    msg.addField("something", "foobar");

    StreamRuleMatcher matcher = getMatcher(rule);
    assertTrue(matcher.match(msg, rule));
  }
  @Test
  public void testMissedMatch() {
    StreamRule rule = getSampleRule();
    rule.setValue("^foo");

    Message msg = getSampleMessage();
    msg.addField("something", "zomg");

    StreamRuleMatcher matcher = getMatcher(rule);
    assertFalse(matcher.match(msg, rule));
  }
  @Test
  public void testSuccessfulComplexRegexMatch() {
    StreamRule rule = getSampleRule();
    rule.setField("some_field");
    rule.setValue("foo=^foo|bar\\d.+wat");

    Message msg = getSampleMessage();
    msg.addField("some_field", "bar1foowat");

    StreamRuleMatcher matcher = getMatcher(rule);
    assertTrue(matcher.match(msg, rule));
  }
  @Test
  public void testConvertersWithMultipleFields() throws Exception {
    final Converter converter =
        new TestConverter.Builder()
            .multiple(true)
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    return ImmutableMap.builder()
                        .put("one", 1)
                        .put("two", "2")
                        .put(
                            "message",
                            "message should not be overwritten") // Try to overwrite reserved field.
                        .build();
                  }
                })
            .build();

    final TestExtractor extractor =
        new TestExtractor.Builder()
            .converters(Lists.newArrayList(converter))
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result("1", -1, -1)};
                  }
                })
            .build();

    final Message msg = createMessage("the message");

    extractor.runExtractor(msg);

    // With a "multiple fields" converter the target field is not touched, only the additional
    // fields are added.
    assertThat(msg.getField("target")).isEqualTo("1");
    assertThat(msg.getField("one")).isEqualTo(1);
    assertThat(msg.getField("two")).isEqualTo("2");

    // Reserved fields are not overwritten!
    assertThat(msg.getField("message")).isEqualTo("the message");

    // Attempts to overwrite a reserved field are recorded as converter exception.
    assertThat(extractor.getConverterExceptionCount()).isEqualTo(1);
  }
  @Test
  public void testMultipleConvertersWithFirstReturningNullValue() throws Exception {
    final Converter converter1 =
        new TestConverter.Builder()
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    return null;
                  }
                })
            .build();

    final Converter converter2 =
        new TestConverter.Builder()
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    return input + "2";
                  }
                })
            .build();

    final TestExtractor extractor =
        new TestExtractor.Builder()
            .converters(Lists.newArrayList(converter1, converter2))
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result("converter", -1, -1)};
                  }
                })
            .build();

    final Message msg = createMessage("message");

    extractor.runExtractor(msg);

    // If the first converter returns null, the second will not be executed because the value is not
    // a string anymore.
    assertThat(msg.getField("target")).isNull();
  }
  @Test
  public void runCodegen() throws IOException {
    final Rule rule = parser.parseRule(ruleForTest(), true).withId("1");

    final String sourceCode = CodeGenerator.sourceCodeForRule(rule);
    Files.write(sourceCode, OUTFILE.toFile(), StandardCharsets.UTF_8);

    log.info("Code:\n{}", sourceCode);

    try {

      ClassLoader ruleClassloader = new ClassLoader() {};
      //noinspection unchecked
      Class<GeneratedRule> rule$1 =
          (Class<GeneratedRule>)
              JCC.loadFromJava(
                  ruleClassloader,
                  "org.graylog.plugins.pipelineprocessor.$dynamic.rules.rule$1",
                  sourceCode);

      //noinspection unchecked
      final Set<Constructor> constructors =
          ReflectionUtils.getConstructors(rule$1, input -> input.getParameterCount() == 1);
      final Constructor onlyElement = Iterables.getOnlyElement(constructors);
      final GeneratedRule generatedRule = (GeneratedRule) onlyElement.newInstance(functionRegistry);

      final Message message = new Message("hello", "jenkins.torch.sh", Tools.nowUTC());
      message.addField("message", "#1234");
      message.addField("something_that_doesnt_exist", "foo");
      final EvaluationContext context = new EvaluationContext(message);

      final boolean when = generatedRule.when(context);
      if (when) {
        generatedRule.then(context);
      }
      log.info("created dynamic rule {} matches: {}", generatedRule.name(), when);

      assertThat(context.currentMessage().hasField("some_identifier")).isTrue();

    } catch (InvocationTargetException
        | ClassNotFoundException
        | InstantiationException
        | IllegalAccessException e) {
      log.error("Cannot load dynamically created class!", e);
    }
  }
  @Test
  public void testWithStringCondition() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder().conditionType(STRING).conditionValue("hello").build();

    // Extractor runs if the message contains the condition value "hello".
    final Message msg1 = createMessage("hello world");

    extractor.runExtractor(msg1);

    assertThat(msg1.hasField("target")).isTrue();

    // Extractor does not run if the message does not contain the condition value.
    final Message msg2 = createMessage("the message");

    extractor.runExtractor(msg2);

    assertThat(msg2.hasField("target")).isFalse();
  }
  @Test
  public void testWithRegexpCondition() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder().conditionType(REGEX).conditionValue("^hello").build();

    // Extractor runs if the message matches the condition regexp.
    final Message msg1 = createMessage("hello world");

    extractor.runExtractor(msg1);

    assertThat(msg1.hasField("target")).isTrue();

    // Extractor does not run if the message does not match the condition regexp.
    final Message msg2 = createMessage("the hello");

    extractor.runExtractor(msg2);

    assertThat(msg2.hasField("target")).isFalse();
  }
  @Test
  public void testWithEmptyResultArray() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[0];
                  }
                })
            .build();

    final Message msg = createMessage("the hello");

    extractor.runExtractor(msg);

    assertThat(msg.hasField("target")).isFalse();
  }
  @Test
  public void testWithOneValueOnlyResultsAndValueIsNull() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result(null, -1, -1)};
                  }
                })
            .build();

    final Message msg = createMessage("the hello");

    extractor.runExtractor(msg);

    assertThat(msg.hasField("target")).isFalse();
  }
  @Test
  public void testCursorStrategyCutIfSourceFieldIsReservedField() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .cursorStrategy(CUT)
            .sourceField("message")
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result("the", 0, 3)};
                  }
                })
            .build();

    final Message msg = createMessage("the hello");

    extractor.runExtractor(msg);

    // The source value is not modified if it is a reserved field.
    assertThat(msg.getField("message")).isEqualTo("the hello");
  }
  @Override
  public boolean match(Message msg, StreamRule rule) {
    Double msgVal = getDouble(msg.getField(rule.getField()));
    if (msgVal == null) {
      return false;
    }

    Double ruleVal = getDouble(rule.getValue());
    if (ruleVal == null) {
      return false;
    }

    return rule.getInverted() ^ (msgVal > ruleVal);
  }
  @Test
  public void testCursorStrategyCutWithAllTextCut() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .cursorStrategy(CUT)
            .sourceField("msg")
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result("the hello", 0, 9)};
                  }
                })
            .build();

    final Message msg = createMessage("message");
    msg.addField("msg", "the hello");

    extractor.runExtractor(msg);

    // If all data is cut from the source field, the "fullyCutByExtractor" string gets inserted.
    assertThat(msg.getField("msg")).isEqualTo("fullyCutByExtractor");
  }
  @Test
  public void testCursorStrategyCutIfBeginAndEndIndexAreDisabled() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .cursorStrategy(CUT)
            .sourceField("msg")
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result("the", -1, -1)};
                  }
                })
            .build();

    final Message msg = createMessage("message");
    msg.addField("msg", "the hello");

    extractor.runExtractor(msg);

    // If the begin and end index is -1, the source field should not be modified.
    assertThat(msg.getField("msg")).isEqualTo("the hello");
  }
  private static boolean checkRouting(String outputTypeClass, Message msg) {
    // ElasticSearch gets all messages.
    if (outputTypeClass.equals(ES_CLASS_NAME)) {
      return true;
    }

    for (Stream stream : msg.getStreams()) {
      if (((StreamImpl) stream).hasConfiguredOutputs(outputTypeClass)) {
        return true;
      }
    }

    // No stream had that output configured.
    return false;
  }
  @Override
  public boolean filter(Message msg, GraylogServer server) {
    for (Blacklist blacklist : Blacklist.fetchAll()) {
      for (BlacklistRule rule : blacklist.getRules()) {
        if (Pattern.compile(rule.getTerm(), Pattern.DOTALL).matcher(msg.getMessage()).matches()) {
          LOG.debug("Message <{}> is blacklisted. First match on {}", this, rule.getTerm());

          // Done - This message is blacklisted.
          return true;
        }
      }
    }

    return false;
  }
  @Test(expected = StringIndexOutOfBoundsException.class)
  public void testCursorStrategyCutIfEndIndexIsDisabled() throws Exception {
    final TestExtractor extractor =
        new TestExtractor.Builder()
            .cursorStrategy(CUT)
            .sourceField("msg")
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result("the", 0, -1)};
                  }
                })
            .build();

    final Message msg = createMessage("message");
    msg.addField("msg", "the hello");

    extractor.runExtractor(msg);

    // If the end index is -1, the source field should not be modified.
    // TODO: The current implementation only checks if begin index is -1. Needs to be fixed.
    assertThat(msg.getField("msg")).isEqualTo("the hello");
  }
  @Test
  public void testRunExtractorCheckSourceValueIsString() throws Exception {
    final TestExtractor extractor = new TestExtractor.Builder().sourceField("a_field").build();

    // Extractor should not run for source field values that are not strings!
    final Message msg1 = createMessage("the message");
    msg1.addField("a_field", 1);

    extractor.runExtractor(msg1);

    assertThat(msg1.hasField("target")).isFalse();

    // The extractor should run for a source field value of type string.
    final Message msg2 = createMessage("the message");
    msg2.addField("a_field", "the source");

    extractor.runExtractor(msg2);

    assertThat(msg2.hasField("target")).isTrue();
  }
Exemple #27
0
 @Override
 public String apply(final Message input) {
   return input.getId();
 }
  @Override
  public void write(Message msg) throws Exception {
    if (shutdown || driverFailed) {
      return;
    }

    try {
      if (connection == null) {
        reconnect();
      }

      if (connection == null) {
        return;
      }

      synchronized (connection) {
        int index = 1;
        logInsert.setTimestamp(index++, new Timestamp(msg.getTimestamp().getMillis()));
        logInsert.setString(index++, msg.getId());
        logInsert.setString(index++, msg.getSource());
        String ms = msg.getMessage();
        if (ms != null && ms.length() > MAX_MESSAGE) {
          ms = ms.substring(0, MAX_MESSAGE);
        }
        logInsert.setString(index++, ms);

        if (fields != null) {
          for (String f : fields) {
            Object value = msg.getField(f);
            String s = value != null ? value.toString() : null;
            if (s == null) {
              logInsert.setNull(index++, Types.VARCHAR);
            } else {
              if (s.length() > MAX_VALUE) {
                s = s.substring(0, MAX_VALUE);
              }
              logInsert.setString(index++, s);
            }
          }
        }

        logInsert.executeUpdate();

        if (logInsertAttribute != null) {
          Object id = null;
          ResultSet ids = logInsert.getGeneratedKeys();
          while (ids != null && ids.next()) {
            id = ids.getObject(1);
          }
          if (id != null) {
            for (Entry<String, Object> e : msg.getFieldsEntries()) {
              String name = e.getKey();
              Object value = e.getValue();
              String s = value != null ? value.toString() : null;
              logInsertAttribute.setObject(1, id);
              logInsertAttribute.setString(2, name);
              if (s.length() > MAX_VALUE) {
                s = s.substring(0, MAX_VALUE);
              }
              logInsertAttribute.setString(3, s);
              logInsertAttribute.executeUpdate();
            }
          } else {
            throw new SQLException("Failed to generate ID for primary log record!");
          }
        }
      }
    } catch (SQLException e) {
      log.log(Level.WARNING, "JDBC output error: " + e.getMessage(), e);
      if (connection != null) {
        try {
          connection.rollback();
          connection.setAutoCommit(true);
        } catch (SQLException ee) {
          // Don`t care
        }
      }
      connection = null;
    } finally {
      if (connection != null) {
        connection.commit();
      }
    }
  }
  @Test
  public void testConvertersWithExceptions() throws Exception {
    final Converter converter1 =
        new TestConverter.Builder()
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    throw new NullPointerException("EEK");
                  }
                })
            .build();

    final Converter converter2 =
        new TestConverter.Builder()
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    return input + "2";
                  }
                })
            .build();

    final Converter converter3 =
        new TestConverter.Builder()
            .callback(
                new Function<Object, Object>() {
                  @Nullable
                  @Override
                  public Object apply(Object input) {
                    throw new NullPointerException("EEK");
                  }
                })
            .build();

    final TestExtractor extractor =
        new TestExtractor.Builder()
            .converters(Lists.newArrayList(converter1, converter2, converter3))
            .callback(
                new Callable<Result[]>() {
                  @Override
                  public Result[] call() throws Exception {
                    return new Result[] {new Result("converter", -1, -1)};
                  }
                })
            .build();

    final Message msg = createMessage("message");

    extractor.runExtractor(msg);

    // The two exceptions should have been recorded.
    assertThat(extractor.getConverterExceptionCount()).isEqualTo(2);

    // It ignores all converters which throw an exception but executes the ones that don't.
    // TODO: Is this really the expected behaviour? The converters are executed in order and
    // basically depend on the output of the previous. This might not work for all converters.
    assertThat(msg.getField("target")).isEqualTo("converter2");
  }