2525 get_disable_trace_configurations_from_env ,
2626 get_disable_trace_configurations_from_local ,
2727 get_disable_trace_configurations_from_yaml ,
28+ get_span_filter_config_from_yaml ,
2829 get_stack_trace_config_from_yaml ,
2930 is_truthy ,
3031 parse_ignored_endpoints ,
3132 parse_ignored_endpoints_from_yaml ,
3233 parse_span_disabling ,
34+ parse_span_filter_config ,
35+ parse_span_filter_from_env ,
3336 parse_technology_stack_trace_config ,
3437 validate_stack_trace_length ,
3538 validate_stack_trace_level ,
@@ -47,6 +50,7 @@ def __init__(self, **kwds: Dict[str, Any]) -> None:
4750 self .extra_http_headers = None
4851 self .allow_exit_as_root = False
4952 self .ignore_endpoints = []
53+ self .span_filters = {}
5054 self .kafka_trace_correlation = True
5155
5256 # disabled_spans lists all categories and types that should be disabled
@@ -83,6 +87,10 @@ def __init__(self, **kwds: Dict[str, Any]) -> None:
8387
8488 self .__dict__ .update (kwds )
8589
90+ def _has_env_filter_vars (self ) -> bool :
91+ """Check if any INSTANA_TRACING_FILTER_* environment variables exist."""
92+ return any (key .startswith ("INSTANA_TRACING_FILTER_" ) for key in os .environ )
93+
8694 def set_trace_configurations (self ) -> None :
8795 """
8896 Set tracing configurations from the environment variables and config file.
@@ -105,10 +113,16 @@ def set_trace_configurations(self) -> None:
105113 ):
106114 self .allow_exit_as_root = True
107115
116+ # Span filter configuration priority:
117+ # INSTANA_TRACING_FILTER_* env vars > INSTANA_CONFIG_PATH > in-code > agent config
118+ if self ._has_env_filter_vars ():
119+ self .span_filters = parse_span_filter_from_env ()
120+ elif "INSTANA_CONFIG_PATH" in os .environ :
121+ self .span_filters = get_span_filter_config_from_yaml ()
108122 # The priority is as follows:
109123 # environment variables > in-code configuration >
110124 # > agent config (configuration.yaml) > default value
111- if "INSTANA_IGNORE_ENDPOINTS" in os .environ :
125+ elif "INSTANA_IGNORE_ENDPOINTS" in os .environ :
112126 self .ignore_endpoints = parse_ignored_endpoints (
113127 os .environ ["INSTANA_IGNORE_ENDPOINTS" ]
114128 )
@@ -146,7 +160,8 @@ def _apply_env_stack_trace_config(self) -> None:
146160
147161 if "INSTANA_STACK_TRACE_LENGTH" in os .environ :
148162 if validated_length := validate_stack_trace_length (
149- os .environ ["INSTANA_STACK_TRACE_LENGTH" ], "from INSTANA_STACK_TRACE_LENGTH"
163+ os .environ ["INSTANA_STACK_TRACE_LENGTH" ],
164+ "from INSTANA_STACK_TRACE_LENGTH" ,
150165 ):
151166 self .stack_trace_length = validated_length
152167
@@ -161,31 +176,41 @@ def _apply_yaml_stack_trace_config(self) -> None:
161176
162177 def _apply_in_code_stack_trace_config (self ) -> None :
163178 """Apply stack trace configuration from in-code config."""
164- if not isinstance (config .get ("tracing" ), dict ) or "global" not in config ["tracing" ]:
179+ if (
180+ not isinstance (config .get ("tracing" ), dict )
181+ or "global" not in config ["tracing" ]
182+ ):
165183 return
166-
184+
167185 global_config = config ["tracing" ]["global" ]
168-
186+
169187 if "INSTANA_STACK_TRACE" not in os .environ and "stack_trace" in global_config :
170- if validated_level := validate_stack_trace_level (global_config ["stack_trace" ], "from in-code config" ):
188+ if validated_level := validate_stack_trace_level (
189+ global_config ["stack_trace" ], "from in-code config"
190+ ):
171191 self .stack_trace_level = validated_level
172-
173- if "INSTANA_STACK_TRACE_LENGTH" not in os .environ and "stack_trace_length" in global_config :
174- if validated_length := validate_stack_trace_length (global_config ["stack_trace_length" ], "from in-code config" ):
192+
193+ if (
194+ "INSTANA_STACK_TRACE_LENGTH" not in os .environ
195+ and "stack_trace_length" in global_config
196+ ):
197+ if validated_length := validate_stack_trace_length (
198+ global_config ["stack_trace_length" ], "from in-code config"
199+ ):
175200 self .stack_trace_length = validated_length
176-
201+
177202 # Technology-specific overrides from in-code config
178203 for tech_name , tech_data in config ["tracing" ].items ():
179204 if tech_name == "global" or not isinstance (tech_data , dict ):
180205 continue
181-
206+
182207 tech_stack_config = parse_technology_stack_trace_config (
183208 tech_data ,
184209 level_key = "stack_trace" ,
185210 length_key = "stack_trace_length" ,
186- tech_name = tech_name
211+ tech_name = tech_name ,
187212 )
188-
213+
189214 if tech_stack_config :
190215 self .stack_trace_technology_config [tech_name ] = tech_stack_config
191216
@@ -196,7 +221,7 @@ def set_stack_trace_configurations(self) -> None:
196221 """
197222 # 1. Environment variables (highest priority)
198223 self ._apply_env_stack_trace_config ()
199-
224+
200225 # 2. INSTANA_CONFIG_PATH (YAML file) - includes tech-specific overrides
201226 if "INSTANA_CONFIG_PATH" in os .environ :
202227 self ._apply_yaml_stack_trace_config ()
@@ -261,10 +286,10 @@ def get_stack_trace_config(self, span_name: str) -> Tuple[str, int]:
261286 """
262287 Get stack trace configuration for a specific span type.
263288 Technology-specific configuration overrides global configuration.
264-
289+
265290 Args:
266291 span_name: The name of the span (e.g., "kafka-producer", "redis", "mysql")
267-
292+
268293 Returns:
269294 Tuple of (level, length) where:
270295 - level: "all", "error", or "none"
@@ -273,17 +298,17 @@ def get_stack_trace_config(self, span_name: str) -> Tuple[str, int]:
273298 # Start with global defaults
274299 level = self .stack_trace_level
275300 length = self .stack_trace_length
276-
301+
277302 # Check for technology-specific overrides
278303 # Extract base technology name from span name
279304 # Examples: "kafka-producer" -> "kafka", "mysql" -> "mysql"
280305 tech_name = span_name .split ("-" )[0 ] if "-" in span_name else span_name
281-
306+
282307 if tech_name in self .stack_trace_technology_config :
283308 tech_config = self .stack_trace_technology_config [tech_name ]
284309 level = tech_config .get ("level" , level )
285310 length = tech_config .get ("length" , length )
286-
311+
287312 return level , length
288313
289314
@@ -334,6 +359,9 @@ def set_tracing(self, tracing: Dict[str, Any]) -> None:
334359 if "ignore-endpoints" in tracing and not self .ignore_endpoints :
335360 self .ignore_endpoints = parse_ignored_endpoints (tracing ["ignore-endpoints" ])
336361
362+ if "filter" in tracing and not self .span_filters :
363+ self .span_filters = parse_span_filter_config (tracing ["filter" ])
364+
337365 if "kafka" in tracing :
338366 if (
339367 "INSTANA_KAFKA_TRACE_CORRELATION" not in os .environ
@@ -361,7 +389,7 @@ def set_tracing(self, tracing: Dict[str, Any]) -> None:
361389 # Handle span disabling configuration
362390 if "disable" in tracing :
363391 self .set_disable_tracing (tracing ["disable" ])
364-
392+
365393 # Handle stack trace configuration from agent config
366394 self .set_stack_trace_from_agent (tracing )
367395
@@ -375,48 +403,56 @@ def _should_apply_agent_global_config(self) -> bool:
375403 has_in_code_config = (
376404 isinstance (config .get ("tracing" ), dict )
377405 and "global" in config ["tracing" ]
378- and ("stack_trace" in config ["tracing" ]["global" ]
379- or "stack_trace_length" in config ["tracing" ]["global" ])
406+ and (
407+ "stack_trace" in config ["tracing" ]["global" ]
408+ or "stack_trace_length" in config ["tracing" ]["global" ]
409+ )
380410 )
381411 return not (has_env_vars or has_yaml_config or has_in_code_config )
382412
383- def _apply_agent_global_stack_trace_config (self , global_config : Dict [str , Any ]) -> None :
413+ def _apply_agent_global_stack_trace_config (
414+ self , global_config : Dict [str , Any ]
415+ ) -> None :
384416 """Apply global stack trace configuration from agent config."""
385417 if "stack-trace" in global_config :
386- if validated_level := validate_stack_trace_level (global_config ["stack-trace" ], "in agent config" ):
418+ if validated_level := validate_stack_trace_level (
419+ global_config ["stack-trace" ], "in agent config"
420+ ):
387421 self .stack_trace_level = validated_level
388-
422+
389423 if "stack-trace-length" in global_config :
390- if validated_length := validate_stack_trace_length (global_config ["stack-trace-length" ], "in agent config" ):
424+ if validated_length := validate_stack_trace_length (
425+ global_config ["stack-trace-length" ], "in agent config"
426+ ):
391427 self .stack_trace_length = validated_length
392428
393429 def _apply_agent_tech_stack_trace_config (self , tracing : Dict [str , Any ]) -> None :
394430 """Apply technology-specific stack trace configuration from agent config."""
395431 for tech_name , tech_config in tracing .items ():
396432 if tech_name == "global" or not isinstance (tech_config , dict ):
397433 continue
398-
434+
399435 tech_stack_config = parse_technology_stack_trace_config (
400436 tech_config ,
401437 level_key = "stack-trace" ,
402438 length_key = "stack-trace-length" ,
403- tech_name = tech_name
439+ tech_name = tech_name ,
404440 )
405-
441+
406442 if tech_stack_config :
407443 self .stack_trace_technology_config [tech_name ] = tech_stack_config
408444
409445 def set_stack_trace_from_agent (self , tracing : Dict [str , Any ]) -> None :
410446 """
411447 Set stack trace configuration from agent config (configuration.yaml).
412448 Only applies if not already set by higher priority sources.
413-
449+
414450 @param tracing: tracing configuration dictionary from agent
415451 """
416452 # Apply global config if no higher priority source exists
417453 if self ._should_apply_agent_global_config () and "global" in tracing :
418454 self ._apply_agent_global_stack_trace_config (tracing ["global" ])
419-
455+
420456 # Apply technology-specific config if not already set by YAML or in-code config
421457 if not self .stack_trace_technology_config :
422458 self ._apply_agent_tech_stack_trace_config (tracing )
0 commit comments