|
30 | 30 | parse_ignored_endpoints, |
31 | 31 | parse_ignored_endpoints_from_yaml, |
32 | 32 | parse_span_disabling, |
| 33 | + parse_technology_stack_trace_config, |
| 34 | + validate_stack_trace_length, |
| 35 | + validate_stack_trace_level, |
33 | 36 | ) |
34 | 37 | from instana.util.runtime import determine_service_name |
35 | 38 |
|
@@ -133,104 +136,73 @@ def set_trace_configurations(self) -> None: |
133 | 136 | self.set_disable_trace_configurations() |
134 | 137 | self.set_stack_trace_configurations() |
135 | 138 |
|
| 139 | + def _apply_env_stack_trace_config(self) -> None: |
| 140 | + """Apply stack trace configuration from environment variables.""" |
| 141 | + if "INSTANA_STACK_TRACE" in os.environ: |
| 142 | + if validated_level := validate_stack_trace_level( |
| 143 | + os.environ["INSTANA_STACK_TRACE"], "from INSTANA_STACK_TRACE" |
| 144 | + ): |
| 145 | + self.stack_trace_level = validated_level |
| 146 | + |
| 147 | + if "INSTANA_STACK_TRACE_LENGTH" in os.environ: |
| 148 | + if validated_length := validate_stack_trace_length( |
| 149 | + os.environ["INSTANA_STACK_TRACE_LENGTH"], "from INSTANA_STACK_TRACE_LENGTH" |
| 150 | + ): |
| 151 | + self.stack_trace_length = validated_length |
| 152 | + |
| 153 | + def _apply_yaml_stack_trace_config(self) -> None: |
| 154 | + """Apply stack trace configuration from YAML file.""" |
| 155 | + yaml_level, yaml_length, yaml_tech_config = get_stack_trace_config_from_yaml() |
| 156 | + if "INSTANA_STACK_TRACE" not in os.environ: |
| 157 | + self.stack_trace_level = yaml_level |
| 158 | + if "INSTANA_STACK_TRACE_LENGTH" not in os.environ: |
| 159 | + self.stack_trace_length = yaml_length |
| 160 | + self.stack_trace_technology_config.update(yaml_tech_config) |
| 161 | + |
| 162 | + def _apply_in_code_stack_trace_config(self) -> None: |
| 163 | + """Apply stack trace configuration from in-code config.""" |
| 164 | + if not isinstance(config.get("tracing"), dict) or "global" not in config["tracing"]: |
| 165 | + return |
| 166 | + |
| 167 | + global_config = config["tracing"]["global"] |
| 168 | + |
| 169 | + 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"): |
| 171 | + 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"): |
| 175 | + self.stack_trace_length = validated_length |
| 176 | + |
| 177 | + # Technology-specific overrides from in-code config |
| 178 | + for tech_name, tech_data in config["tracing"].items(): |
| 179 | + if tech_name == "global" or not isinstance(tech_data, dict): |
| 180 | + continue |
| 181 | + |
| 182 | + tech_stack_config = parse_technology_stack_trace_config( |
| 183 | + tech_data, |
| 184 | + level_key="stack_trace", |
| 185 | + length_key="stack_trace_length", |
| 186 | + tech_name=tech_name |
| 187 | + ) |
| 188 | + |
| 189 | + if tech_stack_config: |
| 190 | + self.stack_trace_technology_config[tech_name] = tech_stack_config |
| 191 | + |
136 | 192 | def set_stack_trace_configurations(self) -> None: |
137 | 193 | """ |
138 | 194 | Set stack trace configurations following precedence: |
139 | 195 | environment variables > INSTANA_CONFIG_PATH > in-code config > agent config > defaults |
140 | 196 | """ |
141 | 197 | # 1. Environment variables (highest priority) |
142 | | - if "INSTANA_STACK_TRACE" in os.environ: |
143 | | - level = os.environ["INSTANA_STACK_TRACE"].lower() |
144 | | - if level in ["all", "error", "none"]: |
145 | | - self.stack_trace_level = level |
146 | | - else: |
147 | | - logger.warning( |
148 | | - f"Invalid INSTANA_STACK_TRACE value: {level}. Must be 'all', 'error', or 'none'. Using default 'all'" |
149 | | - ) |
150 | | - |
151 | | - if "INSTANA_STACK_TRACE_LENGTH" in os.environ: |
152 | | - try: |
153 | | - length = int(os.environ["INSTANA_STACK_TRACE_LENGTH"]) |
154 | | - if length >= 1: |
155 | | - self.stack_trace_length = length |
156 | | - else: |
157 | | - logger.warning( |
158 | | - "INSTANA_STACK_TRACE_LENGTH must be positive. Using default 30" |
159 | | - ) |
160 | | - except ValueError: |
161 | | - logger.warning( |
162 | | - "Invalid INSTANA_STACK_TRACE_LENGTH value. Must be an integer. Using default 30" |
163 | | - ) |
| 198 | + self._apply_env_stack_trace_config() |
164 | 199 |
|
165 | 200 | # 2. INSTANA_CONFIG_PATH (YAML file) - includes tech-specific overrides |
166 | | - elif "INSTANA_CONFIG_PATH" in os.environ: |
167 | | - yaml_level, yaml_length, yaml_tech_config = get_stack_trace_config_from_yaml() |
168 | | - if "INSTANA_STACK_TRACE" not in os.environ: |
169 | | - self.stack_trace_level = yaml_level |
170 | | - if "INSTANA_STACK_TRACE_LENGTH" not in os.environ: |
171 | | - self.stack_trace_length = yaml_length |
172 | | - # Technology-specific overrides from YAML |
173 | | - self.stack_trace_technology_config.update(yaml_tech_config) |
174 | | - |
| 201 | + if "INSTANA_CONFIG_PATH" in os.environ: |
| 202 | + self._apply_yaml_stack_trace_config() |
175 | 203 | # 3. In-code (local) configuration - includes tech-specific overrides |
176 | | - elif isinstance(config.get("tracing"), dict) and "global" in config["tracing"]: |
177 | | - global_config = config["tracing"]["global"] |
178 | | - |
179 | | - if "INSTANA_STACK_TRACE" not in os.environ and "stack_trace" in global_config: |
180 | | - level = str(global_config["stack_trace"]).lower() |
181 | | - if level in ["all", "error", "none"]: |
182 | | - self.stack_trace_level = level |
183 | | - else: |
184 | | - logger.warning( |
185 | | - f"Invalid stack_trace value in config: {level}. Must be 'all', 'error', or 'none'. Using default 'all'" |
186 | | - ) |
187 | | - |
188 | | - if "INSTANA_STACK_TRACE_LENGTH" not in os.environ and "stack_trace_length" in global_config: |
189 | | - try: |
190 | | - length = int(global_config["stack_trace_length"]) |
191 | | - if length >= 1: |
192 | | - self.stack_trace_length = length |
193 | | - else: |
194 | | - logger.warning( |
195 | | - "stack_trace_length must be positive. Using default 30" |
196 | | - ) |
197 | | - except (ValueError, TypeError): |
198 | | - logger.warning( |
199 | | - "Invalid stack_trace_length in config. Must be an integer. Using default 30" |
200 | | - ) |
201 | | - |
202 | | - # Technology-specific overrides from in-code config |
203 | | - for tech_name, tech_data in config["tracing"].items(): |
204 | | - if tech_name == "global" or not isinstance(tech_data, dict): |
205 | | - continue |
206 | | - |
207 | | - tech_stack_config = {} |
208 | | - |
209 | | - if "stack_trace" in tech_data: |
210 | | - tech_level = str(tech_data["stack_trace"]).lower() |
211 | | - if tech_level in ["all", "error", "none"]: |
212 | | - tech_stack_config["level"] = tech_level |
213 | | - else: |
214 | | - logger.warning( |
215 | | - f"Invalid stack_trace value for {tech_name}: {tech_level}. Ignoring." |
216 | | - ) |
217 | | - |
218 | | - if "stack_trace_length" in tech_data: |
219 | | - try: |
220 | | - tech_length = int(tech_data["stack_trace_length"]) |
221 | | - if tech_length >= 1: |
222 | | - tech_stack_config["length"] = tech_length |
223 | | - else: |
224 | | - logger.warning( |
225 | | - f"stack_trace_length for {tech_name} must be positive. Ignoring." |
226 | | - ) |
227 | | - except (ValueError, TypeError): |
228 | | - logger.warning( |
229 | | - f"Invalid stack_trace_length for {tech_name}. Must be an integer. Ignoring." |
230 | | - ) |
231 | | - |
232 | | - if tech_stack_config: |
233 | | - self.stack_trace_technology_config[tech_name] = tech_stack_config |
| 204 | + elif isinstance(config.get("tracing"), dict): |
| 205 | + self._apply_in_code_stack_trace_config() |
234 | 206 |
|
235 | 207 | def set_disable_trace_configurations(self) -> None: |
236 | 208 | disabled_spans = [] |
@@ -393,90 +365,61 @@ def set_tracing(self, tracing: Dict[str, Any]) -> None: |
393 | 365 | # Handle stack trace configuration from agent config |
394 | 366 | self.set_stack_trace_from_agent(tracing) |
395 | 367 |
|
| 368 | + def _should_apply_agent_global_config(self) -> bool: |
| 369 | + """Check if agent global config should be applied (lowest priority).""" |
| 370 | + has_env_vars = ( |
| 371 | + "INSTANA_STACK_TRACE" in os.environ |
| 372 | + or "INSTANA_STACK_TRACE_LENGTH" in os.environ |
| 373 | + ) |
| 374 | + has_yaml_config = "INSTANA_CONFIG_PATH" in os.environ |
| 375 | + has_in_code_config = ( |
| 376 | + isinstance(config.get("tracing"), dict) |
| 377 | + and "global" in config["tracing"] |
| 378 | + and ("stack_trace" in config["tracing"]["global"] |
| 379 | + or "stack_trace_length" in config["tracing"]["global"]) |
| 380 | + ) |
| 381 | + return not (has_env_vars or has_yaml_config or has_in_code_config) |
| 382 | + |
| 383 | + def _apply_agent_global_stack_trace_config(self, global_config: Dict[str, Any]) -> None: |
| 384 | + """Apply global stack trace configuration from agent config.""" |
| 385 | + if "stack-trace" in global_config: |
| 386 | + if validated_level := validate_stack_trace_level(global_config["stack-trace"], "in agent config"): |
| 387 | + self.stack_trace_level = validated_level |
| 388 | + |
| 389 | + if "stack-trace-length" in global_config: |
| 390 | + if validated_length := validate_stack_trace_length(global_config["stack-trace-length"], "in agent config"): |
| 391 | + self.stack_trace_length = validated_length |
| 392 | + |
| 393 | + def _apply_agent_tech_stack_trace_config(self, tracing: Dict[str, Any]) -> None: |
| 394 | + """Apply technology-specific stack trace configuration from agent config.""" |
| 395 | + for tech_name, tech_config in tracing.items(): |
| 396 | + if tech_name == "global" or not isinstance(tech_config, dict): |
| 397 | + continue |
| 398 | + |
| 399 | + tech_stack_config = parse_technology_stack_trace_config( |
| 400 | + tech_config, |
| 401 | + level_key="stack-trace", |
| 402 | + length_key="stack-trace-length", |
| 403 | + tech_name=tech_name |
| 404 | + ) |
| 405 | + |
| 406 | + if tech_stack_config: |
| 407 | + self.stack_trace_technology_config[tech_name] = tech_stack_config |
| 408 | + |
396 | 409 | def set_stack_trace_from_agent(self, tracing: Dict[str, Any]) -> None: |
397 | 410 | """ |
398 | 411 | Set stack trace configuration from agent config (configuration.yaml). |
399 | 412 | Only applies if not already set by higher priority sources. |
400 | 413 | |
401 | 414 | @param tracing: tracing configuration dictionary from agent |
402 | 415 | """ |
403 | | - # Check if we should apply agent config (lowest priority) |
404 | | - should_apply_agent_config = ( |
405 | | - "INSTANA_STACK_TRACE" not in os.environ |
406 | | - and "INSTANA_STACK_TRACE_LENGTH" not in os.environ |
407 | | - and "INSTANA_CONFIG_PATH" not in os.environ |
408 | | - and not ( |
409 | | - isinstance(config.get("tracing"), dict) |
410 | | - and "global" in config["tracing"] |
411 | | - and ("stack_trace" in config["tracing"]["global"] or "stack_trace_length" in config["tracing"]["global"]) |
412 | | - ) |
413 | | - ) |
414 | | - |
415 | | - if should_apply_agent_config and "global" in tracing: |
416 | | - global_config = tracing["global"] |
417 | | - |
418 | | - # Set stack-trace level from agent config |
419 | | - if "stack-trace" in global_config: |
420 | | - level = str(global_config["stack-trace"]).lower() |
421 | | - if level in ["all", "error", "none"]: |
422 | | - self.stack_trace_level = level |
423 | | - else: |
424 | | - logger.warning( |
425 | | - f"Invalid stack-trace value in agent config: {level}. Must be 'all', 'error', or 'none'. Using default 'all'" |
426 | | - ) |
427 | | - |
428 | | - # Set stack-trace length from agent config |
429 | | - if "stack-trace-length" in global_config: |
430 | | - try: |
431 | | - length = int(global_config["stack-trace-length"]) |
432 | | - if length >= 1: |
433 | | - self.stack_trace_length = length |
434 | | - else: |
435 | | - logger.warning( |
436 | | - "stack-trace-length must be positive. Using default 30" |
437 | | - ) |
438 | | - except (ValueError, TypeError): |
439 | | - logger.warning( |
440 | | - "Invalid stack-trace-length in agent config. Must be an integer. Using default 30" |
441 | | - ) |
| 416 | + # Apply global config if no higher priority source exists |
| 417 | + if self._should_apply_agent_global_config() and "global" in tracing: |
| 418 | + self._apply_agent_global_stack_trace_config(tracing["global"]) |
442 | 419 |
|
443 | | - # Technology-specific stack trace configuration from agent config |
444 | | - # Only apply if not already set by higher priority sources (YAML or in-code config) |
445 | | - # If stack_trace_technology_config is already populated, it means YAML or in-code config set it |
| 420 | + # Apply technology-specific config if not already set by YAML or in-code config |
446 | 421 | if not self.stack_trace_technology_config: |
447 | | - # Apply technology-specific overrides from agent config |
448 | | - # Example: kafka, redis, mysql, postgres, mongo, etc. |
449 | | - for tech_name, tech_config in tracing.items(): |
450 | | - if tech_name == "global" or not isinstance(tech_config, dict): |
451 | | - continue |
452 | | - |
453 | | - tech_stack_config = {} |
454 | | - |
455 | | - if "stack-trace" in tech_config: |
456 | | - level = str(tech_config["stack-trace"]).lower() |
457 | | - if level in ["all", "error", "none"]: |
458 | | - tech_stack_config["level"] = level |
459 | | - else: |
460 | | - logger.warning( |
461 | | - f"Invalid stack-trace value for {tech_name}: {level}. Ignoring." |
462 | | - ) |
463 | | - |
464 | | - if "stack-trace-length" in tech_config: |
465 | | - try: |
466 | | - length = int(tech_config["stack-trace-length"]) |
467 | | - if length >= 1: |
468 | | - tech_stack_config["length"] = length |
469 | | - else: |
470 | | - logger.warning( |
471 | | - f"stack-trace-length for {tech_name} must be positive. Ignoring." |
472 | | - ) |
473 | | - except (ValueError, TypeError): |
474 | | - logger.warning( |
475 | | - f"Invalid stack-trace-length for {tech_name}. Must be an integer. Ignoring." |
476 | | - ) |
477 | | - |
478 | | - if tech_stack_config: |
479 | | - self.stack_trace_technology_config[tech_name] = tech_stack_config |
| 422 | + self._apply_agent_tech_stack_trace_config(tracing) |
480 | 423 |
|
481 | 424 | def set_disable_tracing(self, tracing_config: Sequence[Dict[str, Any]]) -> None: |
482 | 425 | # The precedence is as follows: |
|
0 commit comments