Skip to content

Commit 9ab58e1

Browse files
committed
fix: Remove previous ignore-endpoint configuration parse mechanism and adapt configuration functions.
Signed-off-by: Cagri Yonca <cagri@ibm.com>
1 parent 957924f commit 9ab58e1

6 files changed

Lines changed: 380 additions & 274 deletions

File tree

src/instana/options.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727
get_disable_trace_configurations_from_yaml,
2828
get_stack_trace_config_from_yaml,
2929
is_truthy,
30-
parse_filtered_endpoints,
31-
parse_filtered_endpoints_from_yaml,
30+
parse_filter_rules,
31+
parse_filter_rules_yaml,
3232
parse_span_disabling,
33-
parse_span_filter_env_vars,
33+
parse_filter_rules_env_vars,
3434
parse_technology_stack_trace_config,
3535
validate_stack_trace_length,
3636
validate_stack_trace_level,
@@ -120,6 +120,7 @@ def set_trace_configurations(self) -> None:
120120
self.set_span_filter_configurations()
121121

122122
def _add_instana_agent_span_filter(self) -> None:
123+
"""Add Instana agent span filter to exclude internal spans."""
123124
if "exclude" not in self.span_filters:
124125
self.span_filters["exclude"] = []
125126
self.span_filters["exclude"].extend(
@@ -253,15 +254,15 @@ def set_span_filter_configurations(self) -> None:
253254
# > agent config (configuration.yaml) > default value
254255
if any(k.startswith("INSTANA_TRACING_FILTER_") for k in os.environ):
255256
# Check for new span filtering env vars
256-
parsed_filter = parse_span_filter_env_vars()
257+
parsed_filter = parse_filter_rules_env_vars()
257258
if parsed_filter["exclude"] or parsed_filter["include"]:
258259
self.span_filters = parsed_filter
259260
elif "INSTANA_CONFIG_PATH" in os.environ:
260-
self.span_filters = parse_filtered_endpoints_from_yaml(
261+
self.span_filters = parse_filter_rules_yaml(
261262
os.environ["INSTANA_CONFIG_PATH"]
262263
)
263264
elif isinstance(config.get("tracing"), dict) and "filter" in config["tracing"]:
264-
self.span_filters = parse_filtered_endpoints(
265+
self.span_filters = parse_filter_rules(
265266
config["tracing"]["filter"],
266267
)
267268

@@ -374,7 +375,7 @@ def set_tracing(self, tracing: Dict[str, Any]) -> None:
374375
@return: None
375376
"""
376377
if "filter" in tracing and not self.span_filters:
377-
self.span_filters = parse_filtered_endpoints(tracing["filter"])
378+
self.span_filters = parse_filter_rules(tracing["filter"])
378379

379380
if "kafka" in tracing:
380381
if (

src/instana/util/config.py

Lines changed: 69 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -42,46 +42,54 @@
4242
}
4343

4444

45-
def parse_service_pair(pair: str) -> List[str]:
45+
def parse_filter_rules_string(
46+
params: str,
47+
intermediate: Dict[str, Any],
48+
policy: str,
49+
name: str,
50+
) -> Dict[str, List[str]]:
51+
"""
52+
Parses a string to prepare filtered endpoint rules.
53+
54+
@param params: String format with rules separated by '|':
55+
- "key;values;match_type|key;values;match_type"
56+
- Example: "http.target;/health;strict|kafka.service;topic1,topic2;strict"
57+
- match_type is optional and defaults to "strict"
58+
@param intermediate: Dictionary to store parsed rules
59+
@param policy: Policy type ("exclude" or "include")
60+
@param name: Name of the filter rule
61+
@return: Updated intermediate dictionary with parsed attribute rules
4662
"""
47-
Parses a pair string to prepare a list of ignored endpoints.
48-
49-
@param pair: String format:
50-
- "service1:method1,method2" or "service1:method1" or "service1"
51-
@return: List of strings in format ["service1.method1", "service1.method2", "service2.*"]
52-
"""
53-
pair_list = []
54-
if ":" in pair:
55-
service, methods = pair.split(":", 1)
56-
service = service.strip()
57-
method_list = [ep.strip() for ep in methods.split(",") if ep.strip()]
63+
try:
64+
# Rule format: key;values;match_type|key;values;match_type
65+
rules = params.split("|")
66+
for rule in rules:
67+
rule_parts = rule.split(";")
68+
if len(rule_parts) < 2:
69+
continue
5870

59-
for method in method_list:
60-
pair_list.append(f"{service}.{method}")
61-
else:
62-
pair_list.append(f"{pair}.*")
63-
return pair_list
71+
key = rule_parts[0].strip()
72+
values_str = rule_parts[1]
73+
match_type = (
74+
rule_parts[2].strip().lower() if len(rule_parts) > 2 else "strict"
75+
)
6476

77+
# Split values by comma (simple split, assuming no commas in values or user handles escaping if needed?)
78+
# Spec says "values": Mandatory - List of Strings.
79+
# Env var examples: "http.target;/health" -> values=["/health"]
80+
# "kafka.service;topic1,topic2;strict" -> values=["topic1", "topic2"]
81+
values = [v.strip() for v in values_str.split(",") if v.strip()]
6582

66-
def parse_filtered_endpoints_string(params: Union[str, os.PathLike]) -> List[str]:
67-
"""
68-
Parses a string to prepare a list of ignored endpoints.
83+
attr_data = {"key": key, "values": values, "match_type": match_type}
84+
intermediate[policy][name]["attributes"].append(attr_data)
6985

70-
@param params: String format:
71-
- "service1:method1,method2;service2:method3" or "service1;service2"
72-
@return: List of strings in format ["service1.method1", "service1.method2", "service2.*"]
73-
"""
74-
span_filters = []
75-
if params:
76-
service_pairs = params.lower().split(";")
77-
78-
for pair in service_pairs:
79-
if pair.strip():
80-
span_filters += parse_service_pair(pair)
81-
return span_filters
86+
return intermediate
87+
except Exception as e:
88+
logger.error(f"Failed to parse filter params: {e}")
89+
return {}
8290

8391

84-
def parse_filtered_endpoints_dict(filter_dict: Dict[str, Any]) -> Dict[str, List[Any]]:
92+
def parse_filter_rules_dict(filter_dict: Dict[str, Any]) -> Dict[str, List[Any]]:
8593
"""
8694
Parses 'exclude' and 'include' blocks from the filter dict.
8795
@@ -132,37 +140,36 @@ def parse_filtered_endpoints_dict(filter_dict: Dict[str, Any]) -> Dict[str, List
132140
return {"exclude": [], "include": []}
133141

134142

135-
def parse_filtered_endpoints(
136-
params: Union[Dict[str, Any], str],
137-
) -> Union[List[str], Dict[str, List[Any]]]:
143+
def parse_filter_rules(
144+
params: Dict[str, Any],
145+
) -> Dict[str, List[Any]]:
138146
"""
139-
Parses input to prepare a list for ignored endpoints.
147+
Parses input to prepare filtered endpoints.
140148
141-
@param params: Can be either:
142-
- String: "service1:method1,method2;service2:method3" or "service1;service2"
143-
- Dict: {"exclude": [{"name": "foo", "attributes": ...}], "include": []}
144-
@return: List of strings in format ["service1.method1", "service1.method2", "service2.*"]
149+
@param params: Dict with structure:
150+
{"exclude": [{"name": "foo", "attributes": ...}], "include": [{"name": "foo", "attributes": ...}]}
151+
@return: Dict with structure {"exclude": [...], "include": [...]}
145152
"""
146153
try:
147-
if isinstance(params, str):
148-
return parse_filtered_endpoints_string(params)
149-
elif isinstance(params, dict):
150-
return parse_filtered_endpoints_dict(params)
151-
else:
152-
return []
154+
return parse_filter_rules_dict(params)
153155
except Exception as e:
154-
logger.debug("Error parsing ignored endpoints: %s", str(e))
155-
return []
156+
logger.debug("Error parsing filtered endpoints: %s", str(e))
157+
return {}
156158

157159

158-
def parse_filtered_endpoints_from_yaml(
160+
def parse_filter_rules_yaml(
159161
file_path: str,
160-
) -> Union[List[str], Dict[str, List[Any]]]:
162+
) -> Dict[str, List[Any]]:
161163
"""
162-
Parses configuration yaml file and prepares a list of ignored endpoints.
164+
Parses configuration YAML file and prepares filtered endpoint rules.
163165
164-
@param file_path: Path of the file as a string
165-
@return: List of strings in format ["service1.method1", "service1.method2", "service2.*", "kafka.method.topic", "kafka.*.topic", "kafka.method.*"]
166+
@param file_path: Path to the YAML configuration file
167+
@return: Dictionary containing parsed filter rules with structure:
168+
{
169+
"exclude": [{"name": str, "suppression": bool, "attributes": [{"key": str, "values": list, "match_type": str}]}],
170+
"include": [{"name": str, "suppression": None, "attributes": [{"key": str, "values": list, "match_type": str}]}]
171+
}
172+
Returns empty dict {} if no filter configuration is found or on error.
166173
"""
167174
config_reader = ConfigReader(file_path)
168175
span_filters_dict = None
@@ -172,13 +179,13 @@ def parse_filtered_endpoints_from_yaml(
172179
logger.warning(DEPRECATED_CONFIG_KEY_WARNING)
173180
span_filters_dict = config_reader.data["com.instana.tracing"].get("filter")
174181
if span_filters_dict:
175-
span_filters = parse_filtered_endpoints(span_filters_dict)
182+
span_filters = parse_filter_rules(span_filters_dict)
176183
return span_filters
177184
else:
178185
return {}
179186

180187

181-
def parse_span_filter_env_vars() -> Dict[str, List[Any]]:
188+
def parse_filter_rules_env_vars() -> Dict[str, List[Any]]:
182189
"""
183190
Parses INSTANA_TRACING_FILTER_<POLICY>_<NAME>_ATTRIBUTES environment variables.
184191
@@ -216,27 +223,12 @@ def parse_span_filter_env_vars() -> Dict[str, List[Any]]:
216223
}
217224

218225
if suffix == "ATTRIBUTES":
219-
# Rule format: key;values;match_type|key;values;match_type
220-
rules = env_value.split("|")
221-
for rule in rules:
222-
rule_parts = rule.split(";")
223-
if len(rule_parts) < 2:
224-
continue
225-
226-
key = rule_parts[0].strip()
227-
values_str = rule_parts[1]
228-
match_type = (
229-
rule_parts[2].strip().lower() if len(rule_parts) > 2 else "strict"
230-
)
231-
232-
# Split values by comma (simple split, assuming no commas in values or user handles escaping if needed?)
233-
# Spec says "values": Mandatory - List of Strings.
234-
# Env var examples: "http.target;/health" -> values=["/health"]
235-
# "kafka.service;topic1,topic2;strict" -> values=["topic1", "topic2"]
236-
values = [v.strip() for v in values_str.split(",") if v.strip()]
237-
238-
attr_data = {"key": key, "values": values, "match_type": match_type}
239-
intermediate[policy][name]["attributes"].append(attr_data)
226+
intermediate = parse_filter_rules_string(
227+
env_value,
228+
intermediate,
229+
policy,
230+
name,
231+
)
240232

241233
elif suffix == "SUPPRESSION" and policy == "exclude":
242234
intermediate[policy][name]["suppression"] = is_truthy(env_value)

0 commit comments

Comments
 (0)