Skip to content

Commit f1e6e93

Browse files
authored
Merge pull request #160 from ruromero/client-name
feat: Enhance telemetry data
2 parents d201693 + 329c200 commit f1e6e93

File tree

4 files changed

+67
-34
lines changed

4 files changed

+67
-34
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,12 @@ The possible responses are:
213213

214214
## Telemetry
215215

216-
API Clients are expected to send a `rhda-token` HTTP Header that will be used to correlate
217-
different events related to the same user.
218-
If the header is not provided an anonymous event with a generated UUID will be sent instead.
216+
API Clients are expected to send the following HTTP Headers in order to help observe the use of the Backend service:
217+
218+
- `rhda-token` HTTP Header that will be used to correlate different events related to the same user. If the header
219+
is not provided an anonymous event with a generated UUID will be sent instead.
220+
- `rhda-source` The client consuming the Exhort API. It will default to the `User-Agent` HTTP Header
221+
- `rhda-operation-type` When performing an analysis, clients might specify whether it is a component-analysis or a stack-analysis
219222

220223
Telemetry connects to [Segment](https://segment.com/) for sending events.
221224
The connection can be configured with the following properties.

src/main/java/com/redhat/exhort/analytics/AnalyticsService.java

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.concurrent.atomic.AtomicLong;
2727

2828
import org.apache.camel.Exchange;
29+
import org.apache.camel.Message;
2930
import org.eclipse.microprofile.config.inject.ConfigProperty;
3031
import org.eclipse.microprofile.rest.client.inject.RestClient;
3132
import org.slf4j.Logger;
@@ -51,7 +52,11 @@ public class AnalyticsService {
5152

5253
private static final Logger LOGGER = LoggerFactory.getLogger(AnalyticsService.class);
5354

54-
private static final String RHDA_TOKEN = "rhda-token";
55+
private static final String RHDA_TOKEN_HEADER = "rhda-token";
56+
private static final String RHDA_SOURCE_HEADER = "rhda-source";
57+
private static final String RHDA_OPERATION_TYPE_HEADER = "rhda-operation-type";
58+
private static final String USER_AGENT_HEADER = "User-Agent";
59+
5560
private static final String ANONYMOUS_ID = "telemetry-anonymous-id";
5661
private static final String ANALYSIS_EVENT = "rhda.exhort.analysis";
5762
private static final String TOKEN_EVENT = "rhda.exhort.token";
@@ -78,35 +83,36 @@ public void identify(Exchange exchange) {
7883
return;
7984
}
8085

81-
String userId = exchange.getIn().getHeader(RHDA_TOKEN, String.class);
86+
String userId = exchange.getIn().getHeader(RHDA_TOKEN_HEADER, String.class);
87+
Map<String, String> traits = new HashMap<>();
88+
traits.put("serverName", projectName);
89+
traits.put("serverVersion", projectVersion);
90+
traits.put("serverBuild", projectBuild);
91+
92+
IdentifyEvent.Builder builder =
93+
new IdentifyEvent.Builder()
94+
.context(
95+
new Context(new Library(projectId, projectVersion), getSource(exchange.getIn())))
96+
.traits(traits);
97+
8298
if (userId == null) {
8399
String anonymousId = UUID.randomUUID().toString();
84-
Map<String, String> traits = new HashMap<>();
85-
traits.put("serverName", projectName);
86-
traits.put("serverVersion", projectVersion);
87-
traits.put("serverBuild", projectBuild);
88-
IdentifyEvent event =
89-
new IdentifyEvent.Builder()
90-
.context(new Context(new Library(projectId, projectVersion)))
91-
.anonymousId(anonymousId)
92-
.traits(traits)
93-
.build();
94-
try {
95-
Response response = segmentService.identify(event);
96-
if (response.getStatus() >= 400) {
97-
LOGGER.warn(
98-
String.format(
99-
"Unable to send event to segment: %d - %s",
100-
response.getStatus(), response.getStatusInfo()));
101-
}
102-
} catch (Exception e) {
103-
LOGGER.warn("Unable to send event to segment", e);
104-
}
100+
builder.anonymousId(anonymousId);
105101
exchange.setProperty(ANONYMOUS_ID, anonymousId);
106102
} else {
107-
// no need to IDENTIFY as we expect the caller to have done that already
108-
exchange.setProperty(RHDA_TOKEN, userId);
109-
exchange.getIn().removeHeader(RHDA_TOKEN);
103+
builder.userId(userId);
104+
exchange.setProperty(RHDA_TOKEN_HEADER, userId);
105+
}
106+
try {
107+
Response response = segmentService.identify(builder.build());
108+
if (response.getStatus() >= 400) {
109+
LOGGER.warn(
110+
String.format(
111+
"Unable to send event to segment: %d - %s",
112+
response.getStatus(), response.getStatusInfo()));
113+
}
114+
} catch (Exception e) {
115+
LOGGER.warn("Unable to send event to segment", e);
110116
}
111117
}
112118

@@ -132,6 +138,10 @@ public void trackAnalysis(Exchange exchange) {
132138
snykReport.put("remediations", countRemediations(report));
133139
providers.put(Constants.SNYK_PROVIDER, snykReport);
134140
properties.put("providers", providers);
141+
String operationType = exchange.getIn().getHeader(RHDA_OPERATION_TYPE_HEADER, String.class);
142+
if (operationType != null) {
143+
properties.put("operationType", operationType);
144+
}
135145
}
136146
try {
137147
Response response = segmentService.track(builder.properties(properties).build());
@@ -168,16 +178,31 @@ public void trackToken(Exchange exchange) {
168178
}
169179
}
170180

181+
private String getSource(Message message) {
182+
String customSource = message.getHeader(RHDA_SOURCE_HEADER, String.class);
183+
if (customSource != null) {
184+
return customSource;
185+
}
186+
String userAgent = message.getHeader(USER_AGENT_HEADER, String.class);
187+
if (userAgent != null) {
188+
return userAgent;
189+
}
190+
return null;
191+
}
192+
171193
private TrackEvent.Builder prepareTrackEvent(Exchange exchange, String eventName) {
172-
TrackEvent.Builder builder = new TrackEvent.Builder(eventName);
173-
String userId = exchange.getProperty(RHDA_TOKEN, String.class);
194+
TrackEvent.Builder builder =
195+
new TrackEvent.Builder(eventName)
196+
.context(
197+
new Context(new Library(projectId, projectVersion), getSource(exchange.getIn())));
198+
String userId = exchange.getProperty(RHDA_TOKEN_HEADER, String.class);
174199
if (userId != null) {
175200
builder.userId(userId);
176201
} else {
177202
String anonymousId = exchange.getProperty(ANONYMOUS_ID, String.class);
178203
builder.anonymousId(anonymousId);
179204
}
180-
return builder.context(new Context(new Library(projectId, projectVersion)));
205+
return builder;
181206
}
182207

183208
private long countRemediations(AnalysisReport report) {

src/main/java/com/redhat/exhort/analytics/segment/Context.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,9 @@
1818

1919
package com.redhat.exhort.analytics.segment;
2020

21-
public record Context(Library library) {}
21+
import static com.fasterxml.jackson.annotation.JsonInclude.Include;
22+
23+
import com.fasterxml.jackson.annotation.JsonInclude;
24+
25+
@JsonInclude(Include.NON_NULL)
26+
public record Context(Library library, String source) {}

src/main/java/com/redhat/exhort/integration/backend/ExhortIntegration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,6 @@ private void cleanUpHeaders(Exchange exchange) {
172172
msg.removeHeaders("ex-.*-user");
173173
msg.removeHeaders("ex-.*-token");
174174
msg.removeHeader("Authorization");
175-
msg.removeHeader(Constants.RHDA_TOKEN_HEADER);
175+
msg.removeHeaders("rhda-.*");
176176
}
177177
}

0 commit comments

Comments
 (0)