99import io .streamthoughts .kafka .connect .filepulse .config .CommonFilterConfig ;
1010import io .streamthoughts .kafka .connect .filepulse .data .TypedStruct ;
1111import io .streamthoughts .kafka .connect .transform .GrokConfig ;
12+ import java .util .Arrays ;
1213import java .util .HashMap ;
1314import java .util .List ;
1415import java .util .Map ;
@@ -86,4 +87,116 @@ public void testGivenPatternWithNoGroupWhenCapturedNameOnlyIsFalse() {
8687 Assert .assertEquals ("INFO" , struct .getString ("LOGLEVEL" ));
8788 Assert .assertEquals ("a dummy log message" , struct .getString ("GREEDYDATA" ));
8889 }
90+
91+ @ Test
92+ public void testGivenTargetField () {
93+ configs .put (GrokConfig .GROK_PATTERN_CONFIG , GROK_NAMED_CAPTURED_PATTERN );
94+ configs .put ("target" , "logData" );
95+ filter .configure (configs , alias -> null );
96+ List <TypedStruct > results = filter .apply (null , DATA , false ).collect ();
97+
98+ Assert .assertEquals (1 , results .size ());
99+ TypedStruct struct = results .get (0 );
100+
101+ // Original message field should still exist
102+ Assert .assertEquals (INPUT , struct .getString ("message" ));
103+
104+ // Extracted data should be in the target field
105+ Assert .assertTrue (struct .exists ("logData" ));
106+ TypedStruct logData = struct .getStruct ("logData" );
107+ Assert .assertNotNull (logData );
108+ Assert .assertEquals ("1970-01-01 00:00:00,000" , logData .getString ("timestamp" ));
109+ Assert .assertEquals ("INFO" , logData .getString ("level" ));
110+ // Inside the target struct, message is just the extracted value (no merging with original)
111+ Assert .assertEquals ("a dummy log message" , logData .getString ("message" ));
112+ }
113+
114+ @ Test
115+ public void testGivenTargetFieldWithOverwrite () {
116+ configs .put (GrokConfig .GROK_PATTERN_CONFIG , GROK_NAMED_CAPTURED_PATTERN );
117+ configs .put ("target" , "parsed" );
118+ configs .put (CommonFilterConfig .FILTER_OVERWRITE_CONFIG , "message" );
119+ filter .configure (configs , alias -> null );
120+ List <TypedStruct > results = filter .apply (null , DATA , false ).collect ();
121+
122+ Assert .assertEquals (1 , results .size ());
123+ TypedStruct struct = results .get (0 );
124+
125+ // Original message field should still exist
126+ Assert .assertEquals (INPUT , struct .getString ("message" ));
127+
128+ // Extracted data should be in the target field with overwrite applied
129+ Assert .assertTrue (struct .exists ("parsed" ));
130+ TypedStruct parsed = struct .getStruct ("parsed" );
131+ Assert .assertNotNull (parsed );
132+ Assert .assertEquals ("1970-01-01 00:00:00,000" , parsed .getString ("timestamp" ));
133+ Assert .assertEquals ("INFO" , parsed .getString ("level" ));
134+ // With overwrite, message should be a string, not an array
135+ Assert .assertEquals ("a dummy log message" , parsed .getString ("message" ));
136+ }
137+
138+ @ Test
139+ public void testGivenArraySourceWithNestedTarget () {
140+ TypedStruct record = TypedStruct .create ();
141+ record .put (
142+ "logData" ,
143+ Arrays .asList (
144+ "1970-01-01 00:00:00,000 INFO first log message" ,
145+ "1970-01-01 00:00:01,000 WARN second log message" ,
146+ "1970-01-01 00:00:02,000 ERROR third log message" ));
147+
148+ configs .put (GrokConfig .GROK_PATTERN_CONFIG , GROK_NAMED_CAPTURED_PATTERN );
149+ configs .put (CommonFilterConfig .FILTER_SOURCE_FIELD_CONFIG , "logData" );
150+ configs .put ("target" , "parsed.records" );
151+ filter .configure (configs , alias -> null );
152+
153+ List <TypedStruct > results = filter .apply (null , record , false ).collect ();
154+ Assert .assertEquals (1 , results .size ());
155+ TypedStruct struct = results .get (0 );
156+
157+ Assert .assertTrue (struct .exists ("parsed" ));
158+ TypedStruct parsed = struct .getStruct ("parsed" );
159+ Assert .assertNotNull (parsed );
160+ Assert .assertTrue (parsed .exists ("records" ));
161+ List <Object > records = parsed .getArray ("records" );
162+ Assert .assertEquals (3 , records .size ());
163+
164+ TypedStruct first = (TypedStruct ) records .get (0 );
165+ Assert .assertEquals ("1970-01-01 00:00:00,000" , first .getString ("timestamp" ));
166+ Assert .assertEquals ("INFO" , first .getString ("level" ));
167+ Assert .assertEquals ("first log message" , first .getString ("message" ));
168+
169+ TypedStruct last = (TypedStruct ) records .get (2 );
170+ Assert .assertEquals ("1970-01-01 00:00:02,000" , last .getString ("timestamp" ));
171+ Assert .assertEquals ("ERROR" , last .getString ("level" ));
172+ Assert .assertEquals ("third log message" , last .getString ("message" ));
173+ }
174+
175+ @ Test (expected = FilterException .class )
176+ public void testGivenArraySourceWithInvalidElementTypeShouldFail () {
177+ TypedStruct record = TypedStruct .create ().put (
178+ "logs" ,
179+ Arrays .asList ("1970-01-01 00:00:00,000 INFO first log message" , 1 ));
180+
181+ configs .put (GrokConfig .GROK_PATTERN_CONFIG , GROK_NAMED_CAPTURED_PATTERN );
182+ configs .put (CommonFilterConfig .FILTER_SOURCE_FIELD_CONFIG , "logs" );
183+ filter .configure (configs , alias -> null );
184+
185+ filter .apply (null , record , false );
186+ }
187+
188+ @ Test (expected = FilterException .class )
189+ public void testGivenArraySourceWithNonMatchingEntryShouldFail () {
190+ TypedStruct record = TypedStruct .create ().put (
191+ "logs" ,
192+ Arrays .asList (
193+ "1970-01-01 00:00:00,000 INFO first log message" ,
194+ "INVALID" ));
195+
196+ configs .put (GrokConfig .GROK_PATTERN_CONFIG , GROK_NAMED_CAPTURED_PATTERN );
197+ configs .put (CommonFilterConfig .FILTER_SOURCE_FIELD_CONFIG , "logs" );
198+ filter .configure (configs , alias -> null );
199+
200+ filter .apply (null , record , false );
201+ }
89202}
0 commit comments