Own Pipeline Plugin throws Exception


#1

Hi there,

since i got a problem which i think cant get solved by the provided pipeline rule functions, i decided to write my own plugin.
I used this tutorial for setting up my workspace.
Everything seemd to be good, at least until i copied my .jar into the plugin folder and tried to restart graylog.
The errors that are thrown are this:

oivsvmw593 graylog-server[19636]: Caused by: java.lang.ClassNotFoundException: org.graylog.plugins.pipelineprocessor.ast.functions.AbstractFunction
graylog-server[19636]: at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
graylog-server[19636]: at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
graylog-server[19636]: at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:814)
graylog-server[19636]: at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

my Function looks like this:

package com.burda.plugins.domainsplit;

  import org.graylog.plugins.pipelineprocessor.EvaluationContext;
  import org.graylog.plugins.pipelineprocessor.ast.functions.AbstractFunction;
  import org.graylog.plugins.pipelineprocessor.ast.functions.FunctionArgs;
  import org.graylog.plugins.pipelineprocessor.ast.functions.FunctionDescriptor;
  import org.graylog.plugins.pipelineprocessor.ast.functions.ParameterDescriptor;

  import java.util.Arrays;
  import java.util.List;

 public class DomainSplitFunction extends AbstractFunction<String[]> {
     public static final String NAME = "domain_split";
     private final ParameterDescriptor<String, String> value;
     private final List<String> secondLevel = Arrays.asList("2000", "ab", "ac");

  public DomainSplitFunction() {
        value = ParameterDescriptor.string("value")
            .description("The Domain String to be split")
            .build();
     }

    @Override
    public String[] evaluate(FunctionArgs args, EvaluationContext context) {
       String domain = value.required(args, context);

    if(domain == null) {
        return null;
    }

    String[] split = domain.split("\\.");
    String[] domains = new String[3];
    int count = split.length-1;

    String subDom = "";

    try {
        if(secondLevel.contains(split[count-1])) {
            domains[0] = split[count - 1] + "." + split[count];
            count = count - 2;
        } else {
            domains[0] = split[count];
            count = count - 1;
        }

        domains[1] = split[count];
        count = count - 1;

        for(; count >= 0; count--) {
            if(subDom.equals("")) {
                subDom = split[count];
            } else {
                subDom = split[count].concat("."+subDom);
            }
        }

    } catch (Exception e) {
        System.out.println("Error with Domain String");
        return null;
    }

    domains[2] = subDom;
    return domains;

}

@Override
public FunctionDescriptor<String[]> descriptor() {
    return FunctionDescriptor.<String[]>builder()
            .name(NAME)
            .params(value)
            .returnType(String[].class)
            .description("Splits given Domain String into an Array with Top Level (0), Domain (1) and Subdomain (2)")
            .build();
  }
}

The FunctioModule looks like this:

package com.burda.plugins.domainsplit;

import com.google.inject.Binder;
import org.graylog2.plugin.PluginConfigBean;
import org.graylog2.plugin.PluginModule;

import java.util.Collections;
import java.util.Set;

import static org.graylog.plugins.pipelineprocessor.functions.ProcessorFunctionsModule.addMessageProcessorFunction;
import static org.graylog.plugins.pipelineprocessor.functions.ProcessorFunctionsModule.processorFunctionBinder;


public class DomainSplitFunctionModule extends PluginModule {

@Override
public Set<? extends PluginConfigBean> getConfigBeans() {
    return Collections.emptySet();
}

@Override
protected void configure() {
    /*
     * Register your plugin types here.
     *
     * Examples:
     *
     * addMessageInput(Class<? extends MessageInput>);
     * addMessageFilter(Class<? extends MessageFilter>);
     * addMessageOutput(Class<? extends MessageOutput>);
     * addPeriodical(Class<? extends Periodical>);
     * addAlarmCallback(Class<? extends AlarmCallback>);
     * addInitializer(Class<? extends Service>);
     * addRestResource(Class<? extends PluginRestResource>);
     *
     *
     * Add all configuration beans returned by getConfigBeans():
     *
     * addConfigBeans();
     */
    addMessageProcessorFunction(DomainSplitFunction.NAME, DomainSplitFunction.class);
}

protected void addMessageProcessorFunction(String name, Class<DomainSplitFunction> domainSplitFunctionClass) {
    addMessageProcessorFunction(binder(), name, domainSplitFunctionClass);
}

public static void addMessageProcessorFunction(Binder binder, String name, Class<DomainSplitFunction> domainSplitFunctionClass) {
    processorFunctionBinder(binder).addBinding(name).to(domainSplitFunctionClass);
  }
}

I had Problems with editing the FunctionModule like the tutorial did it… It seems like some functions are not working anymore

Greetings

Merasil


(Jochen) #2

Make sure that you’re using a shared classloader for your plugin.


#3

Thx, this made it work :slight_smile:

If u got the time, may i ask u to explain what this switch exactly does? cause i cant find a good documentation about writing own plugins etc.


(Jochen) #4

It loads the plugin in the shared class loader (in which it has access to classes of other plugins in the same shared class loader, such as the processing pipeline plugin) instead of an isolated class loader (in which it only has access to its own classes and the classes of the Graylog core).


(system) #5

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.