Skip to content
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

Java Metrics SDK implementation (Spring Boot) #1179

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

serhii-vydiuk-kevychsolutions
Copy link
Collaborator

@serhii-vydiuk-kevychsolutions serhii-vydiuk-kevychsolutions commented Feb 27, 2025

What is done?

  • User request/response logging for Spring Boot 3+
  • Web hooks verification
  • Unit tests coverage
  • Documentation (README.md)

After testing it with Spring Boot 3+ and fixing bugs, we can add implementation for Spring Boot 2+. It will take about 1 working day to do required changes and test it.
Знімок екрана 2025-02-27 о 23 25 34
Знімок екрана 2025-02-27 о 23 26 11
Знімок екрана 2025-02-27 о 23 30 54

@erunion erunion added enhancement New feature or request java Issues related to our Java SDK labels Feb 27, 2025
Comment on lines +30 to +31
//Uncomment the code below to have a custom user data collection configuration.
//It automatically overrides the default one

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this comment still relevant?

.digest(apiKey.getBytes(StandardCharsets.UTF_8)));

String last4Digits = apiKey.substring(apiKey.length() - 4);
return "sha512-" + base64Hash + "?" + last4Digits;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason to use the encoding algo in the masked key value?

@@ -0,0 +1,19 @@
package com.readme.core.dataextraction;

import lombok.*;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a note, can we update the imports to only be what we need. This will increase compiled resource because we're importing things we don't need.

Comment on lines +11 to +17
List<String> allowlist;
List<String> denylist;
boolean development;
boolean fireAndForget;
String baseLogUrl;
@Builder.Default
int bufferLength = 1;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add comments explaining what these properties are. Some are self explanatory, but some aren't. Also for our team Java is not their native programming language, so providing more context for them will make future improvements and readability better.

Consider this a comment for all of the builders in this PR. Thank you.

List<String> denylist;
boolean development;
boolean fireAndForget;
String baseLogUrl;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this allowed to be null? If not hould this be marked as @nonnull

private static String getRequestParametersAsString(Map<String, String> requestParameters) {
return requestParameters.entrySet()
.stream()
.map(entry -> entry.getKey() + "=" + entry.getValue())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need a null check for the entry value? is null always an acceptable value for the possible query params?

try {
OutgoingLogBody outgoingLogBody = payloadConstructor.construct(payloadData, logOptions);
buffer.add(outgoingLogBody);
if (buffer.size() >= logOptions.getBufferLength()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if an operation completes and the buffer isn't over the size limit? How are the logs dispatched then?

@JsonAnySetter
public void setAdditionalField(String key, Object value) {
if (additional == null) {
additional = new HashMap<>(8);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you

  • change the 8 to a constant. Magic numbers aren't self documenting
  • it seems that many of the classes in this package use the same value to limit the additional HashMap size. Can you extract that so it can be used in both places from the same constant. Assuming they are supposed to have the same value.

Comment on lines +25 to +26
//TODO Fix:
// Handle Basic tokens as well as Bearer ones

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not seeing where this is being handled

Comment on lines +35 to +54
public String extractFromBody(ServletDataPayloadAdapter payload, String fieldPath) {
if (!payload.getRequestMethod().equalsIgnoreCase(HttpMethod.GET.name())) {
if (payload.getRequestContentType().equalsIgnoreCase("application/json")) {
String requestBody = payload.getRequestBody();
try {
JsonNode currentNode = objectMapper.readTree(requestBody);
if (!fieldPath.startsWith("/")) {
fieldPath = "/" + fieldPath;
}
return currentNode.at(fieldPath).asText();
} catch (Exception e) {
log.error("Error when reading the user data from JSON body: {}", e.getMessage());
}
}
log.error("The provided body content type {} is not supported to get user data.", payload.getRequestContentType());
return "";
}
log.error("The HTTP method {} is not supported to get user data from body.", payload.getRequestMethod());
return "";
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guard statements would make this much easier to read:

Suggested change
public String extractFromBody(ServletDataPayloadAdapter payload, String fieldPath) {
if (!payload.getRequestMethod().equalsIgnoreCase(HttpMethod.GET.name())) {
if (payload.getRequestContentType().equalsIgnoreCase("application/json")) {
String requestBody = payload.getRequestBody();
try {
JsonNode currentNode = objectMapper.readTree(requestBody);
if (!fieldPath.startsWith("/")) {
fieldPath = "/" + fieldPath;
}
return currentNode.at(fieldPath).asText();
} catch (Exception e) {
log.error("Error when reading the user data from JSON body: {}", e.getMessage());
}
}
log.error("The provided body content type {} is not supported to get user data.", payload.getRequestContentType());
return "";
}
log.error("The HTTP method {} is not supported to get user data from body.", payload.getRequestMethod());
return "";
}
public String extractFromBody(ServletDataPayloadAdapter payload, String fieldPath) {
if (payload.getRequestMethod().equalsIgnoreCase(HttpMethod.GET.name())) {
log.error("The HTTP method {} is not supported to get user data from body.", payload.getRequestMethod());
return "";
}
if (!payload.getRequestContentType().equalsIgnoreCase("application/json")) {
log.error("The provided body content type {} is not supported to get user data.", payload.getRequestContentType());
return "";
}
String requestBody = payload.getRequestBody();
try {
JsonNode currentNode = objectMapper.readTree(requestBody);
if (!fieldPath.startsWith("/")) {
fieldPath = "/" + fieldPath;
}
return currentNode.at(fieldPath).asText();
} catch (Exception e) {
log.error("Error when reading the user data from JSON body: {}", e.getMessage());
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request java Issues related to our Java SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants