3030#include <fluent-bit/flb_time.h>
3131#include <fluent-bit/flb_pack.h>
3232#include <fluent-bit/flb_log_event.h>
33+ #include <fluent-bit/flb_env.h>
3334
3435#include "in_dummy.h"
3536
@@ -76,21 +77,89 @@ static int generate_event(struct flb_dummy *ctx)
7677 struct flb_time timestamp ;
7778 msgpack_unpacked object ;
7879 int result ;
80+ flb_sds_t resolved_body ;
81+ flb_sds_t resolved_metadata ;
82+ char * body_msgpack = NULL ;
83+ const char * body_template ;
84+ char * metadata_msgpack = NULL ;
85+ const char * metadata_template ;
86+ size_t body_msgpack_size = 0 ;
87+ size_t metadata_msgpack_size = 0 ;
88+ int root_type ;
7989
8090 result = FLB_EVENT_ENCODER_SUCCESS ;
8191 body_start = 0 ;
8292 chunk_offset = 0 ;
8393
8494 generate_timestamp (ctx , & timestamp );
8595
96+ /* Get the raw template from the property (should be raw when FLB_CONFIG_MAP_DYNAMIC_ENV is set) */
97+ body_template = flb_input_get_property ("dummy" , ctx -> ins );
98+ metadata_template = flb_input_get_property ("metadata" , ctx -> ins );
99+
100+ if (!body_template ) {
101+ body_template = DEFAULT_DUMMY_MESSAGE ;
102+ }
103+ if (!metadata_template ) {
104+ metadata_template = DEFAULT_DUMMY_METADATA ;
105+ }
106+
107+ /* Always try to resolve environment variables for dynamic content */
108+ resolved_body = flb_env_var_translate (ctx -> ins -> config -> env , body_template );
109+ if (!resolved_body ) {
110+ resolved_body = flb_sds_create (body_template );
111+ }
112+
113+
114+ /* Always try to resolve environment variables for dynamic content */
115+ resolved_metadata = flb_env_var_translate (ctx -> ins -> config -> env , metadata_template );
116+ if (!resolved_metadata ) {
117+ resolved_metadata = flb_sds_create (metadata_template );
118+ }
119+
120+ /* Parse the resolved JSON strings */
121+ if (resolved_body ) {
122+ result = flb_pack_json (resolved_body ,
123+ flb_sds_len (resolved_body ),
124+ & body_msgpack ,
125+ & body_msgpack_size ,
126+ & root_type ,
127+ NULL );
128+ }
129+ else {
130+ result = 0 ; /* Using cached msgpack */
131+ }
132+
133+ if (result == 0 && resolved_metadata ) {
134+ result = flb_pack_json (resolved_metadata ,
135+ flb_sds_len (resolved_metadata ),
136+ & metadata_msgpack ,
137+ & metadata_msgpack_size ,
138+ & root_type ,
139+ NULL );
140+ }
141+
142+ if (result != 0 ) {
143+ flb_plg_error (ctx -> ins , "failed to parse JSON template" );
144+ flb_sds_destroy (resolved_body );
145+ flb_sds_destroy (resolved_metadata );
146+ if (body_msgpack ) {
147+ flb_free (body_msgpack );
148+ }
149+ if (metadata_msgpack ) {
150+ flb_free (metadata_msgpack );
151+ }
152+ return -1 ;
153+ }
154+
86155 msgpack_unpacked_init (& object );
87156
88157 while (result == FLB_EVENT_ENCODER_SUCCESS &&
89158 msgpack_unpack_next (& object ,
90- ctx -> ref_body_msgpack ,
91- ctx -> ref_body_msgpack_size ,
159+ body_msgpack ,
160+ body_msgpack_size ,
92161 & chunk_offset ) == MSGPACK_UNPACK_SUCCESS ) {
93- body_buffer = & ctx -> ref_body_msgpack [body_start ];
162+ body_buffer = & body_msgpack [body_start ];
94163 body_length = chunk_offset - body_start ;
95164
96165 if (object .data .type == MSGPACK_OBJECT_MAP ) {
@@ -100,8 +169,8 @@ static int generate_event(struct flb_dummy *ctx)
100169
101170 result = flb_log_event_encoder_set_metadata_from_raw_msgpack (
102171 ctx -> encoder ,
103- ctx -> ref_metadata_msgpack ,
104- ctx -> ref_metadata_msgpack_size );
172+ metadata_msgpack ,
173+ metadata_msgpack_size );
105174
106175 if (result == FLB_EVENT_ENCODER_SUCCESS ) {
107176 result = flb_log_event_encoder_set_body_from_raw_msgpack (
@@ -120,6 +189,21 @@ static int generate_event(struct flb_dummy *ctx)
120189
121190 msgpack_unpacked_destroy (& object );
122191
192+ /* Clean up */
193+ if (resolved_body ) {
194+ flb_sds_destroy (resolved_body );
195+ }
196+ if (resolved_metadata ) {
197+ flb_sds_destroy (resolved_metadata );
198+ }
199+ /* Only free msgpack if we allocated it (not using cached) */
200+ if (body_msgpack && body_msgpack != ctx -> ref_body_msgpack ) {
201+ flb_free (body_msgpack );
202+ }
203+ if (metadata_msgpack && metadata_msgpack != ctx -> ref_metadata_msgpack ) {
204+ flb_free (metadata_msgpack );
205+ }
206+
123207 if (result == FLB_EVENT_ENCODER_SUCCESS ) {
124208 result = 0 ;
125209 }
@@ -186,6 +270,15 @@ static int config_destroy(struct flb_dummy *ctx)
186270 flb_free (ctx -> ref_metadata_msgpack );
187271 }
188272
273+ if (ctx -> body_template != NULL ) {
274+ flb_free (ctx -> body_template );
275+ }
276+
277+ if (ctx -> metadata_template != NULL ) {
278+ flb_free (ctx -> metadata_template );
279+ }
280+
281+
189282 if (ctx -> encoder != NULL ) {
190283 flb_log_event_encoder_destroy (ctx -> encoder );
191284 }
@@ -200,12 +293,15 @@ static int configure(struct flb_dummy *ctx,
200293 struct flb_input_instance * in ,
201294 struct timespec * tm )
202295{
203- const char * msg ;
204- int root_type ;
205296 int ret = -1 ;
297+ int root_type ;
298+ const char * msg ;
299+ flb_sds_t resolved_msg ;
206300
207301 ctx -> ref_metadata_msgpack = NULL ;
208302 ctx -> ref_body_msgpack = NULL ;
303+ ctx -> body_template = NULL ;
304+ ctx -> metadata_template = NULL ;
209305 ctx -> dummy_timestamp_set = FLB_FALSE ;
210306
211307 ret = flb_input_config_map_set (in , (void * ) ctx );
@@ -228,7 +324,8 @@ static int configure(struct flb_dummy *ctx,
228324 /* Set using interval settings. */
229325 tm -> tv_sec = ctx -> interval_sec ;
230326 tm -> tv_nsec = ctx -> interval_nsec ;
231- } else {
327+ }
328+ else {
232329 if (ctx -> rate > 1 ) {
233330 /* Set using rate settings. */
234331 tm -> tv_sec = 0 ;
@@ -252,14 +349,23 @@ static int configure(struct flb_dummy *ctx,
252349
253350 flb_time_get (& ctx -> base_timestamp );
254351
255- /* handle it explicitly since we need to validate it is valid JSON */
352+ /* Store the original body template for dynamic re-parsing */
256353 msg = flb_input_get_property ("dummy" , in );
257354 if (msg == NULL ) {
258355 msg = DEFAULT_DUMMY_MESSAGE ;
259356 }
357+ flb_plg_info (ctx -> ins , "received dummy property: %s" , msg );
358+ ctx -> body_template = flb_strdup (msg );
359+
360+ /* Validate the template by parsing it once (with environment variables resolved) */
361+ resolved_msg = flb_env_var_translate (in -> config -> env , msg );
362+ if (!resolved_msg || flb_sds_len (resolved_msg ) == 0 ) {
363+ flb_plg_warn (ctx -> ins , "environment variable resolution failed for dummy message, using default" );
364+ resolved_msg = flb_sds_create (DEFAULT_DUMMY_MESSAGE );
365+ }
260366
261- ret = flb_pack_json (msg ,
262- strlen ( msg ),
367+ ret = flb_pack_json (resolved_msg ,
368+ flb_sds_len ( resolved_msg ),
263369 & ctx -> ref_body_msgpack ,
264370 & ctx -> ref_body_msgpack_size ,
265371 & root_type ,
@@ -276,19 +382,29 @@ static int configure(struct flb_dummy *ctx,
276382 NULL );
277383 if (ret != 0 ) {
278384 flb_plg_error (ctx -> ins , "unexpected error" );
385+ flb_sds_destroy (resolved_msg );
279386 return -1 ;
280387 }
281388 }
282389
283- /* handle it explicitly since we need to validate it is valid JSON */
284- msg = flb_input_get_property ("metadata" , in );
390+ flb_sds_destroy (resolved_msg );
285391
392+ /* Store the original metadata template for dynamic re-parsing */
393+ msg = flb_input_get_property ("metadata" , in );
286394 if (msg == NULL ) {
287395 msg = DEFAULT_DUMMY_METADATA ;
288396 }
397+ ctx -> metadata_template = flb_strdup (msg );
398+
399+ /* Validate the template by parsing it once (with environment variables resolved) */
400+ resolved_msg = flb_env_var_translate (in -> config -> env , msg );
401+ if (!resolved_msg || flb_sds_len (resolved_msg ) == 0 ) {
402+ flb_plg_warn (ctx -> ins , "environment variable resolution failed for metadata, using default" );
403+ resolved_msg = flb_sds_create (DEFAULT_DUMMY_METADATA );
404+ }
289405
290- ret = flb_pack_json (msg ,
291- strlen ( msg ),
406+ ret = flb_pack_json (resolved_msg ,
407+ flb_sds_len ( resolved_msg ),
292408 & ctx -> ref_metadata_msgpack ,
293409 & ctx -> ref_metadata_msgpack_size ,
294410 & root_type ,
@@ -306,10 +422,13 @@ static int configure(struct flb_dummy *ctx,
306422
307423 if (ret != 0 ) {
308424 flb_plg_error (ctx -> ins , "unexpected error" );
425+ flb_sds_destroy (resolved_msg );
309426 return -1 ;
310427 }
311428 }
312429
430+ flb_sds_destroy (resolved_msg );
431+
313432 return 0 ;
314433}
315434
@@ -327,6 +446,7 @@ static int in_dummy_init(struct flb_input_instance *in,
327446 /* Allocate space for the configuration */
328447 ctx = flb_malloc (sizeof (struct flb_dummy ));
329448 if (ctx == NULL ) {
449+ flb_errno ();
330450 return -1 ;
331451 }
332452 ctx -> ins = in ;
@@ -341,7 +461,6 @@ static int in_dummy_init(struct flb_input_instance *in,
341461 }
342462
343463 ctx -> encoder = flb_log_event_encoder_create (FLB_LOG_EVENT_FORMAT_DEFAULT );
344-
345464 if (ctx -> encoder == NULL ) {
346465 flb_plg_error (in , "could not initialize event encoder" );
347466 config_destroy (ctx );
@@ -405,13 +524,15 @@ static struct flb_config_map config_map[] = {
405524 },
406525 {
407526 FLB_CONFIG_MAP_STR , "dummy" , DEFAULT_DUMMY_MESSAGE ,
408- 0 , FLB_FALSE , 0 ,
527+ FLB_CONFIG_MAP_DYNAMIC_ENV , FLB_FALSE , 0 ,
409528 "set the sample record to be generated. It should be a JSON object."
529+ "Environment variables are resolved dynamically."
410530 },
411531 {
412532 FLB_CONFIG_MAP_STR , "metadata" , DEFAULT_DUMMY_METADATA ,
413- 0 , FLB_FALSE , 0 ,
533+ FLB_CONFIG_MAP_DYNAMIC_ENV , FLB_FALSE , 0 ,
414534 "set the sample metadata to be generated. It should be a JSON object."
535+ "Environment variables are resolved dynamically."
415536 },
416537 {
417538 FLB_CONFIG_MAP_INT , "rate" , DEFAULT_RATE ,
0 commit comments