12 Commits

Author SHA1 Message Date
efbd25c2a6 update dependancies 2025-02-08 10:22:23 +01:00
4d575579cd Update to graylog 6 2025-02-08 10:22:20 +01:00
a984d4800f Rename metadata && lookup 2025-02-08 10:20:51 +01:00
43d91b9bd1 reformat jsx files 2025-02-08 10:20:40 +01:00
3544104196 Move buid config to pom.xml 2025-02-08 10:19:45 +01:00
89e9aefc69 Move buid config to pom.xml 2025-02-08 10:19:45 +01:00
433cdd3f56 rename plugin descriptin files 2025-02-08 09:23:31 +01:00
97ac9b0c4b Update redis summary page 2024-03-02 09:31:34 +01:00
a219bc672b Update redis summary page 2024-03-02 09:22:09 +01:00
43b21ad0a9 Ignore target dir 2024-03-02 09:20:28 +01:00
c597467656 v1.0.3: Support string list, with TTL 2024-02-04 16:51:04 +01:00
4b032a90cf Fix metrics 2024-02-04 13:07:19 +01:00
18 changed files with 3804 additions and 3884 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ node_modules/*
target/*
/target/

View File

@ -1,10 +0,0 @@
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED

View File

@ -1,6 +1,6 @@
# RedisLookupPlugin Plugin for Graylog
Plugin to add Redis Data Adapter in read/write to graylog so you can store and retrieve key/values from pipelines
Plugin to add Redis Data Adapter in read/write to graylog so you can store and retrieve key/values and lists of string values from pipelines
Support Redis authentication (with password and username/password)
**Required Graylog version:** 5.0 and later
@ -8,7 +8,7 @@ Support Redis authentication (with password and username/password)
Installation
------------
[Download the plugin](https://git.nosd.in/yo/graylog-redis-lookup-plugin/releases/download/v1.0.0/graylog-plugin-redis-lookup-1.0.0.jar)
[Download the plugin](https://git.nosd.in/yo/graylog-redis-lookup-plugin/releases/download/v1.0.3/graylog-plugin-redis-lookup-1.0.3.jar)
and place the `.jar` file in your Graylog plugin directory. The plugin directory
is the `plugins/` folder relative from your `graylog-server` directory by default
and can be configured in your `graylog.conf` file.
@ -35,8 +35,18 @@ Usage
* Use 'lookup_clear_key(lookup_table, key)' to remove key
* Use 'lookup_has_value(lookup_table, key)' to test key existence
* Use 'lookup_assign_ttl(lookup_table, key, ttl)' to change TTL of existing key
* Use 'lookup_set_string_list(lookup_table, key, value, [ttl])' to create a list named "key"
* Use 'lookup_add_string_list(lookup_table, key, value, [keep_duplicates])' to add value list to existing list
* Use 'lookup_remove_string_list(lookup_table, key, value) to remove a string from list "key"
By default keys will be created in Redis with the default TTL defined at data adapter creation time
By default single value keys will be created in Redis with the default TTL defined at data adapter creation time
Be aware that only setting TTL with 'lookup_assign_ttl' of 'lookup_set_string_list' alter TTL value in Redis ; so a list created with a TTL of 3600 will expire in 3600 seconds, even if it was updated with 'lookup_add_string_list' some seconds before expiration.
Known bugs
----------
Deletion via lookup_remove_string_list, lookup_clear_key or keep_duplicates=false sometimes not done.
Getting started

File diff suppressed because it is too large Load Diff

179
pom.xml
View File

@ -25,13 +25,13 @@
<parent>
<groupId>org.graylog.plugins</groupId>
<artifactId>graylog-plugin-web-parent</artifactId>
<version>5.0.0</version>
<version>6.0.0</version>
<relativePath>../graylog2-server/graylog-plugin-parent/graylog-plugin-web-parent</relativePath>
</parent>
<groupId>in.nosd.redis</groupId>
<artifactId>graylog-plugin-redis-lookup</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
@ -54,56 +54,69 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.release>11</maven.compiler.release>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.useIncrementalCompilation>false</maven.compiler.useIncrementalCompilation>
<!-- Plugins will not be deployed by default - set to `false` if you actually want to deploy it -->
<maven.deploy.skip>true</maven.deploy.skip>
<graylog.version>${project.parent.version}</graylog.version>
<graylog.plugin-dir>/usr/share/graylog-server/plugin</graylog.plugin-dir>
<graylog.version>6.0.0</graylog.version>
<guice.version>7.0.0</guice.version>
<auto-value.version>1.10.4</auto-value.version>
<auto-value-javabean.version>2.5.2</auto-value-javabean.version>
<jackson.version>2.17.1</jackson.version>
<validation-api.version>3.0.2</validation-api.version>
<joda-time.version>2.12.7</joda-time.version>
<commons-lang3.version>3.14.0</commons-lang3.version>
<metrics.version>4.2.25</metrics.version>
<javax.annotation-api.version>1.3.2</javax.annotation-api.version>
<license-maven.version>4.3</license-maven.version>
<!-- Nodejs dependencies -->
<nodejs.version>v18.18.0</nodejs.version>
<yarn.version>v1.22.19</yarn.version>
<!-- Plugin versions -->
<license-maven.version>4.3</license-maven.version>
<download-maven-plugin.version>1.6.8.1</download-maven-plugin.version>
</properties>
<!-- <distributionManagement>
<snapshotRepository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>sonatype-nexus-staging</id>
<name>Nexus Release Repository</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<repositories>
--> <!-- to make our snapshot releases work with Travis et al -->
<!-- <repository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>sonatype-nexus-releases</id>
<name>Sonatype Nexus Releases</name>
<url>https://oss.sonatype.org/content/repositories/releases</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
-->
<dependencies>
<!-- com.codahale.metrics -->
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${metrics.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>${validation-api.version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda-time.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value-annotations</artifactId>
<version>${auto-value.version}</version>
</dependency>
<dependency>
<groupId>org.graylog2</groupId>
<artifactId>graylog2-server</artifactId>
@ -118,6 +131,24 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.21</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>${guice.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-assistedinject</artifactId>
<version>${guice.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value</artifactId>
@ -147,42 +178,12 @@
</resources>
<plugins>
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
<groupId>de.thetaphi</groupId>
<artifactId>forbiddenapis</artifactId>
<configuration>
<licenseSets>
<licenseSet>
<header>com/mycila/maven/plugin/license/templates/SSPL-1.txt</header>
<properties>
<project.inceptionYear>2024</project.inceptionYear>
<owner>johan@nosd.in</owner>
</properties>
<includes>
<include>**/src/main/java/**</include>
<include>**/src/test/java/**</include>
<include>**/pom.xml</include>
<include>*.js</include>
<include>src/web/**/*.js</include>
<include>src/web/**/*.jsx</include>
<include>src/web/**/*.ts</include>
<include>src/web/**/*.tsx</include>
<include>src/web/**/*.css</include>
</includes>
<excludes>
<exclude>*.config.js</exclude>
</excludes>
</licenseSet>
</licenseSets>
<skip>true</skip>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
@ -193,12 +194,25 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<version>3.13.0</version>
<configuration>
<release>17</release>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
<forceJavacCompilerUse>false</forceJavacCompilerUse>
<fork>true</fork>
<compilerArgs>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED</arg>
</compilerArgs>
<annotationProcessors>
<annotationProcessor>com.google.auto.value.processor.AutoValueProcessor</annotationProcessor>
</annotationProcessors>
@ -224,6 +238,12 @@
<version>2.4.1</version>
<configuration>
<minimizeJar>false</minimizeJar>
<artifactSet>
<excludes>
<exclude>com.fasterxml.jackson.core:*</exclude>
<exclude>joda-time:joda-time</exclude>
</excludes>
</artifactSet>
</configuration>
<executions>
<execution>
@ -322,6 +342,7 @@
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.15.0</version>
<executions>
<execution>

View File

@ -27,17 +27,17 @@ import java.util.Set;
/**
* Implement the PluginMetaData interface here.
*/
public class RedisLookupPluginMetaData implements PluginMetaData {
public class RedisLookupMetaData implements PluginMetaData {
private static final String PLUGIN_PROPERTIES = "in.nosd.redis.graylog-plugin-redis-lookup/graylog-plugin.properties";
@Override
public String getUniqueId() {
return "in.nosd.redis.RedisLookupPluginPlugin";
return "in.nosd.redis.RedisLookupPlugin";
}
@Override
public String getName() {
return "RedisLookupPlugin";
return "Redis Lookup";
}
@Override

View File

@ -16,14 +16,15 @@
*/
package in.nosd.redis;
import com.google.inject.Binder;
import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.MapBinder;
import org.graylog.plugins.pipelineprocessor.ast.functions.Function;
import org.graylog2.plugin.PluginConfigBean;
import org.graylog2.plugin.PluginModule;
import com.google.inject.multibindings.MapBinder;
import com.google.inject.Binder;
import com.google.inject.TypeLiteral;
import in.nosd.redis.dataadapters.RedisLookupDataAdapter;
import in.nosd.redis.functions.RedisLookupPluginFunction;
@ -33,7 +34,7 @@ import java.util.Set;
/**
* Extend the PluginModule abstract class here to add you plugin to the system.
*/
public class RedisLookupPluginModule extends PluginModule {
public class RedisLookupModule extends PluginModule {
/**
* Returns all configuration beans required by this plugin.
*
@ -55,7 +56,7 @@ public class RedisLookupPluginModule extends PluginModule {
* addMessageFilter(Class<? extends MessageFilter>);
* addMessageOutput(Class<? extends MessageOutput>);
* addPeriodical(Class<? extends Periodical>);
* addAlarmCallback(Class<? extends AlarmCallback>);
// * addAlarmCallback(Class<? extends AlarmCallback>);
* addInitializer(Class<? extends Service>);
* addRestResource(Class<? extends PluginRestResource>);
*
@ -64,12 +65,12 @@ public class RedisLookupPluginModule extends PluginModule {
*
* addConfigBeans();
*/
addMessageProcessorFunction(RedisLookupPluginFunction.NAME, RedisLookupPluginFunction.class);
addMessageProcessorFunction(RedisLookupPluginFunction.NAME, RedisLookupPluginFunction.class);
installLookupDataAdapter2(RedisLookupDataAdapter.NAME, RedisLookupDataAdapter.class,
RedisLookupDataAdapter.Factory.class, RedisLookupDataAdapter.Config.class);
addConfigBeans();
}

View File

@ -30,11 +30,11 @@ import java.util.Collections;
public class RedisLookupPlugin implements Plugin {
@Override
public PluginMetaData metadata() {
return new RedisLookupPluginMetaData();
return new RedisLookupMetaData();
}
@Override
public Collection<PluginModule> modules () {
return Collections.<PluginModule>singletonList(new RedisLookupPluginModule());
return Collections.<PluginModule>singletonList(new RedisLookupModule());
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright (C) 2024 johan@nosd.in
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program 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
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
package in.nosd.redis;
import org.graylog2.plugin.Plugin;
import org.graylog2.plugin.PluginMetaData;
import org.graylog2.plugin.PluginModule;
import java.util.Collection;
import java.util.Collections;
/**
* Implement the Plugin interface here.
*/
public class RedisLookupPluginPlugin implements Plugin {
@Override
public PluginMetaData metadata() {
return new RedisLookupPluginMetaData();
}
@Override
public Collection<PluginModule> modules () {
return Collections.<PluginModule>singletonList(new RedisLookupPluginModule());
}
}

View File

@ -16,6 +16,20 @@
*/
package in.nosd.redis.dataadapters;
import java.util.List;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import org.graylog.autovalue.WithBeanGetter;
import org.graylog2.lookup.dto.DataAdapterDto;
import org.graylog2.plugin.lookup.LookupCachePurge;
import org.graylog2.plugin.lookup.LookupDataAdapter;
import org.graylog2.plugin.lookup.LookupDataAdapterConfiguration;
import org.graylog2.plugin.lookup.LookupResult;
import org.joda.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
@ -26,37 +40,18 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.auto.value.AutoValue;
import org.graylog2.lookup.dto.DataAdapterDto;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.apache.commons.lang3.StringUtils;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import in.nosd.redis.dataadapters.AutoValue_RedisLookupDataAdapter_Config;
import org.graylog2.plugin.lookup.LookupCachePurge;
import org.graylog2.plugin.lookup.LookupDataAdapter;
import org.graylog2.plugin.lookup.LookupDataAdapterConfiguration;
import org.graylog2.plugin.lookup.LookupResult;
import org.joda.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.StringJoiner;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import reactor.util.annotation.Nullable;
public class RedisLookupDataAdapter extends LookupDataAdapter {
private static final Logger LOG = LoggerFactory.getLogger(RedisLookupDataAdapter.class);
@ -73,14 +68,25 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
private final Meter redisGetRequestErrors;
private final Timer redisSetRequestTimer;
private final Meter redisSetRequestErrors;
private final Timer redisDelRequestTimer;
private final Meter redisDelRequestErrors;
private final Timer redisAssignTtlRequestTimer;
private final Meter redisAssignTtlRequestErrors;
private final Timer redisAddStringListRequestTimer;
private final Meter redisAddStringListRequestErrors;
private final Timer redisSetStringListRequestTimer;
private final Meter redisSetStringListRequestErrors;
private final Timer redisSetStringListWithTtlRequestTimer;
private final Meter redisSetStringListWithTtlRequestErrors;
private final Timer redisRemoveStringListRequestTimer;
private final Meter redisRemoveStringListRequestErrors;
@Inject
public RedisLookupDataAdapter(@Assisted("dto") DataAdapterDto dto,
MetricRegistry metricRegistry) {
super(dto, metricRegistry);
this.config = (Config) dto.config();
RedisURI redisUri ;
redisUri = RedisURI.Builder.redis(this.config.redisHost(),this.config.redisPort())
.withPort(this.config.redisPort())
@ -98,6 +104,18 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
this.redisGetRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisGetRequestErrors"));
this.redisSetRequestTimer = metricRegistry.timer(MetricRegistry.name(getClass(), "redisSetRequestTime"));
this.redisSetRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisSetRequestErrors"));
this.redisDelRequestTimer = metricRegistry.timer(MetricRegistry.name(getClass(), "redisDelRequestTime"));
this.redisDelRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisDelRequestErrors"));
this.redisAssignTtlRequestTimer = metricRegistry.timer(MetricRegistry.name(getClass(), "redisAssignTtlRequestTime"));
this.redisAssignTtlRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisAssignTtlRequestErrors"));
this.redisAddStringListRequestTimer = metricRegistry.timer(MetricRegistry.name(getClass(), "redisAddStringListRequestTime"));
this.redisAddStringListRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisAddStringListRequestErrors"));
this.redisSetStringListRequestTimer = metricRegistry.timer(MetricRegistry.name(getClass(), "redisSetStringListRequestTime"));
this.redisSetStringListRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisSetStringListRequestErrors"));
this.redisSetStringListWithTtlRequestTimer = metricRegistry.timer(MetricRegistry.name(getClass(), "redisSetStringListWithTtlRequestTime"));
this.redisSetStringListWithTtlRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisSetStringListWithTtlRequestErrors"));
this.redisRemoveStringListRequestTimer = metricRegistry.timer(MetricRegistry.name(getClass(), "redisRemoveStringListRequestTime"));
this.redisRemoveStringListRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisRemoveStringListRequestErrors"));
}
@Override
@ -124,6 +142,11 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
cachePurge.purgeAll();
}
private String getSingleValue(String key) {
final String value = this.commands.get(key);
return value;
}
@Override
protected LookupResult doGet(Object key) {
final Timer.Context time = redisGetRequestTimer.time();
@ -133,15 +156,22 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
return getEmptyResult();
}
try {
final String value = this.commands.get(trimmedKey);
if (value == null) {
LOG.debug("Redis GET request for key <{}> returned null, key do not exists.", trimmedKey);
redisGetRequestErrors.mark();
return LookupResult.empty();
// Get item type and existence
final String type = this.commands.type(trimmedKey);
switch(type) {
case "none":
LOG.debug("Redis TYPE request for key <{}> returned null, key do not exists.", trimmedKey);
redisGetRequestErrors.mark();
return LookupResult.empty();
case "list":
final List<String> result = this.commands.lrange(trimmedKey, 0, -1);
return LookupResult.withoutTTL().stringListValue(result).build();
default:
final String value = getSingleValue(trimmedKey);
return LookupResult.single(value);
}
return LookupResult.single(value);
} catch (Exception e) {
LOG.error("Redis GET request error for key <{}>", trimmedKey, e);
LOG.error("Exception: Redis GET request error for key <{}>", trimmedKey, e);
redisGetRequestErrors.mark();
return LookupResult.empty();
} finally {
@ -152,7 +182,6 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
// This is deprecated, see setValue
@Deprecated
public void set(Object key, Object value) {
return;
}
@Override
@ -160,6 +189,7 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
return setValueWithTtl(key, value, this.config.redisKeyTTL());
}
@Override
public LookupResult setValueWithTtl(Object key, Object value, Long ttlSec) {
final Timer.Context time = redisSetRequestTimer.time();
final String trimmedKey = StringUtils.trimToNull(key.toString());
@ -177,7 +207,7 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
}
return LookupResult.single(value.toString());
} catch (Exception e) {
LOG.error("Redis SET(EX) key <{}> to value <{}> with TTL <{}> returned an exception: {}", key, value, ttlSec, e);
LOG.error("Exception: Redis SET(EX) key <{}> to value <{}> with TTL <{}> returned {}", key, value, ttlSec, e);
redisSetRequestErrors.mark();
return LookupResult.withError();
} finally {
@ -187,18 +217,18 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
@Override
public void clearKey(Object key) {
final Timer.Context time = redisSetRequestTimer.time();
final Timer.Context time = redisDelRequestTimer.time();
final String trimmedKey = StringUtils.trimToNull(key.toString());
try {
final Long result = this.commands.del(key.toString());
final Long result = this.commands.del(trimmedKey);
if (result != 1) {
LOG.debug("Redis DEL key <{}> returned {}", key, result);
redisSetRequestErrors.mark();
LOG.debug("Redis DEL key <{}> returned {}", trimmedKey, result);
redisDelRequestErrors.mark();
}
return;
} catch (Exception e) {
LOG.error("Redis DEL key <{}> returned {}", key, e);
redisSetRequestErrors.mark();
LOG.error("Exception: Redis DEL key <{}> returned {}", trimmedKey, e);
redisDelRequestErrors.mark();
return;
} finally {
time.stop();
@ -207,37 +237,40 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
private LookupResult setExpire(String key, Long ttl) {
try {
final Boolean result = this.commands.expire(key, ttl);
if (!result) {
LOG.warn("Redis EXPIRE key <{}> to <{}> returned {}", key, ttl, result);
if (!this.commands.expire(key, ttl)) {
LOG.warn("Redis EXPIRE key <{}> to <{}> returned false (key does not exist or the timeout could not be set)", key, ttl);
return LookupResult.withError();
}
final String value = this.commands.get(key);
return LookupResult.single(value.toString());
} catch (Exception e) {
LOG.error("Redis EXPIRE key <{}> to <{}> returned {}", key, ttl, e);
return LookupResult.withError(e.toString());
return LookupResult.single(this.commands.get(key).toString());
}
catch (Exception e) {
// lettuce 6.3.0 returns "WRONGTYPE Operation against a key holding the wrong kind of value" when EXPIRE on a list key, but do the job.
if (e.getMessage().startsWith("WRONGTYPE Operation against a key holding the wrong kind of value")) {
} else {
LOG.error("Exception: Redis EXPIRE key <{}> to <{}> returned {}", key, ttl, e);
return LookupResult.withError(e.toString());
}
}
return LookupResult.single(this.commands.get(key).toString());
}
private LookupResult setPersist(String key) {
try {
final Boolean result = this.commands.persist(key);
if (!result) {
LOG.warn("Redis PERSIST key <{}> returned {}", key, result);
if (!this.commands.persist(key)) {
LOG.debug("Redis PERSIST key <{}> returned false (key does not exist or does not have an associated timeout)", key);
return LookupResult.withError();
}
final String value = this.commands.get(key);
return LookupResult.single(value.toString());
return LookupResult.single(this.commands.get(key).toString());
} catch (Exception e) {
LOG.error("Redis PERSIST key <{}> returned {}", key, e);
LOG.error("Exception: Redis PERSIST key <{}> returned {}", key, e);
return LookupResult.withError(e.toString());
}
}
// TTL -1 = never expire
@Override
public LookupResult assignTtl(Object key, Long ttlSec) {
final Timer.Context time = redisSetRequestTimer.time();
final Timer.Context time = redisAssignTtlRequestTimer.time();
final String trimmedKey = StringUtils.trimToNull(key.toString());
try {
if (ttlSec > 0) {
@ -246,9 +279,40 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
return setPersist(trimmedKey);
}
} catch (Exception e) {
LOG.error("assignTtl <{}> to key <{}> returned {}", ttlSec, trimmedKey, e);
redisSetRequestErrors.mark();
return LookupResult.withError();
// lettuce 6.3.0 returns "WRONGTYPE Operation against a key holding the wrong kind of value" when TTL on a list key, but do the job.
if (e.getMessage().startsWith("WRONGTYPE Operation against a key holding the wrong kind of value")) {
} else {
LOG.error("Exception: assignTtl <{}> to key <{}> returned {}", ttlSec, trimmedKey, e);
redisAssignTtlRequestErrors.mark();
return LookupResult.withError();
}
} finally {
time.stop();
}
return LookupResult.single(this.commands.get(trimmedKey));
}
@Override
public LookupResult addStringList(Object key, List<String> listValue, boolean keepDuplicates) {
final Timer.Context time = redisAddStringListRequestTimer.time();
final String trimmedKey = StringUtils.trimToNull(key.toString());
if (trimmedKey == null) {
LOG.debug("A blank key was supplied");
return getEmptyResult();
}
try {
if (!keepDuplicates) {
removeStringList(trimmedKey, listValue);
}
final Long len = this.commands.rpush(trimmedKey, listValue.toArray(new String[0]));
if (len > 0) {
return LookupResult.withoutTTL().stringListValue(this.commands.lrange(trimmedKey, 0, -1)).build();
}
return LookupResult.empty();
} catch (Exception e) {
LOG.error("Exception: Redis RPUSH request error for key <{}>: <{}>", trimmedKey, e);
redisAddStringListRequestErrors.mark();
return LookupResult.empty();
} finally {
time.stop();
}
@ -256,7 +320,71 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
@Override
public LookupResult setStringList(Object key, List<String> listValue) {
return LookupResult.empty();
final Timer.Context time = redisSetStringListRequestTimer.time();
final String trimmedKey = StringUtils.trimToNull(key.toString());
if (trimmedKey == null) {
LOG.debug("A blank key was supplied");
return getEmptyResult();
}
try {
// We need to replace list, so we delete it first
this.commands.ltrim(trimmedKey, 1, 0);
final Long len = this.commands.rpush(trimmedKey, listValue.toArray(new String[0]));
if (len > 0) {
return LookupResult.withoutTTL().stringListValue(this.commands.lrange(trimmedKey, 0, -1)).build();
}
return LookupResult.empty();
} catch (Exception e) {
LOG.error("Exception: Redis RPUSH request error for key <{}>: <{}>", trimmedKey, e);
redisSetStringListRequestErrors.mark();
return LookupResult.empty();
} finally {
time.stop();
}
}
@Override
public LookupResult setStringListWithTtl(Object key, List<String> listValue, Long ttlSec) {
final Timer.Context time = redisSetStringListWithTtlRequestTimer.time();
try {
setStringList(key, listValue);
return assignTtl(key, ttlSec);
} catch (Exception e) {
// This exception comes from assignTtl
if (e.getMessage().startsWith("WRONGTYPE Operation against a key holding the wrong kind of value")) {
} else {
LOG.error("Exception: Redis RPUSH request error for key <{}>: <{}>", key, e);
redisSetStringListWithTtlRequestErrors.mark();
return LookupResult.empty();
}
} finally {
time.stop();
}
return LookupResult.withoutTTL().stringListValue(this.commands.lrange(StringUtils.trimToNull(key.toString()), 0, -1)).build();
}
@Override
public LookupResult removeStringList(Object key, List<String> listValue) {
final Timer.Context time = redisRemoveStringListRequestTimer.time();
final String trimmedKey = StringUtils.trimToNull(key.toString());
if (trimmedKey == null) {
LOG.debug("A blank key was supplied");
return getEmptyResult();
}
try {
long removed = 0;
for (String value : listValue) {
removed += this.commands.lrem(trimmedKey, 0, value);
}
LOG.debug("Redis LREM for key <{}> and value <{}> deleted <{}> items", trimmedKey, listValue, removed);
return LookupResult.withoutTTL().stringListValue(this.commands.lrange(trimmedKey, 0, -1)).build();
} catch (Exception e) {
LOG.error("Exception: Redis LREM request error for key <{}> and value <{}>: <{}>", trimmedKey, listValue, e);
redisRemoveStringListRequestErrors.mark();
return LookupResult.empty();
} finally {
time.stop();
}
}
public interface Factory extends LookupDataAdapter.Factory2<RedisLookupDataAdapter> {
@ -289,11 +417,12 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
@AutoValue
@WithBeanGetter
@JsonAutoDetect
@JsonDeserialize(builder = RedisLookupDataAdapter.Config.Builder.class)
@JsonDeserialize(builder = AutoValue_RedisLookupDataAdapter_Config.Builder.class)
@JsonTypeName(NAME)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public abstract static class Config implements LookupDataAdapterConfiguration {
public static abstract class Config implements LookupDataAdapterConfiguration {
@Override
@JsonProperty(TYPE_FIELD)
@ -341,11 +470,6 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
@AutoValue.Builder
public abstract static class Builder {
@JsonCreator
public static Builder create() {
return Config.builder();
}
@JsonProperty(TYPE_FIELD)
public abstract Builder type(String type);

View File

@ -30,7 +30,7 @@ import org.graylog2.plugin.lookup.LookupResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import com.google.inject.Inject;
public class RedisLookupPluginFunction extends LookupTableFunction<GenericLookupResult> {

View File

@ -1 +1 @@
in.nosd.redis.RedisLookupPluginPlugin
in.nosd.redis.RedisLookupPlugin

View File

@ -1,36 +1,35 @@
/*
* Copyright (C) 2024 johan@nosd.in
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program 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
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
/* eslint-disable react/no-unescaped-entities, no-template-curly-in-string */
import React from 'react';
class RedisLookupAdapterDocumentation extends React.Component {
render() {
const style = { marginBottom: 10 };
return (
<div>
<p style={style}>
The Redis Lookup data adapter lookup redis for the given key and returns the values.<br/>
It supports writing key/values to Redis (SET command). <br/>
All created keys will have the TTL configured for the data adapter.
</p>
</div>
)
;
}
}
export default RedisLookupAdapterDocumentation;
/*
* Copyright (C) 2024 johan@nosd.in
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program 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
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
import React from 'react';
class RedisLookupAdapterDocumentation extends React.Component {
render() {
const style = { marginBottom: 10 };
return (
<div>
<p style={style}>
The Redis Lookup data adapter lookup redis for the given key and returns the values.<br/>
It supports writing key/values to Redis (SET command). <br/>
All created keys will have the TTL configured for the data adapter.
</p>
</div>
)
;
}
}
export default RedisLookupAdapterDocumentation;

View File

@ -1,116 +1,115 @@
/*
* Copyright (C) 2024 johan@nosd.in
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program 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
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
import React, { useCallback, useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
//import { Button } from 'components/graylog';
import { Input } from 'components/bootstrap';
class RedisLookupAdapterFieldSet extends React.Component {
static propTypes = {
config: PropTypes.shape({
redis_host: PropTypes.string.isRequired,
}).isRequired,
updateConfig: PropTypes.func.isRequired,
handleFormEvent: PropTypes.func.isRequired,
validationState: PropTypes.func.isRequired,
validationMessage: PropTypes.func.isRequired,
};
handleSelect = (fieldName) => {
return (selectedIndicator) => {
const config = lodash.cloneDeep(this.props.config);
config[fieldName] = selectedIndicator;
this.props.updateConfig(config);
};
};
render() {
const { config } = this.props;
return (
<fieldset>
<Input type="text"
id="redis_host"
name="redis_host"
label="Redis host"
required
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_host', 'Your Redis Host')}
bsStyle={this.props.validationState('redis_host')}
value={config.redis_host}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9" />
<Input type="text"
id="redis_port"
name="redis_port"
label="Redis port"
required
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_port', 'Redis port instance is listening on')}
bsStyle={this.props.validationState('redis_port')}
value={config.redis_port}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9" />
<Input type="text"
id="redis_database"
name="redis_database"
label="Redis database"
required
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_database', 'Redis database')}
bsStyle={this.props.validationState('redis_database')}
value={config.redis_database}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9" />
<Input type="text"
id="redis_ttl"
name="redis_ttl"
label="Redis key TTL"
required
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_ttl', 'Redis key TTL in seconds. Set -1 to not expire keys')}
bsStyle={this.props.validationState('redis_ttl')}
value={config.redis_ttl}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9" />
<Input type="text"
id="redis_username"
name="redis_username"
label="Redis username"
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_username', 'Redis username. Leave empty for no auth or "requirepass" authentication')}
bsStyle={this.props.validationState('redis_username')}
value={config.redis_username}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9" />
<Input type="password"
id="redis_password"
label="Redis password"
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_password', 'Redis password. Leave empty for no auth')}
bsStyle={this.props.validationState('redis_password')}
value={config.redis_password}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9">
</Input>
</fieldset>
);
}
}
export default RedisLookupAdapterFieldSet;
/*
* Copyright (C) 2024 johan@nosd.in
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program 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
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
import React, { useCallback, useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
//import { Button } from 'components/graylog';
import { Input } from 'components/bootstrap';
class RedisLookupAdapterFieldSet extends React.Component {
static propTypes = {
config: PropTypes.shape({
redis_host: PropTypes.string.isRequired,
}).isRequired,
updateConfig: PropTypes.func.isRequired,
handleFormEvent: PropTypes.func.isRequired,
validationState: PropTypes.func.isRequired,
validationMessage: PropTypes.func.isRequired,
};
handleSelect = (fieldName) => {
return (selectedIndicator) => {
const config = lodash.cloneDeep(this.props.config);
config[fieldName] = selectedIndicator;
this.props.updateConfig(config);
};
};
render() {
const { config } = this.props;
return (
<fieldset>
<Input type="text"
id="redis_host"
name="redis_host"
label="Redis host"
required
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_host', 'Your Redis Host')}
bsStyle={this.props.validationState('redis_host')}
value={config.redis_host}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9" />
<Input type="text"
id="redis_port"
name="redis_port"
label="Redis port"
required
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_port', 'Redis port instance is listening on')}
bsStyle={this.props.validationState('redis_port')}
value={config.redis_port}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9" />
<Input type="text"
id="redis_database"
name="redis_database"
label="Redis database"
required
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_database', 'Redis database')}
bsStyle={this.props.validationState('redis_database')}
value={config.redis_database}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9" />
<Input type="text"
id="redis_ttl"
name="redis_ttl"
label="Redis key TTL"
required
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_ttl', 'Redis key TTL in seconds. Set -1 to not expire keys')}
bsStyle={this.props.validationState('redis_ttl')}
value={config.redis_ttl}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9" />
<Input type="text"
id="redis_username"
name="redis_username"
label="Redis username"
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_username', 'Redis username. Leave empty for no auth or "requirepass" authentication')}
bsStyle={this.props.validationState('redis_username')}
value={config.redis_username}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9" />
<Input type="password"
id="redis_password"
label="Redis password"
onChange={this.props.handleFormEvent}
help={this.props.validationMessage('redis_password', 'Redis password. Leave empty for no auth')}
bsStyle={this.props.validationState('redis_password')}
value={config.redis_password}
labelClassName="col-sm-3"
wrapperClassName="col-sm-9">
</Input>
</fieldset>
);
}
}
export default RedisLookupAdapterFieldSet;

View File

@ -1,42 +1,52 @@
/*
* Copyright (C) 2024 johan@nosd.in
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program 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
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
// eslint-disable-next-line react/prefer-stateless-function
import React from 'react';
import PropTypes from 'prop-types';
class RedisLookupAdapterSummary extends React.Component {
static propTypes = {
dataAdapter: PropTypes.shape({
config: PropTypes.shape({
redis_host: PropTypes.string.isRequired,
}),
}),
};
render() {
const { config } = this.props.dataAdapter;
return (
<dl>
<dt>Redis host</dt>
<dd>{config.redis_host || 'n/a'}</dd>
</dl>
);
}
}
export default RedisLookupAdapterSummary;
/*
* Copyright (C) 2024 johan@nosd.in
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program 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
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
// eslint-disable-next-line react/prefer-stateless-function
import React from 'react';
import PropTypes from 'prop-types';
class RedisLookupAdapterSummary extends React.Component {
static propTypes = {
dataAdapter: PropTypes.shape({
config: PropTypes.shape({
redis_host: PropTypes.string.isRequired,
}),
}),
};
render() {
const { config } = this.props.dataAdapter;
return (
<dl>
<dt>Redis host</dt>
<dd>{config.redis_host || 'n/a'}</dd>
<dt>Redis port</dt>
<dd>{config.redis_port || 'n/a'}</dd>
<dt>Redis database</dt>
<dd>{config.redis_database}</dd>
<dt>Redis key TTL</dt>
<dd>{config.redis_ttl || 'n/a'}</dd>
<dt>Redis username</dt>
<dd>{config.redis_username || 'n/a'}</dd>
<dt>Redis password</dt>
<dd>******</dd>
</dl>
);
}
}
export default RedisLookupAdapterSummary;

View File

@ -1,39 +1,39 @@
/*
* Copyright (C) 2024 johan@nosd.in
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program 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
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
// eslint-disable-next-line no-unused-vars
import webpackEntry from 'webpack-entry';
import { PluginManifest, PluginStore } from 'graylog-web-plugin/plugin';
import packageJson from '../../package.json';
import RedisLookupAdapterDocumentation from './dataadapters/RedisLookupAdapterDocumentation';
import RedisLookupAdapterFieldSet from './dataadapters/RedisLookupAdapterFieldSet';
import RedisLookupAdapterSummary from './dataadapters/RedisLookupAdapterSummary';
const manifest = new PluginManifest(packageJson, {
lookupTableAdapters: [
{
type: 'RedisLookup',
displayName: 'Redis Lookup',
formComponent: RedisLookupAdapterFieldSet,
summaryComponent: RedisLookupAdapterSummary,
documentationComponent: RedisLookupAdapterDocumentation,
},
],
});
PluginStore.register(manifest);
/*
* Copyright (C) 2024 johan@nosd.in
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program 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
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
// eslint-disable-next-line no-unused-vars
import webpackEntry from 'webpack-entry';
import { PluginManifest, PluginStore } from 'graylog-web-plugin/plugin';
import packageJson from '../../package.json';
import RedisLookupAdapterDocumentation from './dataadapters/RedisLookupAdapterDocumentation';
import RedisLookupAdapterFieldSet from './dataadapters/RedisLookupAdapterFieldSet';
import RedisLookupAdapterSummary from './dataadapters/RedisLookupAdapterSummary';
const manifest = new PluginManifest(packageJson, {
lookupTableAdapters: [
{
type: 'RedisLookup',
displayName: 'Redis Lookup',
formComponent: RedisLookupAdapterFieldSet,
summaryComponent: RedisLookupAdapterSummary,
documentationComponent: RedisLookupAdapterDocumentation,
},
],
});
PluginStore.register(manifest);

View File

@ -19,6 +19,6 @@ const { PluginWebpackConfig } = require('graylog-web-plugin');
const { loadBuildConfig } = require('graylog-web-plugin');
// Remember to use the same name here and in `getUniqueId()` in the java MetaData class
module.exports = new PluginWebpackConfig(__dirname, 'in.nosd.redis.RedisLookupPluginPlugin', loadBuildConfig(path.resolve(__dirname, './build.config')), {
module.exports = new PluginWebpackConfig(__dirname, 'in.nosd.redis.RedisLookupPlugin', loadBuildConfig(path.resolve(__dirname, './build.config')), {
// Here goes your additional webpack configuration.
});

5667
yarn.lock

File diff suppressed because it is too large Load Diff