Skip to content

Commit

Permalink
[feat][sdk-105] Add telemetry (#313)
Browse files Browse the repository at this point in the history
* feat(telemetry): add log events

* feat(telemetry): add navigation events

* feat(telemetry): add Network events

* feat(telemetry): add Manual events

* feat(telemetry): add maximum telemetry data

* feat(telemetry): describe usage for static factories

* fix(telemetry): add maximumTelemetryData to Reactive Streams ConfigBuilder

* refactor(telemetry): replace static factories for TelemetryEventTracker

* fix(telemetry): remove reference to TelemetryEventTracker in Body

* fix(telemetry): set source only as "client" or "server" for Telemetry events

* test(telemetry): add tests for TelemetryEvent

* refactor(telemetry): modify equals and hashcode, and create a new hashmap in constructor

* revert(notifier): previous reference

* refactor: set source as an enum

* refactor: docs

* fix: test

* fix: checkstyle

* fix: checkstyle

* fix: checkstyle

* fix: checkstyle

* fix: add revapi acceptedBreaks

* fix: checkstyles

* fix(ci): set expected release configuration

* fix(ci): remove jdk7 condition

* fix(ci): set release.sh new folder

* fix(ci): suggested change

* refactor(telemetry): move coerce in logic to RollbarTelemetryEventTracker

* refactor(telemetry): rename class

* fix(telemetry): checkstyle

* refactor(telemetry): modify Telemetry queue capacity

* refactor(telemetry): modify Telemetry capacity default value

* fix(telemetry): checkstyle

* docs(telemetry): fix ConfigBuilder.telemetryEventTracker javadoc

* docs(telemetry): fix ConfigBuilder.maximumTelemetryData javadoc
  • Loading branch information
christianbuon authored Oct 3, 2024
1 parent 32abb9e commit 2bbb12c
Show file tree
Hide file tree
Showing 18 changed files with 1,197 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,4 @@ jobs:
NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }}
NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
run: |
./gradlew -Dorg.gradle.internal.http.socketTimeout=300000 -Dorg.gradle.internal.http.connectionTimeout=300000 publishToSonatype
./.github/scripts/release.sh
8 changes: 8 additions & 0 deletions .palantir/revapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@ acceptedBreaks:
justification: "This is a binary compatible change, which could only break custom\
\ implementations of our config interfaces, but those interfaces are not meant\
\ to be implemented by users"
"2.0.0":
com.rollbar:rollbar-java:
- code: "java.method.addedToInterface"
new: "method com.rollbar.notifier.telemetry.TelemetryEventTracker com.rollbar.notifier.config.CommonConfig::telemetryEventTracker()"
justification: "This is going to be added in a major version"
- code: "java.method.addedToInterface"
new: "method int com.rollbar.notifier.config.CommonConfig::maximumTelemetryData()"
justification: "This is going to be added in a major version"
44 changes: 44 additions & 0 deletions rollbar-android/src/main/java/com/rollbar/android/Rollbar.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import android.util.Log;
import com.rollbar.android.notifier.sender.ConnectionAwareSenderFailureStrategy;
import com.rollbar.android.provider.ClientProvider;
import com.rollbar.api.payload.data.TelemetryType;
import com.rollbar.notifier.config.ConfigProvider;
import com.rollbar.notifier.uncaughtexception.RollbarUncaughtExceptionHandler;
import com.rollbar.android.provider.NotifierProvider;
Expand Down Expand Up @@ -926,6 +927,49 @@ public void log(final Throwable error, final Map<String, Object> custom, final S
rollbar.log(error, custom, description, level);
}

/**
* Record log telemetry event. ({@link TelemetryType#LOG}).
*
* @param level the TelemetryEvent severity (e.g. {@link Level#DEBUG}).
* @param message the message sent for this event (e.g. "hello world").
*/
public void recordLogEventFor(Level level, final String message) {
rollbar.recordLogEventFor(level, message);
}

/**
* Record manual telemetry event. ({@link TelemetryType#MANUAL})
*
* @param level the TelemetryEvent severity (e.g. {@link Level#DEBUG}).
* @param message the message sent for this event (e.g. "hello world").
*/
public void recordManualEventFor(Level level, final String message) {
rollbar.recordManualEventFor(level, message);
}

/**
* Record navigation telemetry event with from (origin) and to (destination).({@link TelemetryType#NAVIGATION})
*
* @param level the TelemetryEvent severity (e.g. {@link Level#DEBUG}).
* @param from the starting point (e.g. "SettingView").
* @param to the destination point (e.g. "HomeView").
*/
public void recordNavigationEventFor(Level level, final String from, final String to) {
rollbar.recordNavigationEventFor(level, from, to);
}

/**
* Record network telemetry event with method, url, and status code.({@link TelemetryType#NETWORK})
*
* @param level the TelemetryEvent severity (e.g. {@link Level#DEBUG}).
* @param method the verb used (e.g. "POST").
* @param url the api url (e.g. "<a href="http://rollbar.com/test/api">http://rollbar.com/test/api</a>").
* @param statusCode the response status code (e.g. "404").
*/
public void recordNetworkEventFor(Level level, final String method, final String url, final String statusCode) {
rollbar.recordNetworkEventFor(level, method, url, statusCode);
}

