Compare commits
5 commits
Author | SHA1 | Date | |
---|---|---|---|
Mark Nellemann | 3ef961e44b | ||
Mark Nellemann | bd5e2634d5 | ||
Mark Nellemann | 1acdd6a93d | ||
Mark Nellemann | d39837861f | ||
Mark Nellemann | 422f1fbb71 |
108
README.md
108
README.md
|
@ -1,107 +1,3 @@
|
||||||
# Syslog Director
|
# Repository moved
|
||||||
|
|
||||||
All received messages are written to *stdout* and/or forwarded to remote logging destinations.
|
|
||||||
|
|
||||||
Supported incoming message formats are:
|
|
||||||
- Syslog RFC5424 - TCP and UDP
|
|
||||||
- Syslog RFC3164 (BSD) - TCP and UDP
|
|
||||||
- Graylog GELF - TCP and UDP (compressed & chunked)
|
|
||||||
|
|
||||||
Supported remote logging destinations are:
|
|
||||||
- Syslog (RFC5424 over UDP)
|
|
||||||
- Graylog (GELF over UDP)
|
|
||||||
- Grafana Loki (HTTP over TCP).
|
|
||||||
|
|
||||||
This software is free to use and is licensed under the [Apache 2.0 License](LICENSE).
|
|
||||||
|
|
||||||
![architecture](doc/syslogd.png)
|
|
||||||
|
|
||||||
Some of my other related projects are:
|
|
||||||
|
|
||||||
- [hmci](https://git.data.coop/nellemann/hmci) for agent-less monitoring of IBM Power servers
|
|
||||||
- [svci](https://git.data.coop/nellemann/svci) for monitoring IBM Spectrum Virtualize (Flashsystems / Storwize / SVC)
|
|
||||||
- [sysmon](https://git.data.coop/nellemann/sysmon) for monitoring all types of servers with a small Java agent
|
|
||||||
|
|
||||||
## Usage Instructions
|
|
||||||
|
|
||||||
- Install the syslogd package (*.deb* or *.rpm*) from [packages](https://git.data.coop/nellemann/-/packages/generic/syslogd/) or build from source.
|
|
||||||
|
|
||||||
```text
|
|
||||||
Usage: syslogd [-dhV] [--[no-]ansi] [--[no-]stdout] [--[no-]tcp] [--[no-]udp]
|
|
||||||
[-f=<protocol>] [-p=<num>] [--to-gelf=<uri>] [--to-loki=<url>]
|
|
||||||
[--to-syslog=<uri>]
|
|
||||||
-d, --debug Enable debugging [default: 'false'].
|
|
||||||
-f, --format=<protocol> Input format: RFC-5424, RFC-3164 or GELF [default:
|
|
||||||
RFC-3164].
|
|
||||||
-h, --help Show this help message and exit.
|
|
||||||
--[no-]ansi Output in ANSI colors [default: true].
|
|
||||||
--[no-]stdout Output messages to stdout [default: true].
|
|
||||||
--[no-]tcp Listen on TCP [default: true].
|
|
||||||
--[no-]udp Listen on UDP [default: true].
|
|
||||||
-p, --port=<num> Listening port [default: 1514].
|
|
||||||
--to-gelf=<uri> Forward to Graylog <udp://host:port>.
|
|
||||||
--to-loki=<url> Forward to Grafana Loki <http://host:port>.
|
|
||||||
--to-syslog=<uri> Forward to Syslog <udp://host:port> (RFC-5424).
|
|
||||||
-V, --version Print version information and exit.
|
|
||||||
```
|
|
||||||
|
|
||||||
The default syslog port (514) requires you to run syslogd as root / administrator.
|
|
||||||
Any port number above 1024 does not require privileges and can be selected with the *-p* or *--port* option.
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
Listening on the default syslog port:
|
|
||||||
|
|
||||||
```
|
|
||||||
java -jar /path/to/syslogd-x.y.z-all.jar --port 514
|
|
||||||
```
|
|
||||||
|
|
||||||
or, if installed as a *deb* or *rpm* package:
|
|
||||||
|
|
||||||
```
|
|
||||||
/opt/syslogd/bin/syslogd --port 514
|
|
||||||
```
|
|
||||||
|
|
||||||
Forwarding messages on to another log-system on a non-standard port.
|
|
||||||
|
|
||||||
```
|
|
||||||
java -jar /path/to/syslogd-x.y.z-all.jar --to-syslog udp://remotehost:514
|
|
||||||
```
|
|
||||||
|
|
||||||
Forwarding messages to a Graylog server in GELF format.
|
|
||||||
|
|
||||||
```
|
|
||||||
java -jar /path/to/syslogd-x.y.z-all.jar --to-gelf udp://remotehost:12201
|
|
||||||
```
|
|
||||||
|
|
||||||
Forwarding to a Grafana Loki server.
|
|
||||||
|
|
||||||
```
|
|
||||||
java -jar /path/to/syslogd-x.y.z-all.jar --to-loki http://remotehost:3100
|
|
||||||
```
|
|
||||||
|
|
||||||
If you don't want any output locally (only forwarding), you can use the ```--no-stdout``` flag.
|
|
||||||
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
### IBM AIX and VIO Servers
|
|
||||||
|
|
||||||
Syslog messages from AIX (and IBM Power Virtual I/O Servers) can be troublesome with some logging solutions. These can be received with
|
|
||||||
*syslogd* and then forwarded on to your preferred logging solution.
|
|
||||||
|
|
||||||
### Forwarding to Grafana Loki
|
|
||||||
|
|
||||||
Forwarding is currently done by making HTTP connections to the Loki API, which works fine for low volume messages, but might cause issues for large volume of messages.
|
|
||||||
|
|
||||||
## Development Notes
|
|
||||||
|
|
||||||
### Test Grafana Loki
|
|
||||||
|
|
||||||
Run Loki and Grafana in local containers to test.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker run --rm -d --name=loki -p 3100:3100 grafana/loki
|
|
||||||
docker run --rm -d --name=grafana --link loki:loki -p 3000:3000 grafana/grafana:7.1.3
|
|
||||||
```
|
|
||||||
|
|
||||||
|
Please visit [github.com/mnellemann/syslogd](https://github.com/mnellemann/syslogd)
|
16
build.gradle
16
build.gradle
|
@ -4,7 +4,7 @@ plugins {
|
||||||
id 'application'
|
id 'application'
|
||||||
id 'jacoco'
|
id 'jacoco'
|
||||||
id "net.nemerosa.versioning" version "2.15.1"
|
id "net.nemerosa.versioning" version "2.15.1"
|
||||||
id "com.netflix.nebula.ospackage" version "10.0.0"
|
id "com.netflix.nebula.ospackage" version "11.5.0"
|
||||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,12 +13,12 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
annotationProcessor 'info.picocli:picocli-codegen:4.7.0'
|
annotationProcessor 'info.picocli:picocli-codegen:4.7.5'
|
||||||
implementation 'info.picocli:picocli:4.7.0'
|
implementation 'info.picocli:picocli:4.7.5'
|
||||||
implementation 'org.slf4j:slf4j-api:2.0.6'
|
implementation 'org.slf4j:slf4j-api:2.0.9'
|
||||||
implementation 'org.slf4j:slf4j-simple:2.0.6'
|
implementation 'org.slf4j:slf4j-simple:2.0.9'
|
||||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.1'
|
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
|
||||||
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.1'
|
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2'
|
||||||
implementation 'org.apache.commons:commons-collections4:4.4'
|
implementation 'org.apache.commons:commons-collections4:4.4'
|
||||||
|
|
||||||
testImplementation 'org.spockframework:spock-core:2.3-groovy-3.0'
|
testImplementation 'org.spockframework:spock-core:2.3-groovy-3.0'
|
||||||
|
@ -38,7 +38,7 @@ test {
|
||||||
}
|
}
|
||||||
|
|
||||||
jacoco {
|
jacoco {
|
||||||
toolVersion = "0.8.8"
|
toolVersion = "0.8.10"
|
||||||
}
|
}
|
||||||
|
|
||||||
jacocoTestReport {
|
jacocoTestReport {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<mxfile host="drawio-plugin" modified="2022-12-07T07:21:50.025Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36" etag="0NRdR40T7b5zyLZSsQHk" version="20.5.3" type="embed"><diagram id="23iRSUPoRavnBvh4doch" name="Page-1"><mxGraphModel dx="1115" dy="620" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="10" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;curved=1;sketch=1;shadow=1;" parent="1" source="2" target="3" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="2" value="RFC--3164" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1"><mxGeometry x="100" y="40" width="120" height="60" as="geometry"/></mxCell><mxCell id="13" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="3" target="9" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="14" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="3" target="6" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="15" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="3" target="7" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="16" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="3" target="8" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="3" value="syslogd" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;sketch=1;rounded=1;shadow=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"><mxGeometry x="280" y="130" width="120" height="60" as="geometry"/></mxCell><mxCell id="11" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="4" target="3" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="4" value="RFC--5424" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1"><mxGeometry x="20" y="130" width="120" height="60" as="geometry"/></mxCell><mxCell id="12" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="5" target="3" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="5" value="GELF" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#f8cecc;strokeColor=#b85450;" parent="1" vertex="1"><mxGeometry x="130" y="223.5" width="120" height="60" as="geometry"/></mxCell><mxCell id="6" value="Syslog<br>RFC-5424" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1"><mxGeometry x="570" y="80" width="120" height="60" as="geometry"/></mxCell><mxCell id="7" value="Grafana Loki" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="1" vertex="1"><mxGeometry x="550" y="170" width="120" height="60" as="geometry"/></mxCell><mxCell id="8" value="Graylog" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1"><mxGeometry x="420" y="250" width="120" height="60" as="geometry"/></mxCell><mxCell id="9" value="Standard<br>Output" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;" parent="1" vertex="1"><mxGeometry x="410" y="30" width="120" height="60" as="geometry"/></mxCell></root></mxGraphModel></diagram></mxfile>
|
<mxfile host="drawio-plugin" modified="2023-02-05T13:04:08.556Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36" etag="__kq9uG-1g-sjP8t85Xj" version="20.5.3" type="embed"><diagram id="23iRSUPoRavnBvh4doch" name="Page-1"><mxGraphModel dx="809" dy="749" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="10" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;curved=1;sketch=1;shadow=1;" parent="1" source="2" target="3" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="2" value="Syslog<br>RFC--3164" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1"><mxGeometry x="50" y="90" width="120" height="60" as="geometry"/></mxCell><mxCell id="13" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="3" target="9" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="14" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="3" target="6" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="15" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="3" target="7" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="16" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="3" target="8" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="3" value="syslogd" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;sketch=1;rounded=1;shadow=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"><mxGeometry x="280" y="130" width="120" height="60" as="geometry"/></mxCell><mxCell id="11" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="4" target="3" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="4" value="Syslog<br>RFC--5424" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1"><mxGeometry x="40" y="180" width="120" height="60" as="geometry"/></mxCell><mxCell id="12" style="edgeStyle=orthogonalEdgeStyle;curved=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;shadow=1;" parent="1" source="5" target="3" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="5" value="GELF" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#f8cecc;strokeColor=#b85450;" parent="1" vertex="1"><mxGeometry x="120" y="260" width="120" height="60" as="geometry"/></mxCell><mxCell id="6" value="Syslog<br>RFC-5424" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1"><mxGeometry x="570" y="80" width="120" height="60" as="geometry"/></mxCell><mxCell id="7" value="Grafana Loki" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="1" vertex="1"><mxGeometry x="550" y="170" width="120" height="60" as="geometry"/></mxCell><mxCell id="8" value="Graylog" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1"><mxGeometry x="420" y="250" width="120" height="60" as="geometry"/></mxCell><mxCell id="9" value="Standard<br>Output" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;" parent="1" vertex="1"><mxGeometry x="410" y="30" width="120" height="60" as="geometry"/></mxCell><mxCell id="17" value="Standard<br>Input" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;shadow=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;" vertex="1" parent="1"><mxGeometry x="180" y="30" width="90" height="60" as="geometry"/></mxCell><mxCell id="19" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;curved=1;sketch=1;shadow=1;" edge="1" parent="1" source="17" target="3"><mxGeometry relative="1" as="geometry"><mxPoint x="190" y="110" as="sourcePoint"/><mxPoint x="300" y="170" as="targetPoint"/></mxGeometry></mxCell></root></mxGraphModel></diagram></mxfile>
|
BIN
doc/syslogd.png
BIN
doc/syslogd.png
Binary file not shown.
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 96 KiB |
|
@ -1,5 +1,5 @@
|
||||||
id = syslogd
|
id = syslogd
|
||||||
name = syslogd
|
name = syslogd
|
||||||
group = biz.nellemann.syslogd
|
group = biz.nellemann.syslogd
|
||||||
version = 1.3.3
|
version = 1.3.5
|
||||||
description = "Syslog Director"
|
description = "Syslog Director"
|
||||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -15,16 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package biz.nellemann.syslogd;
|
package biz.nellemann.syslogd;
|
||||||
|
|
||||||
import biz.nellemann.syslogd.msg.SyslogMessage;
|
|
||||||
import biz.nellemann.syslogd.net.*;
|
|
||||||
import biz.nellemann.syslogd.parser.GelfParser;
|
|
||||||
import biz.nellemann.syslogd.parser.SyslogParser;
|
|
||||||
import biz.nellemann.syslogd.parser.SyslogParserRfc3164;
|
|
||||||
import biz.nellemann.syslogd.parser.SyslogParserRfc5424;
|
|
||||||
|
|
||||||
import picocli.CommandLine;
|
|
||||||
import picocli.CommandLine.Command;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -34,6 +24,19 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import biz.nellemann.syslogd.msg.SyslogMessage;
|
||||||
|
import biz.nellemann.syslogd.net.GelfClient;
|
||||||
|
import biz.nellemann.syslogd.net.LokiClient;
|
||||||
|
import biz.nellemann.syslogd.net.TcpServer;
|
||||||
|
import biz.nellemann.syslogd.net.UdpClient;
|
||||||
|
import biz.nellemann.syslogd.net.UdpServer;
|
||||||
|
import biz.nellemann.syslogd.parser.GelfParser;
|
||||||
|
import biz.nellemann.syslogd.parser.SyslogParser;
|
||||||
|
import biz.nellemann.syslogd.parser.SyslogParserRfc3164;
|
||||||
|
import biz.nellemann.syslogd.parser.SyslogParserRfc5424;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
import picocli.CommandLine.Command;
|
||||||
|
|
||||||
@Command(name = "syslogd",
|
@Command(name = "syslogd",
|
||||||
mixinStandardHelpOptions = true,
|
mixinStandardHelpOptions = true,
|
||||||
versionProvider = biz.nellemann.syslogd.VersionProvider.class)
|
versionProvider = biz.nellemann.syslogd.VersionProvider.class)
|
||||||
|
@ -58,6 +61,9 @@ public class Application implements Callable<Integer>, LogReceiveListener {
|
||||||
@CommandLine.Option(names = "--no-stdout", negatable = true, description = "Output messages to stdout [default: true].", defaultValue = "true")
|
@CommandLine.Option(names = "--no-stdout", negatable = true, description = "Output messages to stdout [default: true].", defaultValue = "true")
|
||||||
private boolean stdout;
|
private boolean stdout;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = "--no-stdin", negatable = true, description = "Forward messages from stdin [default: true].", defaultValue = "true")
|
||||||
|
private boolean stdin;
|
||||||
|
|
||||||
@CommandLine.Option(names = {"-f", "--format"}, description = "Input format: RFC-5424, RFC-3164 or GELF [default: RFC-3164].", defaultValue = "RFC-3164")
|
@CommandLine.Option(names = {"-f", "--format"}, description = "Input format: RFC-5424, RFC-3164 or GELF [default: RFC-3164].", defaultValue = "RFC-3164")
|
||||||
private String protocol;
|
private String protocol;
|
||||||
|
|
||||||
|
@ -77,7 +83,6 @@ public class Application implements Callable<Integer>, LogReceiveListener {
|
||||||
@Override
|
@Override
|
||||||
public Integer call() throws IOException {
|
public Integer call() throws IOException {
|
||||||
|
|
||||||
|
|
||||||
if(enableDebug) {
|
if(enableDebug) {
|
||||||
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "DEBUG");
|
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "DEBUG");
|
||||||
}
|
}
|
||||||
|
@ -115,6 +120,12 @@ public class Application implements Callable<Integer>, LogReceiveListener {
|
||||||
t.start();
|
t.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(stdin) {
|
||||||
|
InputReader inputReader = new InputReader(System.in, protocol);
|
||||||
|
inputReader.addEventListener(this);
|
||||||
|
inputReader.start();
|
||||||
|
}
|
||||||
|
|
||||||
if(udpServer) {
|
if(udpServer) {
|
||||||
UdpServer udpServer = new UdpServer(port);
|
UdpServer udpServer = new UdpServer(port);
|
||||||
udpServer.addEventListener(this);
|
udpServer.addEventListener(this);
|
||||||
|
@ -144,7 +155,7 @@ public class Application implements Callable<Integer>, LogReceiveListener {
|
||||||
|
|
||||||
if(msg != null) {
|
if(msg != null) {
|
||||||
|
|
||||||
if(logForwardListeners.size() > 0) {
|
if(!logForwardListeners.isEmpty()) {
|
||||||
sendForwardEvent(msg);
|
sendForwardEvent(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
70
src/main/java/biz/nellemann/syslogd/InputReader.java
Normal file
70
src/main/java/biz/nellemann/syslogd/InputReader.java
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package biz.nellemann.syslogd;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import biz.nellemann.syslogd.msg.SyslogMessage;
|
||||||
|
|
||||||
|
public class InputReader extends Thread {
|
||||||
|
|
||||||
|
private final Scanner input;
|
||||||
|
private final String protocol;
|
||||||
|
|
||||||
|
public InputReader(InputStream inputStream, String protocol) {
|
||||||
|
input = new Scanner(inputStream);
|
||||||
|
this.protocol = protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
while(input.hasNextLine()) {
|
||||||
|
SyslogMessage msg = new SyslogMessage(input.nextLine());
|
||||||
|
msg.hostname = "localhost";
|
||||||
|
msg.application = "syslogd";
|
||||||
|
|
||||||
|
String payload;
|
||||||
|
if(protocol.equalsIgnoreCase("GELF"))
|
||||||
|
payload = SyslogPrinter.toGelf(msg);
|
||||||
|
else if (protocol.equalsIgnoreCase("RFC-5424")) {
|
||||||
|
payload = SyslogPrinter.toRfc5424(msg);
|
||||||
|
} else {
|
||||||
|
payload = SyslogPrinter.toRfc3164(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendEvent(payload);
|
||||||
|
}
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private synchronized void sendEvent(String text) {
|
||||||
|
LogReceiveEvent event = new LogReceiveEvent( this, text);
|
||||||
|
for (LogReceiveListener eventListener : eventListeners) {
|
||||||
|
eventListener.onLogEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event Listener Configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected List<LogReceiveListener> eventListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
public synchronized void addEventListener(LogReceiveListener listener ) {
|
||||||
|
eventListeners.add( listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void addEventListener(List<LogReceiveListener> listeners ) {
|
||||||
|
eventListeners.addAll(listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void removeEventListener( LogReceiveListener l ) {
|
||||||
|
eventListeners.remove( l );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -23,15 +23,13 @@ import java.util.EventObject;
|
||||||
public class LogReceiveEvent extends EventObject {
|
public class LogReceiveEvent extends EventObject {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
//private final String message;
|
|
||||||
private final DatagramPacket packet;
|
private final DatagramPacket packet;
|
||||||
|
|
||||||
/*
|
|
||||||
public LogReceiveEvent(final Object source, final String message ) {
|
public LogReceiveEvent(final Object source, final String message ) {
|
||||||
super( source );
|
super( source );
|
||||||
this.message = message;
|
byte[] bytes = message.getBytes();
|
||||||
|
this.packet = new DatagramPacket(bytes, bytes.length);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
public LogReceiveEvent(final Object source, final DatagramPacket packet) {
|
public LogReceiveEvent(final Object source, final DatagramPacket packet) {
|
||||||
super( source );
|
super( source );
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class SyslogMessage {
|
||||||
|
|
||||||
// The TIMESTAMP field is a formalized timestamp derived from [RFC3339].
|
// The TIMESTAMP field is a formalized timestamp derived from [RFC3339].
|
||||||
@JsonProperty("timestamp") // 1670357783.694 - in GELF: seconds since UNIX epoch with optional decimal places for milliseconds
|
@JsonProperty("timestamp") // 1670357783.694 - in GELF: seconds since UNIX epoch with optional decimal places for milliseconds
|
||||||
public Instant timestamp;
|
public Instant timestamp = Instant.now();
|
||||||
|
|
||||||
// The HOSTNAME field identifies the machine that originally sent the syslog message.
|
// The HOSTNAME field identifies the machine that originally sent the syslog message.
|
||||||
@JsonProperty("host")
|
@JsonProperty("host")
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
package biz.nellemann.syslogd.net;
|
package biz.nellemann.syslogd.net;
|
||||||
|
|
||||||
import biz.nellemann.syslogd.LogForwardEvent;
|
|
||||||
import biz.nellemann.syslogd.SyslogPrinter;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import biz.nellemann.syslogd.LogForwardEvent;
|
||||||
|
import biz.nellemann.syslogd.SyslogPrinter;
|
||||||
|
|
||||||
public class GelfClient extends UdpClient {
|
public class GelfClient extends UdpClient {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(GelfClient.class);
|
private final static Logger log = LoggerFactory.getLogger(GelfClient.class);
|
||||||
|
|
|
@ -15,19 +15,22 @@
|
||||||
*/
|
*/
|
||||||
package biz.nellemann.syslogd.net;
|
package biz.nellemann.syslogd.net;
|
||||||
|
|
||||||
import biz.nellemann.syslogd.LogForwardEvent;
|
|
||||||
import biz.nellemann.syslogd.LogForwardListener;
|
|
||||||
import biz.nellemann.syslogd.SyslogPrinter;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.*;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import biz.nellemann.syslogd.LogForwardEvent;
|
||||||
|
import biz.nellemann.syslogd.LogForwardListener;
|
||||||
|
import biz.nellemann.syslogd.SyslogPrinter;
|
||||||
|
|
||||||
public class LokiClient implements LogForwardListener, Runnable {
|
public class LokiClient implements LogForwardListener, Runnable {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(LokiClient.class);
|
private final static Logger log = LoggerFactory.getLogger(LokiClient.class);
|
||||||
|
@ -84,7 +87,7 @@ public class LokiClient implements LogForwardListener, Runnable {
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
send(blockingQueue.take());
|
send(blockingQueue.take());
|
||||||
} catch (Exception e) {
|
} catch (MalformedURLException | InterruptedException e) {
|
||||||
log.warn(e.getMessage());
|
log.warn(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package biz.nellemann.syslogd.net;
|
package biz.nellemann.syslogd.net;
|
||||||
|
|
||||||
import biz.nellemann.syslogd.LogReceiveEvent;
|
|
||||||
import biz.nellemann.syslogd.LogReceiveListener;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.DatagramPacket;
|
import java.net.DatagramPacket;
|
||||||
import java.net.DatagramSocket;
|
import java.net.DatagramSocket;
|
||||||
|
@ -27,6 +24,9 @@ import java.util.List;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import biz.nellemann.syslogd.LogReceiveEvent;
|
||||||
|
import biz.nellemann.syslogd.LogReceiveListener;
|
||||||
|
|
||||||
public class UdpServer extends Thread {
|
public class UdpServer extends Thread {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(UdpServer.class);
|
private final static Logger log = LoggerFactory.getLogger(UdpServer.class);
|
||||||
|
@ -38,6 +38,7 @@ public class UdpServer extends Thread {
|
||||||
socket = new DatagramSocket(port);
|
socket = new DatagramSocket(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
byte[] buf = new byte[8192];
|
byte[] buf = new byte[8192];
|
||||||
|
@ -48,7 +49,7 @@ public class UdpServer extends Thread {
|
||||||
socket.receive(packet);
|
socket.receive(packet);
|
||||||
//String packetData = new String(packet.getData(), packet.getOffset(), packet.getLength(), StandardCharsets.UTF_8);
|
//String packetData = new String(packet.getData(), packet.getOffset(), packet.getLength(), StandardCharsets.UTF_8);
|
||||||
sendEvent(packet);
|
sendEvent(packet);
|
||||||
} catch (Exception e) {
|
} catch (IOException e) {
|
||||||
log.error("run() - error: {}", e.getMessage());
|
log.error("run() - error: {}", e.getMessage());
|
||||||
listen = false;
|
listen = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
package biz.nellemann.syslogd.parser;
|
package biz.nellemann.syslogd.parser;
|
||||||
|
|
||||||
import biz.nellemann.syslogd.msg.SyslogMessage;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
|
||||||
import org.apache.commons.collections4.map.PassiveExpiringMap;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.map.PassiveExpiringMap;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
|
||||||
|
import biz.nellemann.syslogd.msg.SyslogMessage;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
For more information about the GELF format, visit: https://go2docs.graylog.org/5-0/getting_in_log_data/gelf.html
|
For more information about the GELF format, visit: https://go2docs.graylog.org/5-0/getting_in_log_data/gelf.html
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -8,6 +8,10 @@ public class JsonUtil {
|
||||||
|
|
||||||
public static String encode(String input) {
|
public static String encode(String input) {
|
||||||
|
|
||||||
|
if(input == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder output = new StringBuilder();
|
StringBuilder output = new StringBuilder();
|
||||||
|
|
||||||
for (int i = 0; i < input.length(); i++) {
|
for (int i = 0; i < input.length(); i++) {
|
||||||
|
|
|
@ -15,15 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package biz.nellemann.syslogd.parser;
|
package biz.nellemann.syslogd.parser;
|
||||||
|
|
||||||
import biz.nellemann.syslogd.msg.SyslogMessage;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.zip.DataFormatException;
|
import java.util.zip.DataFormatException;
|
||||||
import java.util.zip.Inflater;
|
import java.util.zip.Inflater;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import biz.nellemann.syslogd.msg.SyslogMessage;
|
||||||
|
|
||||||
public abstract class SyslogParser {
|
public abstract class SyslogParser {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(SyslogParser.class);
|
private final static Logger log = LoggerFactory.getLogger(SyslogParser.class);
|
||||||
|
@ -73,7 +74,7 @@ public abstract class SyslogParser {
|
||||||
Inflater decompressor = new Inflater();
|
Inflater decompressor = new Inflater();
|
||||||
decompressor.setInput(data, 0, data.length);
|
decompressor.setInput(data, 0, data.length);
|
||||||
//byte[] result = new byte[data.length * 2];
|
//byte[] result = new byte[data.length * 2];
|
||||||
int resultLength = decompressor.inflate(result);
|
decompressor.inflate(result);
|
||||||
decompressor.end();
|
decompressor.end();
|
||||||
|
|
||||||
// Decode the bytes into a String
|
// Decode the bytes into a String
|
||||||
|
|
|
@ -15,18 +15,21 @@
|
||||||
*/
|
*/
|
||||||
package biz.nellemann.syslogd.parser;
|
package biz.nellemann.syslogd.parser;
|
||||||
|
|
||||||
import biz.nellemann.syslogd.msg.Facility;
|
import java.time.Instant;
|
||||||
import biz.nellemann.syslogd.msg.Severity;
|
import java.time.OffsetDateTime;
|
||||||
import biz.nellemann.syslogd.msg.SyslogMessage;
|
import java.time.ZoneId;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.time.*;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import biz.nellemann.syslogd.msg.Facility;
|
||||||
|
import biz.nellemann.syslogd.msg.Severity;
|
||||||
|
import biz.nellemann.syslogd.msg.SyslogMessage;
|
||||||
|
|
||||||
public class SyslogParserRfc3164 extends SyslogParser {
|
public class SyslogParserRfc3164 extends SyslogParser {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(SyslogParserRfc3164.class);
|
private final static Logger log = LoggerFactory.getLogger(SyslogParserRfc3164.class);
|
||||||
|
@ -89,6 +92,7 @@ public class SyslogParserRfc3164 extends SyslogParser {
|
||||||
* @param dateString
|
* @param dateString
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Instant parseTimestamp(String dateString) {
|
public Instant parseTimestamp(String dateString) {
|
||||||
|
|
||||||
// We need to add current year to parse date correctly
|
// We need to add current year to parse date correctly
|
||||||
|
|
|
@ -15,20 +15,21 @@
|
||||||
*/
|
*/
|
||||||
package biz.nellemann.syslogd.parser;
|
package biz.nellemann.syslogd.parser;
|
||||||
|
|
||||||
import biz.nellemann.syslogd.msg.Severity;
|
|
||||||
import biz.nellemann.syslogd.msg.Facility;
|
|
||||||
import biz.nellemann.syslogd.msg.SyslogMessage;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.*;
|
import java.time.Instant;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import biz.nellemann.syslogd.msg.Facility;
|
||||||
|
import biz.nellemann.syslogd.msg.Severity;
|
||||||
|
import biz.nellemann.syslogd.msg.SyslogMessage;
|
||||||
|
|
||||||
public class SyslogParserRfc5424 extends SyslogParser {
|
public class SyslogParserRfc5424 extends SyslogParser {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(SyslogParserRfc5424.class);
|
private final static Logger log = LoggerFactory.getLogger(SyslogParserRfc5424.class);
|
||||||
|
@ -98,6 +99,7 @@ public class SyslogParserRfc5424 extends SyslogParser {
|
||||||
* @param dateString
|
* @param dateString
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Instant parseTimestamp(String dateString) {
|
public Instant parseTimestamp(String dateString) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue