Skip to content

Commit b82a852

Browse files
committed
refactor(stack_trace): create helper functions to eliminate repetition
Signed-off-by: Varsha GS <[email protected]>
1 parent 929a7df commit b82a852

File tree

3 files changed

+126
-150
lines changed

3 files changed

+126
-150
lines changed

src/instana/options.py

Lines changed: 31 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
parse_ignored_endpoints,
3131
parse_ignored_endpoints_from_yaml,
3232
parse_span_disabling,
33+
parse_technology_stack_trace_config,
34+
validate_stack_trace_length,
35+
validate_stack_trace_level,
3336
)
3437
from instana.util.runtime import determine_service_name
3538

@@ -140,27 +143,16 @@ def set_stack_trace_configurations(self) -> None:
140143
"""
141144
# 1. Environment variables (highest priority)
142145
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-
)
146+
if validated_level := validate_stack_trace_level(
147+
os.environ["INSTANA_STACK_TRACE"], "from INSTANA_STACK_TRACE"
148+
):
149+
self.stack_trace_level = validated_level
150150

151151
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-
)
152+
if validated_length := validate_stack_trace_length(
153+
os.environ["INSTANA_STACK_TRACE_LENGTH"], "from INSTANA_STACK_TRACE_LENGTH"
154+
):
155+
self.stack_trace_length = validated_length
164156

165157
# 2. INSTANA_CONFIG_PATH (YAML file) - includes tech-specific overrides
166158
elif "INSTANA_CONFIG_PATH" in os.environ:
@@ -177,57 +169,24 @@ def set_stack_trace_configurations(self) -> None:
177169
global_config = config["tracing"]["global"]
178170

179171
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-
)
172+
if validated_level := validate_stack_trace_level(global_config["stack_trace"], "in local in-code config"):
173+
self.stack_trace_level = validated_level
187174

188175
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-
)
176+
if validated_length := validate_stack_trace_length(global_config["stack_trace_length"], "in local in-code config"):
177+
self.stack_trace_length = validated_length
201178

202179
# Technology-specific overrides from in-code config
203180
for tech_name, tech_data in config["tracing"].items():
204181
if tech_name == "global" or not isinstance(tech_data, dict):
205182
continue
206183

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-
)
184+
tech_stack_config = parse_technology_stack_trace_config(
185+
tech_data,
186+
level_key="stack_trace",
187+
length_key="stack_trace_length",
188+
tech_name=tech_name
189+
)
231190

232191
if tech_stack_config:
233192
self.stack_trace_technology_config[tech_name] = tech_stack_config
@@ -417,28 +376,13 @@ def set_stack_trace_from_agent(self, tracing: Dict[str, Any]) -> None:
417376

418377
# Set stack-trace level from agent config
419378
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-
)
379+
if validated_level := validate_stack_trace_level(global_config["stack-trace"], "in agent config"):
380+
self.stack_trace_level = validated_level
427381

428382
# Set stack-trace length from agent config
429383
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-
)
384+
if validated_length := validate_stack_trace_length(global_config["stack-trace-length"], "in agent config"):
385+
self.stack_trace_length = validated_length
442386

443387
# Technology-specific stack trace configuration from agent config
444388
# Only apply if not already set by higher priority sources (YAML or in-code config)
@@ -450,30 +394,12 @@ def set_stack_trace_from_agent(self, tracing: Dict[str, Any]) -> None:
450394
if tech_name == "global" or not isinstance(tech_config, dict):
451395
continue
452396

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-
)
397+
tech_stack_config = parse_technology_stack_trace_config(
398+
tech_config,
399+
level_key="stack-trace",
400+
length_key="stack-trace-length",
401+
tech_name=tech_name
402+
)
477403

478404
if tech_stack_config:
479405
self.stack_trace_technology_config[tech_name] = tech_stack_config

src/instana/util/config.py

Lines changed: 93 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,89 @@ def get_disable_trace_configurations_from_local() -> Tuple[List[str], List[str]]
319319
return [], []
320320

321321

322+
def validate_stack_trace_level(level_value: Any, context: str = "") -> Union[str, None]:
323+
"""
324+
Validate stack trace level value.
325+
326+
Args:
327+
level_value: The level value to validate
328+
context: Context string for error messages (e.g., "for kafka", "in agent config")
329+
330+
Returns:
331+
Validated level string ("all", "error", or "none"), or None if invalid
332+
"""
333+
level = str(level_value).lower()
334+
if level in ["all", "error", "none"]:
335+
return level
336+
337+
context_msg = f" {context}" if context else ""
338+
logger.warning(
339+
f"Invalid stack-trace value{context_msg}: {level}. Must be 'all', 'error', or 'none'. Using default 'all'."
340+
)
341+
return None
342+
343+
344+
def validate_stack_trace_length(length_value: Any, context: str = "") -> Union[int, None]:
345+
"""
346+
Validate stack trace length value.
347+
348+
Args:
349+
length_value: The length value to validate
350+
context: Context string for error messages (e.g., "for kafka", "in agent config")
351+
352+
Returns:
353+
Validated length integer (>= 1), or None if invalid
354+
"""
355+
try:
356+
length = int(length_value)
357+
if length >= 1:
358+
return length
359+
360+
context_msg = f" {context}" if context else ""
361+
logger.warning(
362+
f"stack-trace-length{context_msg} must be positive. Using default 30."
363+
)
364+
return None
365+
except (ValueError, TypeError):
366+
context_msg = f" {context}" if context else ""
367+
logger.warning(
368+
f"Invalid stack-trace-length{context_msg}. Must be an integer. Using default 30."
369+
)
370+
return None
371+
372+
373+
def parse_technology_stack_trace_config(
374+
tech_data: Dict[str, Any],
375+
level_key: str = "stack-trace",
376+
length_key: str = "stack-trace-length",
377+
tech_name: str = "",
378+
) -> Dict[str, Union[str, int]]:
379+
"""
380+
Parse technology-specific stack trace configuration from a dictionary.
381+
382+
Args:
383+
tech_data: Dictionary containing stack trace configuration
384+
level_key: Key name for level configuration (e.g., "stack-trace" or "stack_trace")
385+
length_key: Key name for length configuration (e.g., "stack-trace-length" or "stack_trace_length")
386+
tech_name: Technology name for error messages (e.g., "kafka", "redis")
387+
388+
Returns:
389+
Dictionary with "level" and/or "length" keys, or empty dict if no valid config
390+
"""
391+
tech_stack_config = {}
392+
context = f"for {tech_name}" if tech_name else ""
393+
394+
if level_key in tech_data:
395+
if validated_level := validate_stack_trace_level(tech_data[level_key], context):
396+
tech_stack_config["level"] = validated_level
397+
398+
if length_key in tech_data:
399+
if validated_length := validate_stack_trace_length(tech_data[length_key], context):
400+
tech_stack_config["length"] = validated_length
401+
402+
return tech_stack_config
403+
404+
322405
def get_stack_trace_config_from_yaml() -> Tuple[str, int, Dict[str, Dict[str, Union[str, int]]]]:
323406
"""
324407
Get stack trace configuration from YAML file specified by INSTANA_CONFIG_PATH.
@@ -353,57 +436,24 @@ def get_stack_trace_config_from_yaml() -> Tuple[str, int, Dict[str, Dict[str, Un
353436
global_config = tracing_data["global"]
354437

355438
if "stack-trace" in global_config:
356-
config_level = global_config["stack-trace"].lower()
357-
if config_level in ["all", "error", "none"]:
358-
level = config_level
359-
else:
360-
logger.warning(
361-
f"Invalid stack-trace value in config: {config_level}. Must be 'all', 'error', or 'none'. Using default 'all'"
362-
)
439+
if validated_level := validate_stack_trace_level(global_config["stack-trace"], "in YAML config"):
440+
level = validated_level
363441

364442
if "stack-trace-length" in global_config:
365-
try:
366-
config_length = int(global_config["stack-trace-length"])
367-
if config_length >= 1:
368-
length = config_length
369-
else:
370-
logger.warning(
371-
"stack-trace-length must be positive. Using default 30"
372-
)
373-
except (ValueError, TypeError):
374-
logger.warning(
375-
"Invalid stack-trace-length in config. Must be an integer. Using default 30"
376-
)
443+
if validated_length := validate_stack_trace_length(global_config["stack-trace-length"], "in YAML config"):
444+
length = validated_length
377445

378446
# Read technology-specific overrides
379447
for tech_name, tech_data in tracing_data.items():
380448
if tech_name == "global" or not isinstance(tech_data, dict):
381449
continue
382450

383-
tech_stack_config = {}
384-
385-
if "stack-trace" in tech_data:
386-
tech_level = str(tech_data["stack-trace"]).lower()
387-
if tech_level in ["all", "error", "none"]:
388-
tech_stack_config["level"] = tech_level
389-
else:
390-
logger.warning(
391-
f"Invalid stack-trace value for {tech_name} in YAML: {tech_level}. Ignoring."
392-
)
393-
394-
if "stack-trace-length" in tech_data:
395-
try:
396-
tech_length = int(tech_data["stack-trace-length"])
397-
if tech_length >= 1:
398-
tech_stack_config["length"] = tech_length
399-
else:
400-
logger.warning(
401-
f"stack-trace-length for {tech_name} must be positive. Ignoring."
402-
)
403-
except (ValueError, TypeError):
404-
logger.warning(
405-
f"Invalid stack-trace-length for {tech_name} in YAML. Must be an integer. Ignoring."
406-
)
451+
tech_stack_config = parse_technology_stack_trace_config(
452+
tech_data,
453+
level_key="stack-trace",
454+
length_key="stack-trace-length",
455+
tech_name=tech_name
456+
)
407457

408458
if tech_stack_config:
409459
tech_config[tech_name] = tech_stack_config

tests/test_options.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ def test_stack_trace_level_env_var_invalid(
685685
self.options = BaseOptions()
686686
assert self.options.stack_trace_level == "all" # Falls back to default
687687
assert any(
688-
"Invalid INSTANA_STACK_TRACE value" in message
688+
"Invalid stack-trace value from INSTANA_STACK_TRACE" in message
689689
for message in caplog.messages
690690
)
691691

@@ -712,7 +712,7 @@ def test_stack_trace_length_env_var(
712712
[
713713
("0", "must be positive"),
714714
("-5", "must be positive"),
715-
("invalid", "Invalid INSTANA_STACK_TRACE_LENGTH"),
715+
("invalid", "Invalid stack-trace-length from INSTANA_STACK_TRACE_LENGTH"),
716716
],
717717
)
718718
def test_stack_trace_length_env_var_invalid(

0 commit comments

Comments
 (0)