@@ -19,18 +19,20 @@ use linkme::distributed_slice;
1919use otap_df_config:: SignalType ;
2020use otap_df_config:: error:: Error as ConfigError ;
2121use otap_df_config:: node:: NodeUserConfig ;
22+ use otap_df_engine:: ConsumerEffectHandlerExtension ;
2223use otap_df_engine:: config:: ProcessorConfig ;
2324use otap_df_engine:: context:: PipelineContext ;
24- use otap_df_engine:: error:: { Error , ProcessorErrorKind } ;
25+ use otap_df_engine:: control:: NackMsg ;
26+ use otap_df_engine:: error:: Error ;
2527use otap_df_engine:: local:: processor as local;
2628use otap_df_engine:: message:: Message ;
2729use otap_df_engine:: node:: NodeId ;
2830use otap_df_engine:: processor:: ProcessorWrapper ;
29- use otap_df_pdata:: OtapArrowRecords ;
3031use otap_df_pdata:: encode:: record:: attributes:: StrKeysAttributesRecordBatchBuilder ;
3132use otap_df_pdata:: otlp:: attributes:: AttributeValueType ;
3233use otap_df_pdata:: proto:: opentelemetry:: arrow:: v1:: ArrowPayloadType ;
3334use otap_df_pdata:: schema:: consts;
35+ use otap_df_pdata:: { OtapArrowRecords , OtapPayload } ;
3436use serde_json:: Value ;
3537use std:: collections:: { HashMap , HashSet } ;
3638use std:: sync:: Arc ;
@@ -57,59 +59,8 @@ pub struct Config {
5759 exclude_keys : Option < HashSet < String > > ,
5860}
5961
60- /// Processor that condenses multiple attributes into a single attribute based on predefined rules.
61- pub struct CondenseAttributesProcessor {
62- config : Config ,
63- rows_to_preserve : Vec < usize > ,
64- }
65-
66- fn engine_err ( msg : & str ) -> Error {
67- Error :: PdataConversionError {
68- error : msg. to_string ( ) ,
69- }
70- }
71-
72- /// Factory function to create a Condense Attributes processor
73- pub fn create_condense_attributes_processor (
74- _: PipelineContext ,
75- node : NodeId ,
76- node_config : Arc < NodeUserConfig > ,
77- processor_config : & ProcessorConfig ,
78- ) -> Result < ProcessorWrapper < OtapPdata > , ConfigError > {
79- Ok ( ProcessorWrapper :: local (
80- CondenseAttributesProcessor :: from_config ( & node_config. config ) ?,
81- node,
82- node_config,
83- processor_config,
84- ) )
85- }
86-
87- /// Register CondenseAttributesProcessor as an OTAP processor factory
88- #[ allow( unsafe_code) ]
89- #[ distributed_slice( OTAP_PROCESSOR_FACTORIES ) ]
90- pub static CONDENSE_ATTRIBUTES_PROCESSOR_FACTORY : otap_df_engine:: ProcessorFactory < OtapPdata > =
91- otap_df_engine:: ProcessorFactory {
92- name : CONDENSE_ATTRIBUTES_PROCESSOR_URN ,
93- create : |pipeline_ctx : PipelineContext ,
94- node : NodeId ,
95- node_config : Arc < NodeUserConfig > ,
96- proc_cfg : & ProcessorConfig | {
97- create_condense_attributes_processor ( pipeline_ctx, node, node_config, proc_cfg)
98- } ,
99- wiring_contract : otap_df_engine:: wiring_contract:: WiringContract :: UNRESTRICTED ,
100- } ;
101-
102- impl CondenseAttributesProcessor {
103- /// Creates a new CondenseAttributesProcessor instance
104- #[ must_use]
105- pub fn new ( config : Config ) -> Self {
106- Self {
107- config,
108- rows_to_preserve : Vec :: new ( ) ,
109- }
110- }
111-
112- /// Creates a new CondenseAttributesProcessor instance from configuration
62+ impl Config {
63+ /// Creates a new Config instance from configuration
11364 pub fn from_config ( config : & Value ) -> Result < Self , ConfigError > {
11465 let destination_key = config
11566 . get ( "destination_key" )
@@ -193,12 +144,74 @@ impl CondenseAttributesProcessor {
193144 }
194145 }
195146
196- Ok ( Self :: new ( Config {
147+ Ok ( Self {
197148 destination_key,
198149 delimiter,
199150 source_keys,
200151 exclude_keys,
201- } ) )
152+ } )
153+ }
154+ }
155+
156+ /// Processor that condenses multiple attributes into a single attribute based on predefined rules.
157+ pub struct CondenseAttributesProcessor {
158+ config : Config ,
159+ rows_to_preserve : Vec < usize > ,
160+ }
161+
162+ fn engine_err ( msg : & str ) -> Error {
163+ Error :: PdataConversionError {
164+ error : msg. to_string ( ) ,
165+ }
166+ }
167+
168+ /// Factory function to create a Condense Attributes processor
169+ pub fn create_condense_attributes_processor (
170+ _: PipelineContext ,
171+ node : NodeId ,
172+ node_config : Arc < NodeUserConfig > ,
173+ processor_config : & ProcessorConfig ,
174+ ) -> Result < ProcessorWrapper < OtapPdata > , ConfigError > {
175+ let processor = CondenseAttributesProcessor :: from_config ( & node_config. config ) ?;
176+
177+ otap_df_telemetry:: otel_info!( "condense_attributes_processor.ready" ) ;
178+
179+ Ok ( ProcessorWrapper :: local (
180+ processor,
181+ node,
182+ node_config,
183+ processor_config,
184+ ) )
185+ }
186+
187+ /// Register CondenseAttributesProcessor as an OTAP processor factory
188+ #[ allow( unsafe_code) ]
189+ #[ distributed_slice( OTAP_PROCESSOR_FACTORIES ) ]
190+ pub static CONDENSE_ATTRIBUTES_PROCESSOR_FACTORY : otap_df_engine:: ProcessorFactory < OtapPdata > =
191+ otap_df_engine:: ProcessorFactory {
192+ name : CONDENSE_ATTRIBUTES_PROCESSOR_URN ,
193+ create : |pipeline_ctx : PipelineContext ,
194+ node : NodeId ,
195+ node_config : Arc < NodeUserConfig > ,
196+ proc_cfg : & ProcessorConfig | {
197+ create_condense_attributes_processor ( pipeline_ctx, node, node_config, proc_cfg)
198+ } ,
199+ wiring_contract : otap_df_engine:: wiring_contract:: WiringContract :: UNRESTRICTED ,
200+ } ;
201+
202+ impl CondenseAttributesProcessor {
203+ /// Creates a new CondenseAttributesProcessor instance
204+ #[ must_use]
205+ pub fn new ( config : Config ) -> Self {
206+ Self {
207+ config,
208+ rows_to_preserve : Vec :: new ( ) ,
209+ }
210+ }
211+
212+ /// Creates a new CondenseAttributesProcessor instance from configuration
213+ pub fn from_config ( config : & Value ) -> Result < Self , ConfigError > {
214+ Ok ( Self :: new ( Config :: from_config ( config) ?) )
202215 }
203216
204217 /// Condenses attributes in the given record batch according to the processor configuration.
@@ -531,34 +544,79 @@ impl local::Processor<OtapPdata> for CondenseAttributesProcessor {
531544 effect_handler : & mut local:: EffectHandler < OtapPdata > ,
532545 ) -> Result < ( ) , Error > {
533546 match msg {
534- Message :: Control ( _control) => Ok ( ( ) ) ,
547+ Message :: Control ( control_msg) => {
548+ use otap_df_engine:: control:: NodeControlMsg ;
549+ match control_msg {
550+ NodeControlMsg :: Config { config } => {
551+ match Config :: from_config ( & config) {
552+ Ok ( new_config) => {
553+ otap_df_telemetry:: otel_info!(
554+ "condense_attributes_processor.reconfigured"
555+ ) ;
556+ self . config = new_config;
557+ }
558+ Err ( e) => {
559+ otap_df_telemetry:: otel_warn!(
560+ "condense_attributes_processor.reconfigure_error" ,
561+ message = %e
562+ ) ;
563+ }
564+ }
565+ Ok ( ( ) )
566+ }
567+ _ => Ok ( ( ) ) ,
568+ }
569+ }
535570 Message :: PData ( pdata) => {
536571 let signal = pdata. signal_type ( ) ;
537572 let ( context, payload) = pdata. into_parts ( ) ;
538573
539574 let mut records: OtapArrowRecords = payload. try_into ( ) ?;
540575
541- let condensed_records: OtapArrowRecords =
542- match signal {
543- SignalType :: Logs => match self . condense ( & mut records) {
544- // TODO: Add instrumentation for condensed count
545- Ok ( _condensed) => records,
546- Err ( e) => return Err ( e) ,
547- } ,
548- _ => return Err ( Error :: ProcessorError {
549- processor : effect_handler. processor_id ( ) ,
550- kind : ProcessorErrorKind :: Other ,
551- error :
552- "CondenseAttributesProcessor only supported for SignalType 'Logs'"
553- . to_string ( ) ,
554- source_detail : String :: new ( ) ,
555- } ) ,
556- } ;
557-
558- effect_handler
559- . send_message ( OtapPdata :: new ( context, condensed_records. into ( ) ) )
560- . await ?;
561- Ok ( ( ) )
576+ let input_items = records. num_items ( ) as u64 ;
577+
578+ otap_df_telemetry:: otel_debug!(
579+ "condense_attributes_processor.processing" ,
580+ input_items
581+ ) ;
582+
583+ let result = match signal {
584+ SignalType :: Logs => self . condense ( & mut records) ,
585+ _ => Err ( Error :: InternalError {
586+ message : "CondenseAttributesProcessor only supported for SignalType 'Logs'"
587+ . to_string ( ) ,
588+ } ) ,
589+ } ;
590+
591+ match result {
592+ Ok ( condensed) => {
593+ otap_df_telemetry:: otel_debug!(
594+ "condense_attributes_processor.success" ,
595+ input_items,
596+ output_items = condensed
597+ ) ;
598+ effect_handler
599+ . send_message ( OtapPdata :: new ( context, records. into ( ) ) )
600+ . await ?;
601+ Ok ( ( ) )
602+ }
603+ Err ( e) => {
604+ let message = e. to_string ( ) ;
605+ otap_df_telemetry:: otel_error!(
606+ "condense_attributes_processor.failure" ,
607+ input_items,
608+ message,
609+ ) ;
610+
611+ effect_handler
612+ . notify_nack ( NackMsg :: new (
613+ message,
614+ OtapPdata :: new ( context, OtapPayload :: empty ( SignalType :: Logs ) ) ,
615+ ) )
616+ . await ?;
617+ Err ( e)
618+ }
619+ }
562620 }
563621 }
564622 }
0 commit comments