/**
* Send payload to Rollbar.
*
Expand Down
30 changes: 30 additions & 0 deletions rollbar-api/src/main/java/com/rollbar/api/payload/data/Source.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.rollbar.api.payload.data;

import com.rollbar.api.json.JsonSerializable;

/**
* The Source of a payload.
*/
public enum Source implements JsonSerializable {

/**
* A Client source (e.g. Android)
*/
CLIENT("client"),

/**
* A Server source (e.g. Spring)
*/
SERVER("server");

private final String jsonName;

Source(String jsonName) {
this.jsonName = jsonName;
}

@Override
public Object asJson() {
return jsonName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.rollbar.api.payload.data;

import com.rollbar.api.json.JsonSerializable;
import com.rollbar.api.truncation.StringTruncatable;
import com.rollbar.api.truncation.TruncationHelper;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
* Represents an event that allows you to leave a 'breadcrumb' leading up to an exception.
*/
public class TelemetryEvent implements JsonSerializable, StringTruncatable<TelemetryEvent> {

private final TelemetryType type;
private final Level level;
private final Long timestamp;
private final Map<String, String> body;
private final Source source;
private static final long serialVersionUID = 2843361810242481727L;

/**
* Construct a TelemetryEvent.
*
* @param telemetryType {@link TelemetryType}
* @param level {@link Level}
* @param timestamp the timestamp for this TelemetryEvent
* @param source {@link Source}
* @param body a map containing all the data required by the {@link TelemetryType}
*/
public TelemetryEvent(
TelemetryType telemetryType,
Level level,
Long timestamp,
Source source,
Map<String, String> body
) {
type = telemetryType;
this.timestamp = timestamp;
this.level = level;
this.source = source;
this.body = new HashMap<>(body);
}

@Override
public Map<String, Object> asJson() {
Map<String, Object> values = new HashMap<>();
values.put("type", type.asJson());
values.put("level", level.asJson());
values.put("source", source.asJson());
values.put("timestamp_ms", timestamp);
values.put("body", body);
return values;
}

@Override
public TelemetryEvent truncateStrings(int maxLength) {
Map<String, String> truncatedMap = new HashMap<>();
for (Map.Entry<String, String> entry : body.entrySet()) {
String truncatedValue = TruncationHelper.truncateString(entry.getValue(), maxLength);
truncatedMap.put(entry.getKey(), truncatedValue);
}
return new TelemetryEvent(
this.type,
this.level,
this.timestamp,
this.source,
truncatedMap
);
}

@Override
public String toString() {
return "TelemetryEvent{"
+ "type='" + type.asJson() + '\''
+ ", level='" + level.asJson() + '\''
+ ", source='" + source + '\''
+ ", timestamp_ms=" + timestamp
+ ", body=" + body
+ '}';
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TelemetryEvent that = (TelemetryEvent) o;
return type == that.type && level == that.level && Objects.equals(timestamp, that.timestamp)
&& Objects.equals(body, that.body) && Objects.equals(source, that.source);
}

@Override
public int hashCode() {
return Objects.hash(type, level, timestamp, body, source);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.rollbar.api.payload.data;

import com.rollbar.api.json.JsonSerializable;

/**
* Represents the different types of {@link TelemetryEvent} available.
*/
public enum TelemetryType implements JsonSerializable {
LOG("log"),
MANUAL("manual"),
NAVIGATION("navigation"),
NETWORK("network");

private final String jsonName;

TelemetryType(String jsonName) {
this.jsonName = jsonName;
}

@Override
public Object asJson() {
return jsonName;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.rollbar.api.payload.data.body;

import com.rollbar.api.json.JsonSerializable;
import com.rollbar.api.payload.data.TelemetryEvent;
import com.rollbar.api.truncation.StringTruncatable;

import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
* A container for the actual error(s), message, or crash report that caused this error.
Expand All @@ -14,8 +17,11 @@ public class Body implements JsonSerializable, StringTruncatable<Body> {

private final BodyContent bodyContent;

private final List<TelemetryEvent> telemetryEvents;

private Body(Builder builder) {
this.bodyContent = builder.bodyContent;
this.telemetryEvents = builder.telemetryEvents;
}

/**
Expand All @@ -34,6 +40,10 @@ public Object asJson() {
values.put(bodyContent.getKeyName(), bodyContent);
}

if (telemetryEvents != null) {
values.put("telemetry", telemetryEvents);
}

return values;
}

Expand All @@ -53,24 +63,26 @@ public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {

if (!(o instanceof Body)) {
return false;
}

Body body = (Body) o;

return bodyContent != null ? bodyContent.equals(body.bodyContent) : body.bodyContent == null;
return Objects.equals(bodyContent, body.bodyContent)
&& Objects.equals(telemetryEvents, body.telemetryEvents);
}

@Override
public int hashCode() {
return bodyContent != null ? bodyContent.hashCode() : 0;
return Objects.hash(bodyContent, telemetryEvents);
}

@Override
public String toString() {
return "Body{"
+ "bodyContent=" + bodyContent
+ ", telemetry=" + telemetryEvents
+ '}';
}

Expand All @@ -81,6 +93,8 @@ public static final class Builder {

private BodyContent bodyContent;

private List<TelemetryEvent> telemetryEvents;

/**
* Constructor.
*/
Expand All @@ -95,6 +109,7 @@ public Builder() {
*/
public Builder(Body body) {
this.bodyContent = body.bodyContent;
this.telemetryEvents = body.telemetryEvents;
}

/**
Expand All @@ -109,6 +124,17 @@ public Builder bodyContent(BodyContent bodyContent) {
return this;
}

/**
* The Telemetry events of this body.
*
* @param telemetryEvents the events captured until this payload;
* @return the builder instance.
*/
public Builder telemetryEvents(List<TelemetryEvent> telemetryEvents) {
this.telemetryEvents = telemetryEvents;
return this;
}

/**
* Builds the {@link Body body}.
*
Expand Down
Loading

0 comments on commit 2bbb12c

Please sign in to comment.