Skip to content

Commit 70c36a4

Browse files
authored
Add support for "Event" eventType (#83)
* Implement WindowsEventType and its tests * Add WindowsEventType to NLFPlugin.syslogMessage
1 parent 74686a2 commit 70c36a4

6 files changed

Lines changed: 551 additions & 0 deletions

File tree

src/main/java/com/teragrep/nlf_01/NLFPlugin.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ else if (jsonObject.getString("Type").equals("ContainerAppConsoleLogs")) {
119119
else if (jsonObject.getString("Type").equals("DataverseActivity")) {
120120
eventTypes.add(new DataverseActivityType(parsedEvent, realHostname, componentNameForPartitions));
121121
}
122+
else if (jsonObject.getString("Type").equals("Event")) {
123+
eventTypes.add(new WindowsEventType(parsedEvent, realHostname, componentNameForPartitions));
124+
}
122125
else if (jsonObject.getString("Type").equals("FunctionAppLogs")) {
123126
eventTypes.add(new FunctionAppLogsType(parsedEvent, realHostname, componentNameForPartitions));
124127
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Teragrep Neon log format plugin for AKV_01
3+
* Copyright (C) 2025 Suomen Kanuuna Oy
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*
18+
*
19+
* Additional permission under GNU Affero General Public License version 3
20+
* section 7
21+
*
22+
* If you modify this Program, or any covered work, by linking or combining it
23+
* with other code, such other code is not for that reason alone subject to any
24+
* of the requirements of the GNU Affero GPL version 3 as long as this Program
25+
* is the same Program as licensed from Suomen Kanuuna Oy without any additional
26+
* modifications.
27+
*
28+
* Supplemented terms under GNU Affero General Public License version 3
29+
* section 7
30+
*
31+
* Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified
32+
* versions must be marked as "Modified version of" The Program.
33+
*
34+
* Names of the licensors and authors may not be used for publicity purposes.
35+
*
36+
* No rights are granted for use of trade names, trademarks, or service marks
37+
* which are in The Program if any.
38+
*
39+
* Licensee must indemnify licensors and authors for any liability that these
40+
* contractual assumptions impose on licensors and authors.
41+
*
42+
* To the extent this program is licensed as part of the Commercial versions of
43+
* Teragrep, the applicable Commercial License may apply to this file if you as
44+
* a licensee so wish it.
45+
*/
46+
package com.teragrep.nlf_01.types;
47+
48+
import com.teragrep.akv_01.event.ParsedEvent;
49+
import com.teragrep.akv_01.plugin.PluginException;
50+
import com.teragrep.nlf_01.util.ASCIIString;
51+
import com.teragrep.nlf_01.util.DefaultSDElements;
52+
import com.teragrep.nlf_01.util.MD5Hash;
53+
import com.teragrep.nlf_01.util.ResourceId;
54+
import com.teragrep.nlf_01.util.SDElements;
55+
import com.teragrep.nlf_01.util.ValidKey;
56+
import com.teragrep.nlf_01.util.ValidRFC5424AppName;
57+
import com.teragrep.nlf_01.util.ValidRFC5424Hostname;
58+
import com.teragrep.nlf_01.util.ValidRFC5424Timestamp;
59+
import com.teragrep.nlf_01.util.ValidStringKey;
60+
import com.teragrep.rlo_14.Facility;
61+
import com.teragrep.rlo_14.SDElement;
62+
import com.teragrep.rlo_14.Severity;
63+
import jakarta.json.JsonObject;
64+
import java.util.Set;
65+
66+
public final class WindowsEventType implements EventType {
67+
68+
private final ParsedEvent parsedEvent;
69+
private final String realHostname;
70+
private final String componentNameForPartitions;
71+
72+
public WindowsEventType(
73+
final ParsedEvent parsedEvent,
74+
final String realHostname,
75+
final String componentNameForPartitions
76+
) {
77+
this.parsedEvent = parsedEvent;
78+
this.realHostname = realHostname;
79+
this.componentNameForPartitions = componentNameForPartitions;
80+
}
81+
82+
@Override
83+
public Severity severity() {
84+
return Severity.NOTICE;
85+
}
86+
87+
@Override
88+
public Facility facility() {
89+
return Facility.AUDIT;
90+
}
91+
92+
@Override
93+
public String hostname() throws PluginException {
94+
final JsonObject record = parsedEvent.asJsonStructure().asJsonObject();
95+
96+
final ValidKey<String> validKey = new ValidStringKey(record, "_Internal_WorkspaceResourceId");
97+
98+
final String resourceId = validKey.value();
99+
100+
return new ValidRFC5424Hostname(
101+
"md5-".concat(new MD5Hash(resourceId).md5().concat("-").concat(new ASCIIString(new ResourceId(resourceId).resourceName()).withNonAsciiCharsRemoved()))
102+
).hostnameWithInvalidCharsRemoved();
103+
104+
}
105+
106+
@Override
107+
public String appName() throws PluginException {
108+
final JsonObject record = parsedEvent.asJsonStructure().asJsonObject();
109+
110+
return new ValidRFC5424AppName(new ValidStringKey(record, "Source").value()).appName();
111+
}
112+
113+
@Override
114+
public long timestamp() throws PluginException {
115+
final JsonObject record = parsedEvent.asJsonStructure().asJsonObject();
116+
117+
final ValidKey<String> validKey = new ValidStringKey(record, "TimeGenerated");
118+
119+
return new ValidRFC5424Timestamp(validKey.value()).validTimestamp();
120+
}
121+
122+
@Override
123+
public Set<SDElement> sdElements() throws PluginException {
124+
final SDElements defaultSDElements = new DefaultSDElements(
125+
parsedEvent,
126+
realHostname,
127+
this.getClass(),
128+
componentNameForPartitions
129+
);
130+
final Set<SDElement> elems = defaultSDElements.sdElements();
131+
132+
final JsonObject mainObject = parsedEvent.asJsonStructure().asJsonObject();
133+
134+
final ValidKey<String> validKey = new ValidStringKey(mainObject, "_ResourceId");
135+
final String resourceId = validKey.value();
136+
137+
// Append the origin of this event to the DefaultSDElements
138+
elems.add(new SDElement("origin@48577").addSDParam("_ResourceId", resourceId));
139+
140+
return elems;
141+
}
142+
143+
@Override
144+
public String msgId() throws PluginException {
145+
final String sequenceNumber;
146+
if (!parsedEvent.systemProperties().isStub()) {
147+
sequenceNumber = String.valueOf(parsedEvent.systemProperties().asMap().getOrDefault("SequenceNumber", ""));
148+
}
149+
else {
150+
sequenceNumber = "";
151+
}
152+
return sequenceNumber;
153+
}
154+
155+
@Override
156+
public String msg() throws PluginException {
157+
return parsedEvent.asString();
158+
}
159+
}

src/test/java/com/teragrep/nlf_01/NLFPluginTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
import com.teragrep.nlf_01.types.PowerPlatformAdminActivityType;
8080
import com.teragrep.nlf_01.types.SQLSecurityAuditEventsType;
8181
import com.teragrep.nlf_01.types.SyslogType;
82+
import com.teragrep.nlf_01.types.WindowsEventType;
8283
import com.teragrep.nlf_01.util.Sourceable;
8384
import com.teragrep.rlo_14.SDElement;
8485
import com.teragrep.rlo_14.SDParam;
@@ -504,6 +505,39 @@ void dataverseActivityType() {
504505
Assertions.assertTrue(sdElementMap.get("aer_event@48577").containsKey("properties"));
505506
}
506507

508+
@Test
509+
void windowsEventTypeTest() {
510+
final String json = Assertions
511+
.assertDoesNotThrow(() -> Files.readString(Paths.get("src/test/resources/windows_event.json")));
512+
final ParsedEvent parsedEvent = new ParsedEventFactory(
513+
new UnparsedEventImpl(json, new EventPartitionContextImpl(new HashMap<>()), new EventPropertiesImpl(new HashMap<>()), new EventSystemPropertiesImpl(new HashMap<>()), new EnqueuedTimeImpl("2020-01-01T00:00:00"), new EventOffsetImpl("0"))
514+
).parsedEvent();
515+
516+
final NLFPlugin plugin = new NLFPlugin(new FakeSourceable());
517+
final List<SyslogMessage> syslogMessages = Assertions
518+
.assertDoesNotThrow(() -> plugin.syslogMessage(parsedEvent));
519+
Assertions.assertEquals(1, syslogMessages.size());
520+
521+
final SyslogMessage syslogMessage = syslogMessages.get(0);
522+
Assertions.assertEquals("md5-0ded52ef915af563e25778bf26b0f129-resourceName", syslogMessage.getHostname());
523+
Assertions.assertEquals("Windows", syslogMessage.getAppName());
524+
Assertions.assertEquals("2020-01-01T01:02:34.567Z", syslogMessage.getTimestamp());
525+
Assertions.assertEquals(json, syslogMessage.getMsg());
526+
final Map<String, Map<String, String>> sdElementMap = syslogMessage
527+
.getSDElements()
528+
.stream()
529+
.collect(Collectors.toMap((SDElement::getSdID), (sdElem) -> sdElem.getSdParams().stream().collect(Collectors.toMap(SDParam::getParamName, SDParam::getParamValue))));
530+
531+
Assertions
532+
.assertEquals(
533+
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}",
534+
sdElementMap.get("origin@48577").get("_ResourceId")
535+
);
536+
Assertions
537+
.assertEquals(WindowsEventType.class.getSimpleName(), sdElementMap.get("nlf_01@48577").get("eventType"));
538+
Assertions.assertTrue(sdElementMap.get("aer_event@48577").containsKey("properties"));
539+
}
540+
507541
@Test
508542
void adfActivityRunType() {
509543
final String json = Assertions

0 commit comments

Comments
 (0)