Skip to content

Commit ba3fe2e

Browse files
author
Serhii Vydiuk
committed
User data collection custom implementation + docs updated
1 parent 9a04ef1 commit ba3fe2e

File tree

4 files changed

+163
-22
lines changed

4 files changed

+163
-22
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.readme.example;
2+
3+
import com.readme.dataextraction.UserDataCollector;
4+
import com.readme.domain.UserData;
5+
import com.readme.starter.datacollection.ServletDataPayloadAdapter;
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
9+
/**
10+
* Configuration class for customizing the strategy to collect user data.
11+
*
12+
* <p>This configuration provides a custom implementation of {@link UserDataCollector},
13+
* which overrides the default behavior provided by the SDK. It allows developers
14+
* to specify their own logic for extracting user-specific information, such as API keys,
15+
* email addresses, or labels, from the incoming HTTP requests.</p>
16+
*
17+
* <p>In this example, the API key is extracted from the HTTP headers using the header
18+
* "X-User-Name", while the email and label fields are hardcoded with custom values.
19+
* Developers can modify this logic to suit their application's requirements.</p>
20+
*
21+
* <p>By defining this bean, Spring Boot's auto-configuration will automatically use
22+
* this custom implementation instead of the default {@link UserDataCollector}.</p>
23+
*/
24+
@Configuration
25+
public class CustomUserDataCollectorConfig {
26+
27+
//Uncomment the code below to have a custom user data collection configuration.
28+
//It automatically overrides the default one
29+
30+
31+
// @Bean
32+
// public UserDataCollector<ServletDataPayloadAdapter> customUserDataCollector() {
33+
// return payloadAdapter -> {
34+
// String apiKey = payloadAdapter.getRequestHeaders().get("x-user-name");
35+
// return UserData.builder()
36+
// .apiKey(apiKey)
37+
// .email("[email protected]")
38+
// .label("owl-label")
39+
// .build();
40+
// };
41+
// }
42+
}
Lines changed: 107 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,134 @@
1-
# Monitoring Library Configuration Guide
1+
## Table of Contents
2+
1. [Overview](#overview)
3+
2. [Configuration](#configuration)
4+
- [Readme API Key](#readme-api-key)
5+
- [User data configuration ](#userdata-configuration)
6+
- [Custom user data collection config](#customizing-user-data-collection)
7+
8+
---
29

310
## Overview
411

5-
This spring-boot-starter provides possibility to integrate Readme Metrics SDK to a Spring Boot application easily.
6-
It provides a convenient way to extract user-specific information (e.g., api-key, email, label) from
7-
incoming HTTP requests. It allows configuring multiple extraction methods, such as HTTP headers, JWT claims, or JSON body fields.
12+
This library provides an easy way to integrate the ReadMe Metrics into a Spring Boot application,
13+
enabling comprehensive monitoring and logging capabilities.
14+
The SDK is designed to collect detailed information from HTTP requests and responses, as well as user-specific data,
15+
for better observability and insights into application behavior.
16+
17+
### Key Features:
18+
1. **Request and Response Data Logging**:
19+
- Collects HTTP request and response details, including headers, body content, and HTTP status codes.
20+
- Ensures minimal impact on the application's core business logic by leveraging efficient wrappers for request and response processing.
21+
22+
2. **User Data Extraction**:
23+
- Logs information about the user making the request, such as `api-key`, `email`, and `label`.
24+
- Supports multiple configurable data extraction methods:
25+
- **HTTP headers**
26+
- **JWT claims**
27+
- **JSON body fields**
28+
29+
---
830

931
## Configuration
1032

11-
Add the following properties to your `application.yaml` or `application.properties` file.
12-
Each field (`apiKey`, `email`, `label`) requires two sub-properties:
13-
- `source`: Defines where to extract the data from.
33+
To configure the library, you need to define two main aspects:
34+
1. The `ReadMe API Key`, which is required to send logged data to the ReadMe platform.
35+
2. The `UserData` fields (`apiKey`, `email`, `label`), which define where to extract user-specific information from incoming requests.
36+
37+
### ReadMe API Key configuration
38+
39+
The `ReadMe API Key` is a unique identifier that you receive from the ReadMe platform. It is used to authenticate and authorize data sent to the ReadMe metrics endpoint.
40+
You can configure the `ReadMe API Key` in your `application.yaml` or `application.properties` file using environment variables for security.
41+
42+
**application.yaml:**
43+
```yaml
44+
readme:
45+
readmeApiKey: ${README_API_KEY}
46+
```
47+
**application.properties:**
48+
```properties
49+
readme.readmeApiKey=${README_API_KEY}
50+
```
51+
52+
### UserData configuration
53+
54+
The library allows you to extract user-specific data (`apiKey`, `email`, `label`) from incoming HTTP requests. Each field requires two properties:
55+
- **`source`**: Specifies where to extract the data from.
1456
- Possible values:
15-
- `header`: Extracts data from an HTTP header.
16-
- `jwtClaim`: Extracts data from a JWT token claim.
17-
- `jsonBody`: Extracts data from the JSON body of a request.
18-
- `fieldName`: Specifies the name or key associated with the source.
57+
- `header`: Extracts data from an HTTP header.
58+
- `jwtClaim`: Extracts data from a JWT token claim.
59+
- `jsonBody`: Extracts data from the JSON body of a request.
60+
- **`fieldName`**: The key or field name corresponding to the specified source.
1961

20-
### Example Configuration (YAML)
62+
63+
**application.yaml:**
2164
```yaml
2265
readme:
23-
readmeApiKey: ${readmeApiKey}
2466
userdata:
2567
apiKey:
2668
source: header
2769
fieldName: X-User-Id
2870
email:
29-
source: jwt
71+
source: jwtClaim
3072
fieldName: aud
3173
label:
3274
source: jsonBody
33-
fieldName: user.name
75+
fieldName: user/name
3476
```
3577
36-
### Example Configuration (PROPERTIES)
78+
**application.properties:**
3779
```properties
3880
readme.userdata.apikey.source=header
3981
readme.userdata.apikey.fieldname=X-User-Id
4082

41-
readme.userdata.email.source=jwtClaim
83+
readme.userdata.email.source=jwt
4284
readme.userdata.email.fieldname=aud
4385

4486
readme.userdata.label.source=jsonBody
45-
readme.userdata.label.fieldname=user.name
46-
```
87+
readme.userdata.label.fieldname=user/name
88+
```
89+
90+
### Customizing user data collection
91+
92+
The library provides a default implementation of `UserDataCollector`, which extracts user data based on the configuration
93+
in your YAML or properties file. However, some use cases may require custom logic to extract user-specific information.
94+
For example:
95+
- The user data comes from a unique header format.
96+
- Complex logic is needed to determine user-specific fields.
97+
- Multiple fields need to be combined dynamically.
98+
99+
In such cases, you can configure the library with a custom way of extracting user data information
100+
by creating your own implementation of `UserDataCollector`.
101+
102+
---
103+
104+
#### How to Create a Custom UserDataCollector
105+
106+
To create a custom `UserDataCollector`, define a Spring bean for your implementation.
107+
The library's configuration will automatically use your custom implementation if it is present in the application context.
108+
109+
---
110+
111+
#### Example: Custom Implementation
112+
113+
Below is an example of a custom `UserDataCollector` that extracts the `apiKey` from an HTTP header and assigns static
114+
values for `email` and `label`.
115+
116+
```java
117+
@Configuration
118+
public class CustomUserDataCollectorConfig {
119+
120+
@Bean
121+
public UserDataCollector<ServletDataPayloadAdapter> customUserDataCollector() {
122+
return payloadAdapter -> {
123+
// Extract the apiKey from the request headers
124+
String apiKey = payloadAdapter.getRequestHeaders().get("x-user-name");
125+
126+
// Build the UserData object
127+
return UserData.builder()
128+
.apiKey(apiKey)
129+
130+
.label("owl-label")
131+
.build();
132+
};
133+
}
134+
}

packages/java/readme-metrics-spring-boot-starter/src/main/java/com/readme/starter/config/DataCollectionAutoConfiguration.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22

33
import com.readme.dataextraction.RequestDataCollector;
44
import com.readme.dataextraction.UserDataCollector;
5+
import com.readme.dataextraction.UserDataExtractor;
56
import com.readme.starter.datacollection.DataCollectionFilter;
67
import com.readme.starter.datacollection.ServletDataPayloadAdapter;
8+
import com.readme.starter.datacollection.userinfo.ServletUserDataCollector;
79
import lombok.AllArgsConstructor;
10+
import lombok.extern.log4j.Log4j;
11+
import lombok.extern.slf4j.Slf4j;
812
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
13+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
914
import org.springframework.boot.web.servlet.FilterRegistrationBean;
1015
import org.springframework.context.annotation.Bean;
1116
import org.springframework.context.annotation.ComponentScan;
@@ -24,9 +29,9 @@
2429
* </ul>
2530
*/
2631
@Configuration
27-
@ConditionalOnClass({UserDataProperties.class})
2832
@ComponentScan(basePackages = {"com.readme.starter"})
2933
@AllArgsConstructor
34+
@Slf4j
3035
public class DataCollectionAutoConfiguration {
3136

3237
@Bean
@@ -40,4 +45,11 @@ public FilterRegistrationBean<DataCollectionFilter> metricsFilter(
4045
return registrationBean;
4146
}
4247

48+
@Bean
49+
@ConditionalOnMissingBean(UserDataCollector.class)
50+
public UserDataCollector<ServletDataPayloadAdapter> userDataCollector(UserDataProperties userDataProperties,
51+
UserDataExtractor<ServletDataPayloadAdapter> extractionService) {
52+
log.info("readme-metrics: Creating of default user data collector");
53+
return new ServletUserDataCollector(userDataProperties, extractionService);
54+
}
4355
}

packages/java/readme-metrics-spring-boot-starter/src/main/java/com/readme/starter/datacollection/userinfo/ServletUserDataCollector.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import com.readme.starter.datacollection.ServletDataPayloadAdapter;
1010
import lombok.AllArgsConstructor;
1111
import lombok.extern.slf4j.Slf4j;
12-
import org.springframework.context.annotation.DependsOn;
12+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
1313
import org.springframework.stereotype.Component;
1414

1515
/**
@@ -23,7 +23,6 @@
2323
* Ensures flexibility and proper encapsulation of the strategy selection logic.
2424
*/
2525

26-
@Component
2726
@AllArgsConstructor
2827
@Slf4j
2928
public class ServletUserDataCollector implements UserDataCollector<ServletDataPayloadAdapter> {

0 commit comments

Comments
 (0)