Compare commits
21 Commits
v1.0.0
...
efbd25c2a6
Author | SHA1 | Date | |
---|---|---|---|
efbd25c2a6 | |||
4d575579cd | |||
a984d4800f | |||
43d91b9bd1 | |||
3544104196 | |||
89e9aefc69 | |||
433cdd3f56 | |||
97ac9b0c4b | |||
a219bc672b | |||
43b21ad0a9 | |||
c597467656 | |||
4b032a90cf | |||
e1f6e0ad60 | |||
e77d4d915d | |||
0a0748172e | |||
8febd14eb6 | |||
2cf5dff011 | |||
30e1bf70d9 | |||
f1c53077a4 | |||
5a4b3cb38a | |||
5487e2dd71 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ node_modules/*
|
|||||||
target/*
|
target/*
|
||||||
|
|
||||||
|
|
||||||
|
/target/
|
||||||
|
@ -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
|
|
24
README.md
24
README.md
@ -1,6 +1,6 @@
|
|||||||
# RedisLookupPlugin Plugin for Graylog
|
# 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)
|
Support Redis authentication (with password and username/password)
|
||||||
|
|
||||||
**Required Graylog version:** 5.0 and later
|
**Required Graylog version:** 5.0 and later
|
||||||
@ -8,7 +8,7 @@ Support Redis authentication (with password and username/password)
|
|||||||
Installation
|
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
|
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
|
is the `plugins/` folder relative from your `graylog-server` directory by default
|
||||||
and can be configured in your `graylog.conf` file.
|
and can be configured in your `graylog.conf` file.
|
||||||
@ -30,8 +30,24 @@ Usage
|
|||||||
-----
|
-----
|
||||||
|
|
||||||
* Create data adapter, cache (or not), lookup table
|
* Create data adapter, cache (or not), lookup table
|
||||||
* Use 'lookup_set_value(lookup_table, key, value)' to create or update key in redis
|
* Use 'lookup_set_value(lookup_table, key, value, [ttl])' to create or update key in redis
|
||||||
* Use 'lookup(lookup_table, key)' to get key
|
* Use 'lookup_value(lookup_table, key)' to get key value
|
||||||
|
* 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 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
|
Getting started
|
||||||
---------------
|
---------------
|
||||||
|
File diff suppressed because it is too large
Load Diff
179
pom.xml
179
pom.xml
@ -25,13 +25,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.graylog.plugins</groupId>
|
<groupId>org.graylog.plugins</groupId>
|
||||||
<artifactId>graylog-plugin-web-parent</artifactId>
|
<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>
|
<relativePath>../graylog2-server/graylog-plugin-parent/graylog-plugin-web-parent</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>in.nosd.redis</groupId>
|
<groupId>in.nosd.redis</groupId>
|
||||||
<artifactId>graylog-plugin-redis-lookup</artifactId>
|
<artifactId>graylog-plugin-redis-lookup</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.0.3</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
@ -54,56 +54,69 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.release>11</maven.compiler.release>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<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 -->
|
<!-- Plugins will not be deployed by default - set to `false` if you actually want to deploy it -->
|
||||||
<maven.deploy.skip>true</maven.deploy.skip>
|
<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.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>
|
</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>
|
<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>
|
<dependency>
|
||||||
<groupId>org.graylog2</groupId>
|
<groupId>org.graylog2</groupId>
|
||||||
<artifactId>graylog2-server</artifactId>
|
<artifactId>graylog2-server</artifactId>
|
||||||
@ -118,6 +131,24 @@
|
|||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</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>
|
<dependency>
|
||||||
<groupId>com.google.auto.value</groupId>
|
<groupId>com.google.auto.value</groupId>
|
||||||
<artifactId>auto-value</artifactId>
|
<artifactId>auto-value</artifactId>
|
||||||
@ -147,42 +178,12 @@
|
|||||||
</resources>
|
</resources>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.mycila</groupId>
|
<groupId>de.thetaphi</groupId>
|
||||||
<artifactId>license-maven-plugin</artifactId>
|
<artifactId>forbiddenapis</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<licenseSets>
|
<skip>true</skip>
|
||||||
<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>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>check</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
@ -193,12 +194,25 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.10.1</version>
|
<version>3.13.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<release>17</release>
|
<release>17</release>
|
||||||
<showWarnings>true</showWarnings>
|
<showWarnings>true</showWarnings>
|
||||||
<showDeprecation>true</showDeprecation>
|
<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>
|
<annotationProcessors>
|
||||||
<annotationProcessor>com.google.auto.value.processor.AutoValueProcessor</annotationProcessor>
|
<annotationProcessor>com.google.auto.value.processor.AutoValueProcessor</annotationProcessor>
|
||||||
</annotationProcessors>
|
</annotationProcessors>
|
||||||
@ -224,6 +238,12 @@
|
|||||||
<version>2.4.1</version>
|
<version>2.4.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<minimizeJar>false</minimizeJar>
|
<minimizeJar>false</minimizeJar>
|
||||||
|
<artifactSet>
|
||||||
|
<excludes>
|
||||||
|
<exclude>com.fasterxml.jackson.core:*</exclude>
|
||||||
|
<exclude>joda-time:joda-time</exclude>
|
||||||
|
</excludes>
|
||||||
|
</artifactSet>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
@ -322,6 +342,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.github.eirslett</groupId>
|
<groupId>com.github.eirslett</groupId>
|
||||||
<artifactId>frontend-maven-plugin</artifactId>
|
<artifactId>frontend-maven-plugin</artifactId>
|
||||||
|
<version>1.15.0</version>
|
||||||
|
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
|
@ -27,17 +27,17 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* Implement the PluginMetaData interface here.
|
* 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";
|
private static final String PLUGIN_PROPERTIES = "in.nosd.redis.graylog-plugin-redis-lookup/graylog-plugin.properties";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUniqueId() {
|
public String getUniqueId() {
|
||||||
return "in.nosd.redis.RedisLookupPluginPlugin";
|
return "in.nosd.redis.RedisLookupPlugin";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "RedisLookupPlugin";
|
return "Redis Lookup";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -16,14 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
package in.nosd.redis;
|
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.graylog.plugins.pipelineprocessor.ast.functions.Function;
|
||||||
import org.graylog2.plugin.PluginConfigBean;
|
import org.graylog2.plugin.PluginConfigBean;
|
||||||
import org.graylog2.plugin.PluginModule;
|
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.dataadapters.RedisLookupDataAdapter;
|
||||||
import in.nosd.redis.functions.RedisLookupPluginFunction;
|
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.
|
* 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.
|
* Returns all configuration beans required by this plugin.
|
||||||
*
|
*
|
||||||
@ -55,7 +56,7 @@ public class RedisLookupPluginModule extends PluginModule {
|
|||||||
* addMessageFilter(Class<? extends MessageFilter>);
|
* addMessageFilter(Class<? extends MessageFilter>);
|
||||||
* addMessageOutput(Class<? extends MessageOutput>);
|
* addMessageOutput(Class<? extends MessageOutput>);
|
||||||
* addPeriodical(Class<? extends Periodical>);
|
* addPeriodical(Class<? extends Periodical>);
|
||||||
* addAlarmCallback(Class<? extends AlarmCallback>);
|
// * addAlarmCallback(Class<? extends AlarmCallback>);
|
||||||
* addInitializer(Class<? extends Service>);
|
* addInitializer(Class<? extends Service>);
|
||||||
* addRestResource(Class<? extends PluginRestResource>);
|
* addRestResource(Class<? extends PluginRestResource>);
|
||||||
*
|
*
|
@ -30,11 +30,11 @@ import java.util.Collections;
|
|||||||
public class RedisLookupPlugin implements Plugin {
|
public class RedisLookupPlugin implements Plugin {
|
||||||
@Override
|
@Override
|
||||||
public PluginMetaData metadata() {
|
public PluginMetaData metadata() {
|
||||||
return new RedisLookupPluginMetaData();
|
return new RedisLookupMetaData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<PluginModule> modules () {
|
public Collection<PluginModule> modules () {
|
||||||
return Collections.<PluginModule>singletonList(new RedisLookupPluginModule());
|
return Collections.<PluginModule>singletonList(new RedisLookupModule());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,6 +16,20 @@
|
|||||||
*/
|
*/
|
||||||
package in.nosd.redis.dataadapters;
|
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.Meter;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.codahale.metrics.Timer;
|
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.annotation.JsonTypeName;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
import com.google.auto.value.AutoValue;
|
import com.google.auto.value.AutoValue;
|
||||||
import org.graylog2.lookup.dto.DataAdapterDto;
|
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.assistedinject.Assisted;
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import io.lettuce.core.RedisClient;
|
import io.lettuce.core.RedisClient;
|
||||||
import io.lettuce.core.RedisURI;
|
import io.lettuce.core.RedisURI;
|
||||||
import io.lettuce.core.api.StatefulRedisConnection;
|
import io.lettuce.core.api.StatefulRedisConnection;
|
||||||
import io.lettuce.core.api.sync.RedisCommands;
|
import io.lettuce.core.api.sync.RedisCommands;
|
||||||
import in.nosd.redis.dataadapters.AutoValue_RedisLookupDataAdapter_Config;
|
import jakarta.validation.constraints.Min;
|
||||||
import org.graylog2.plugin.lookup.LookupCachePurge;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import org.graylog2.plugin.lookup.LookupDataAdapter;
|
import reactor.util.annotation.Nullable;
|
||||||
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;
|
|
||||||
|
|
||||||
public class RedisLookupDataAdapter extends LookupDataAdapter {
|
public class RedisLookupDataAdapter extends LookupDataAdapter {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RedisLookupDataAdapter.class);
|
private static final Logger LOG = LoggerFactory.getLogger(RedisLookupDataAdapter.class);
|
||||||
@ -68,18 +63,30 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
|
|||||||
private final Config config;
|
private final Config config;
|
||||||
private final RedisClient client;
|
private final RedisClient client;
|
||||||
private RedisCommands<String, String> commands;
|
private RedisCommands<String, String> commands;
|
||||||
|
private StatefulRedisConnection<String, String> connection;
|
||||||
private final Timer redisGetRequestTimer;
|
private final Timer redisGetRequestTimer;
|
||||||
private final Meter redisGetRequestErrors;
|
private final Meter redisGetRequestErrors;
|
||||||
private final Timer redisSetRequestTimer;
|
private final Timer redisSetRequestTimer;
|
||||||
private final Meter redisSetRequestErrors;
|
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
|
@Inject
|
||||||
public RedisLookupDataAdapter(@Assisted("dto") DataAdapterDto dto,
|
public RedisLookupDataAdapter(@Assisted("dto") DataAdapterDto dto,
|
||||||
MetricRegistry metricRegistry) {
|
MetricRegistry metricRegistry) {
|
||||||
super(dto, metricRegistry);
|
super(dto, metricRegistry);
|
||||||
|
|
||||||
this.config = (Config) dto.config();
|
this.config = (Config) dto.config();
|
||||||
|
|
||||||
RedisURI redisUri ;
|
RedisURI redisUri ;
|
||||||
redisUri = RedisURI.Builder.redis(this.config.redisHost(),this.config.redisPort())
|
redisUri = RedisURI.Builder.redis(this.config.redisHost(),this.config.redisPort())
|
||||||
.withPort(this.config.redisPort())
|
.withPort(this.config.redisPort())
|
||||||
@ -97,21 +104,33 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
|
|||||||
this.redisGetRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisGetRequestErrors"));
|
this.redisGetRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisGetRequestErrors"));
|
||||||
this.redisSetRequestTimer = metricRegistry.timer(MetricRegistry.name(getClass(), "redisSetRequestTime"));
|
this.redisSetRequestTimer = metricRegistry.timer(MetricRegistry.name(getClass(), "redisSetRequestTime"));
|
||||||
this.redisSetRequestErrors = metricRegistry.meter(MetricRegistry.name(getClass(), "redisSetRequestErrors"));
|
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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add code to initialise Redis connection
|
|
||||||
@Override
|
@Override
|
||||||
protected void doStart() throws Exception {
|
protected void doStart() throws Exception {
|
||||||
StatefulRedisConnection<String, String> connection = this.client.connect();
|
connection = this.client.connect();
|
||||||
this.commands = connection.sync();
|
this.commands = connection.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add code to close Redis connection
|
|
||||||
@Override
|
@Override
|
||||||
protected void doStop() throws Exception {
|
protected void doStop() throws Exception {
|
||||||
|
connection.close();
|
||||||
|
client.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the refresh interval for this data adapter. Use {@link Duration#ZERO} if refresh should be disabled.
|
||||||
@Override
|
@Override
|
||||||
public Duration refreshInterval() {
|
public Duration refreshInterval() {
|
||||||
return REFRESH_INTERVAL_DURATION;
|
return REFRESH_INTERVAL_DURATION;
|
||||||
@ -123,6 +142,11 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
|
|||||||
cachePurge.purgeAll();
|
cachePurge.purgeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getSingleValue(String key) {
|
||||||
|
final String value = this.commands.get(key);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected LookupResult doGet(Object key) {
|
protected LookupResult doGet(Object key) {
|
||||||
final Timer.Context time = redisGetRequestTimer.time();
|
final Timer.Context time = redisGetRequestTimer.time();
|
||||||
@ -132,15 +156,22 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
|
|||||||
return getEmptyResult();
|
return getEmptyResult();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final String value = this.commands.get(trimmedKey);
|
// Get item type and existence
|
||||||
if (value == null) {
|
final String type = this.commands.type(trimmedKey);
|
||||||
LOG.warn("Redis GET request for key <{}> returned null, key do not exists.", trimmedKey);
|
switch(type) {
|
||||||
|
case "none":
|
||||||
|
LOG.debug("Redis TYPE request for key <{}> returned null, key do not exists.", trimmedKey);
|
||||||
redisGetRequestErrors.mark();
|
redisGetRequestErrors.mark();
|
||||||
return LookupResult.empty();
|
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) {
|
} 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();
|
redisGetRequestErrors.mark();
|
||||||
return LookupResult.empty();
|
return LookupResult.empty();
|
||||||
} finally {
|
} finally {
|
||||||
@ -149,25 +180,207 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is deprecated, see setValue
|
// This is deprecated, see setValue
|
||||||
@Override
|
@Deprecated
|
||||||
public void set(Object key, Object value) {
|
public void set(Object key, Object value) {
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LookupResult setValue(Object key, Object value) {
|
public LookupResult setValue(Object key, Object value) {
|
||||||
|
return setValueWithTtl(key, value, this.config.redisKeyTTL());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LookupResult setValueWithTtl(Object key, Object value, Long ttlSec) {
|
||||||
final Timer.Context time = redisSetRequestTimer.time();
|
final Timer.Context time = redisSetRequestTimer.time();
|
||||||
|
final String trimmedKey = StringUtils.trimToNull(key.toString());
|
||||||
try {
|
try {
|
||||||
final String result = this.commands.setex(key.toString(), this.config.redisKeyTTL(), value.toString());
|
final String result;
|
||||||
|
if (ttlSec > 0 ) {
|
||||||
|
result = this.commands.setex(trimmedKey, ttlSec, value.toString());
|
||||||
|
} else {
|
||||||
|
result = this.commands.set(trimmedKey, value.toString());
|
||||||
|
}
|
||||||
if (!result.equals("OK")) {
|
if (!result.equals("OK")) {
|
||||||
LOG.warn("Redis SET key <{}> to value <{}> returned {}", key, value, result);
|
LOG.warn("Redis SET(EX) key <{}> to value <{}> with TTL <{}> returned {}", key, value, ttlSec, result);
|
||||||
redisSetRequestErrors.mark();
|
redisSetRequestErrors.mark();
|
||||||
return LookupResult.empty();
|
return LookupResult.empty();
|
||||||
}
|
}
|
||||||
return LookupResult.single(value.toString());
|
return LookupResult.single(value.toString());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Redis SET key <{}> to value <{}> returned an exception: {}", key, value, e);
|
LOG.error("Exception: Redis SET(EX) key <{}> to value <{}> with TTL <{}> returned {}", key, value, ttlSec, e);
|
||||||
redisSetRequestErrors.mark();
|
redisSetRequestErrors.mark();
|
||||||
|
return LookupResult.withError();
|
||||||
|
} finally {
|
||||||
|
time.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearKey(Object key) {
|
||||||
|
final Timer.Context time = redisDelRequestTimer.time();
|
||||||
|
final String trimmedKey = StringUtils.trimToNull(key.toString());
|
||||||
|
try {
|
||||||
|
final Long result = this.commands.del(trimmedKey);
|
||||||
|
if (result != 1) {
|
||||||
|
LOG.debug("Redis DEL key <{}> returned {}", trimmedKey, result);
|
||||||
|
redisDelRequestErrors.mark();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Exception: Redis DEL key <{}> returned {}", trimmedKey, e);
|
||||||
|
redisDelRequestErrors.mark();
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
time.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LookupResult setExpire(String key, Long ttl) {
|
||||||
|
try {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
return LookupResult.single(this.commands.get(key).toString());
|
||||||
|
} catch (Exception 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 = redisAssignTtlRequestTimer.time();
|
||||||
|
final String trimmedKey = StringUtils.trimToNull(key.toString());
|
||||||
|
try {
|
||||||
|
if (ttlSec > 0) {
|
||||||
|
return setExpire(trimmedKey, ttlSec);
|
||||||
|
} else {
|
||||||
|
return setPersist(trimmedKey);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LookupResult setStringList(Object key, List<String> listValue) {
|
||||||
|
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();
|
return LookupResult.empty();
|
||||||
} finally {
|
} finally {
|
||||||
time.stop();
|
time.stop();
|
||||||
@ -194,7 +407,7 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
|
|||||||
.redisHost("127.0.0.1")
|
.redisHost("127.0.0.1")
|
||||||
.redisPort(6379)
|
.redisPort(6379)
|
||||||
.redisDB(0)
|
.redisDB(0)
|
||||||
.redisKeyTTL(86400)
|
.redisKeyTTL(-1)
|
||||||
.redisUsername("")
|
.redisUsername("")
|
||||||
.redisPassword("")
|
.redisPassword("")
|
||||||
.build();
|
.build();
|
||||||
@ -204,11 +417,12 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
|
|||||||
|
|
||||||
|
|
||||||
@AutoValue
|
@AutoValue
|
||||||
|
@WithBeanGetter
|
||||||
@JsonAutoDetect
|
@JsonAutoDetect
|
||||||
@JsonDeserialize(builder = RedisLookupDataAdapter.Config.Builder.class)
|
@JsonDeserialize(builder = AutoValue_RedisLookupDataAdapter_Config.Builder.class)
|
||||||
@JsonTypeName(NAME)
|
@JsonTypeName(NAME)
|
||||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
public abstract static class Config implements LookupDataAdapterConfiguration {
|
public static abstract class Config implements LookupDataAdapterConfiguration {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@JsonProperty(TYPE_FIELD)
|
@JsonProperty(TYPE_FIELD)
|
||||||
@ -256,11 +470,6 @@ public class RedisLookupDataAdapter extends LookupDataAdapter {
|
|||||||
|
|
||||||
@AutoValue.Builder
|
@AutoValue.Builder
|
||||||
public abstract static class Builder {
|
public abstract static class Builder {
|
||||||
@JsonCreator
|
|
||||||
public static Builder create() {
|
|
||||||
return Config.builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty(TYPE_FIELD)
|
@JsonProperty(TYPE_FIELD)
|
||||||
public abstract Builder type(String type);
|
public abstract Builder type(String type);
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ import org.graylog2.plugin.lookup.LookupResult;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
public class RedisLookupPluginFunction extends LookupTableFunction<GenericLookupResult> {
|
public class RedisLookupPluginFunction extends LookupTableFunction<GenericLookupResult> {
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ public class RedisLookupPluginFunction extends LookupTableFunction<GenericLookup
|
|||||||
public FunctionDescriptor<GenericLookupResult> descriptor() {
|
public FunctionDescriptor<GenericLookupResult> descriptor() {
|
||||||
return FunctionDescriptor.<GenericLookupResult>builder()
|
return FunctionDescriptor.<GenericLookupResult>builder()
|
||||||
.name(NAME)
|
.name(NAME)
|
||||||
.description("Match a key into Redis instance and return value")
|
.description("Match a key into Redis instance and return value. Do not use, prefer standard 'lookup_*' functions")
|
||||||
.params(keyParam)
|
.params(keyParam)
|
||||||
.returnType(GenericLookupResult.class)
|
.returnType(GenericLookupResult.class)
|
||||||
.build();
|
.build();
|
||||||
|
@ -1 +1 @@
|
|||||||
in.nosd.redis.RedisLookupPluginPlugin
|
in.nosd.redis.RedisLookupPlugin
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
* along with this program. If not, see
|
* along with this program. If not, see
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||||
*/
|
*/
|
||||||
/* eslint-disable react/no-unescaped-entities, no-template-curly-in-string */
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
class RedisLookupAdapterDocumentation extends React.Component {
|
class RedisLookupAdapterDocumentation extends React.Component {
|
||||||
|
@ -82,7 +82,7 @@ class RedisLookupAdapterFieldSet extends React.Component {
|
|||||||
label="Redis key TTL"
|
label="Redis key TTL"
|
||||||
required
|
required
|
||||||
onChange={this.props.handleFormEvent}
|
onChange={this.props.handleFormEvent}
|
||||||
help={this.props.validationMessage('redis_ttl', 'Redis key TTL in seconds')}
|
help={this.props.validationMessage('redis_ttl', 'Redis key TTL in seconds. Set -1 to not expire keys')}
|
||||||
bsStyle={this.props.validationState('redis_ttl')}
|
bsStyle={this.props.validationState('redis_ttl')}
|
||||||
value={config.redis_ttl}
|
value={config.redis_ttl}
|
||||||
labelClassName="col-sm-3"
|
labelClassName="col-sm-3"
|
||||||
@ -112,5 +112,4 @@ class RedisLookupAdapterFieldSet extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default RedisLookupAdapterFieldSet;
|
export default RedisLookupAdapterFieldSet;
|
||||||
|
@ -34,6 +34,16 @@ class RedisLookupAdapterSummary extends React.Component {
|
|||||||
<dl>
|
<dl>
|
||||||
<dt>Redis host</dt>
|
<dt>Redis host</dt>
|
||||||
<dd>{config.redis_host || 'n/a'}</dd>
|
<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>
|
</dl>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,6 @@ const { PluginWebpackConfig } = require('graylog-web-plugin');
|
|||||||
const { loadBuildConfig } = 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
|
// 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.
|
// Here goes your additional webpack configuration.
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user