-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rate limiting based span drop (#318)
* add rate limiting config based span drop * additional test * helm config * fix config * add span drop counter * remove extra lines * fix indentation helm * address review comments * refactor
- Loading branch information
1 parent
3fe1e7a
commit 7b1c78b
Showing
7 changed files
with
163 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
...lizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/RateLimitingSpanFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package org.hypertrace.core.spannormalizer.jaeger; | ||
|
||
import com.typesafe.config.Config; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import org.hypertrace.core.datamodel.Event; | ||
|
||
public class RateLimitingSpanFilter { | ||
|
||
private static final String RATE_LIMIT_CONFIG_PATH = "rate.limit.config"; | ||
private static final String TENANT_ID_KEY = "tenantId"; | ||
private static final String GROUPING_KEY_KEY = "groupingKey"; | ||
private static final String MAX_SPANS_PER_MINUTE_KEY = "maxSpansPerMinute"; | ||
private static final long SPAN_COUNT_WINDOW = 3600; // fixed at 1minute | ||
|
||
Map<String, Map<Long, Long>> tenantSpanCountMap = new HashMap<>(); | ||
Map<String, Long> tenantMaxSpansPerMinuteMap = new HashMap<>(); | ||
Set<String> seenAttributes = new HashSet<>(); | ||
|
||
public RateLimitingSpanFilter(Config config) { | ||
for (Config rateLimitConfig : config.getConfigList(RATE_LIMIT_CONFIG_PATH)) { | ||
String tenantId = rateLimitConfig.getString(TENANT_ID_KEY); | ||
String groupingKey = rateLimitConfig.getString(GROUPING_KEY_KEY); | ||
String key = generateKey(tenantId, groupingKey); | ||
tenantMaxSpansPerMinuteMap.put(key, rateLimitConfig.getLong(MAX_SPANS_PER_MINUTE_KEY)); | ||
tenantSpanCountMap.put(key, Map.of(0L, 0L)); | ||
seenAttributes.add(groupingKey); | ||
} | ||
} | ||
|
||
public boolean shouldDropSpan(String tenantId, Event event) { | ||
boolean shouldDropSpan = false; | ||
for (String attribute : seenAttributes) { | ||
String key = generateKey(tenantId, attribute); | ||
if (!tenantMaxSpansPerMinuteMap.containsKey(key) | ||
|| !event.getAttributes().getAttributeMap().containsKey(attribute) | ||
|| !tenantSpanCountMap.containsKey(key)) { | ||
continue; | ||
} | ||
|
||
Long startTimeKey = tenantSpanCountMap.get(key).keySet().iterator().next(); | ||
if (event.getStartTimeMillis() - startTimeKey > SPAN_COUNT_WINDOW) { | ||
tenantSpanCountMap.put(key, Map.of(event.getStartTimeMillis(), 1L)); | ||
} else { | ||
long currentProcessedSpansCount = tenantSpanCountMap.get(key).get(startTimeKey); | ||
if (currentProcessedSpansCount >= tenantMaxSpansPerMinuteMap.get(key)) { | ||
shouldDropSpan = true; | ||
} | ||
tenantSpanCountMap.put(key, Map.of(startTimeKey, currentProcessedSpansCount + 1)); | ||
} | ||
} | ||
return shouldDropSpan; | ||
} | ||
|
||
private String generateKey(String first, String second) { | ||
return first + "/" + second; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,3 +61,5 @@ span.rules.exclude { | |
expireAfterWriteDuration = 5m | ||
} | ||
} | ||
|
||
rate.limit.config = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,3 +83,4 @@ span.rules.exclude { | |
} | ||
} | ||
|
||
rate.limit.config = [] |