-
Notifications
You must be signed in to change notification settings - Fork 1
Add is_whitelisted tag to captcha metrics #104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,25 +33,29 @@ public MetricsService(MeterRegistry meterRegistry, DifficultyService difficultyS | |
} | ||
|
||
public void recordChallengeRequest(String siteKey, long difficulty, SourceAddress sourceAddress) { | ||
final boolean isWhitelisted = difficultyService.isSourceAddressWhitelisted(siteKey, sourceAddress); | ||
long sameSourceAddressRequestCount = getSameSourceAddressRequestCount(sourceAddress); | ||
|
||
Counter.builder("captcha.challenge.requests") | ||
.tag("site_key", siteKey) | ||
.tag("difficulty", String.valueOf(difficulty)) | ||
.tag("same_source_address_request_count", String.valueOf(sameSourceAddressRequestCount)) | ||
.tag("is_whitelisted", String.valueOf(isWhitelisted)) | ||
.description("Counter for captcha challenge requests") | ||
.register(meterRegistry) | ||
.increment(); | ||
} | ||
|
||
public void recordVerifySuccess(String siteKey, SourceAddress sourceAddress) { | ||
final long difficulty = difficultyService.getDifficultyForSourceAddress(siteKey, sourceAddress); | ||
final boolean isWhitelisted = difficultyService.isSourceAddressWhitelisted(siteKey, sourceAddress); | ||
long sameSourceAddressRequestCount = getSameSourceAddressRequestCount(sourceAddress); | ||
|
||
Counter.builder("captcha.verify.success") | ||
.tag("site_key", siteKey) | ||
.tag("difficulty", String.valueOf(difficulty)) | ||
.tag("same_source_address_request_count", String.valueOf(sameSourceAddressRequestCount)) | ||
.tag("is_whitelisted", String.valueOf(isWhitelisted)) | ||
.description("Counter for captcha verify success requests") | ||
Comment on lines
+51
to
59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Avoid duplicate lookups if possible. If DifficultyService can expose a single call returning both difficulty and whitelisted status, prefer that to reduce I/O/CPU on hot paths. Otherwise, LGTM. 🤖 Prompt for AI Agents
|
||
.register(meterRegistry) | ||
.increment(); | ||
|
@@ -64,12 +68,14 @@ public void recordClientSolveTime(String siteKey, SourceAddress sourceAddress, L | |
} | ||
|
||
final long difficulty = difficultyService.getDifficultyForSourceAddress(siteKey, sourceAddress); | ||
final boolean isWhitelisted = difficultyService.isSourceAddressWhitelisted(siteKey, sourceAddress); | ||
long sameSourceAddressRequestCount = getSameSourceAddressRequestCount(sourceAddress); | ||
|
||
DistributionSummary.builder("captcha.client.solve.time") | ||
.tag("site_key", siteKey) | ||
.tag("difficulty", String.valueOf(difficulty)) | ||
.tag("same_source_address_request_count", String.valueOf(sameSourceAddressRequestCount)) | ||
.tag("is_whitelisted", String.valueOf(isWhitelisted)) | ||
.description("Summary of the time taken by clients to solve captcha challenges") | ||
Comment on lines
70
to
79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Consistent tagging; please add whitelisted-path coverage. Tagging is consistent. Add tests that assert is_whitelisted=true for verify and client.solve.time as well. 🤖 Prompt for AI Agents
|
||
.baseUnit("milliseconds") | ||
.register(meterRegistry) | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -55,6 +55,7 @@ class CaptchaControllerTest { | |||||
private static final String TEST_SITE_SECRET = "test_secret"; | ||||||
private static final String TEST_HMAC_KEY = "secret"; | ||||||
private static final String TEST_CLIENT_ADDRESS = "1.2.3.4"; | ||||||
private static final String TEST_WHITELISTED_ADDRESS = "10.0.0.0"; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Use a host address, not the network address. 10.0.0.0 can be treated as a network address. Prefer 10.0.0.1 (still private/whitelisted) to avoid edge‑case parser behavior. - private static final String TEST_WHITELISTED_ADDRESS = "10.0.0.0";
+ private static final String TEST_WHITELISTED_ADDRESS = "10.0.0.1"; 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||
private static final ExtendedPayload TEST_PAYLOAD; | ||||||
|
||||||
static { | ||||||
|
@@ -236,6 +237,28 @@ void postVerify_expired() { | |||||
} | ||||||
} | ||||||
|
||||||
@Test | ||||||
@SneakyThrows | ||||||
void testChallengeMetricsWhiteListedSourceAddress() { | ||||||
final PostChallengeRequest challengeRequest = new PostChallengeRequest(TEST_SITE_KEY, TEST_SITE_SECRET, TEST_WHITELISTED_ADDRESS); | ||||||
final String challengeRequestBody = objectMapper.writeValueAsString(challengeRequest); | ||||||
|
||||||
mockMvc.perform( | ||||||
post("/api/v1/captcha/challenge") | ||||||
.content(challengeRequestBody) | ||||||
.contentType(MediaType.APPLICATION_JSON)) | ||||||
.andExpect(status().isOk()); | ||||||
|
||||||
mockMvc.perform( | ||||||
get("/actuator/metrics/captcha.challenge.requests")) | ||||||
.andExpect(status().isOk()) | ||||||
.andExpect(jsonPath("$.measurements[0].value", is(1.0))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='difficulty')].values[0]", hasItem("1"))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='site_key')].values[0]", hasItem("test_site"))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='same_source_address_request_count')].values[*]", hasItem("1"))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='is_whitelisted')].values[0]", hasItem("true"))); | ||||||
} | ||||||
Comment on lines
+240
to
+260
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Stabilize test preconditions and whitelist source.
@Test
@SneakyThrows
void testChallengeMetricsWhiteListedSourceAddress() {
+ databaseTestUtil.clearDatabase();
final PostChallengeRequest challengeRequest = new PostChallengeRequest(TEST_SITE_KEY, TEST_SITE_SECRET, TEST_WHITELISTED_ADDRESS); If needed, I can add a @DynamicPropertySource to inject the whitelist CIDR for tests.
|
||||||
|
||||||
@Test | ||||||
@SneakyThrows | ||||||
void testChallengeMetricsIncrement() { | ||||||
|
@@ -256,7 +279,8 @@ void testChallengeMetricsIncrement() { | |||||
.andExpect(jsonPath("$.measurements[0].value", is((double) i))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='difficulty')].values[0]", hasItem("1000"))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='site_key')].values[0]", hasItem("test_site"))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='same_source_address_request_count')].values[*]", hasItem(String.valueOf(i)))); | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='same_source_address_request_count')].values[*]", hasItem(String.valueOf(i)))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='is_whitelisted')].values[0]", hasItem("false"))); | ||||||
} | ||||||
} | ||||||
|
||||||
|
@@ -287,7 +311,8 @@ void testVerifyMetricsIncrement() { | |||||
.andExpect(jsonPath("$.measurements[0].value", is((double) i))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='difficulty')].values[0]", hasItem("1000"))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='site_key')].values[0]", hasItem("test_site"))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='same_source_address_request_count')]").exists()); | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='same_source_address_request_count')]").exists()) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='is_whitelisted')].values[0]", hasItem("false"))); | ||||||
|
||||||
Comment on lines
+314
to
316
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Extend coverage to whitelisted verify/solve‑time. Consider adding mirror tests using TEST_WHITELISTED_ADDRESS to assert is_whitelisted=true for captcha.verify.success and captcha.client.solve.time. Also applies to: 324-326 🤖 Prompt for AI Agents
|
||||||
mockMvc.perform(get("/actuator/metrics/captcha.client.solve.time")) | ||||||
.andExpect(status().isOk()) | ||||||
|
@@ -296,7 +321,8 @@ void testVerifyMetricsIncrement() { | |||||
.andExpect(jsonPath("$.measurements[?(@.statistic=='MAX')].value", hasItem((double) TEST_PAYLOAD.getTook()))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='difficulty')].values[0]", hasItem("1000"))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='site_key')].values[0]", hasItem("test_site"))) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='same_source_address_request_count')]").exists()); | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='same_source_address_request_count')]").exists()) | ||||||
.andExpect(jsonPath("$.availableTags[?(@.tag=='is_whitelisted')].values[0]", hasItem("false"))); | ||||||
|
||||||
databaseTestUtil.clearDatabase(); | ||||||
} | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
New tag changes meter identity; also flag high-cardinality tag risk.
Apply this diff to drop the risky tag (not introduced by this PR, but strongly recommended):
Counter.builder("captcha.challenge.requests") .tag("site_key", siteKey) .tag("difficulty", String.valueOf(difficulty)) - .tag("same_source_address_request_count", String.valueOf(sameSourceAddressRequestCount)) .tag("is_whitelisted", String.valueOf(isWhitelisted))
To check for dashboards/alerts using this metric:
🏁 Script executed:
Length of output: 5720
Remove high‑cardinality tag "same_source_address_request_count" from all captcha metrics; coordinate any "is_whitelisted" identity change.
Apply this removal in each metric builder:
-.tag("same_source_address_request_count", String.valueOf(sameSourceAddressRequestCount))
📝 Committable suggestion