Skip to content

Commit

Permalink
Provide API for attaching custom measurements to transactions (#2260)
Browse files Browse the repository at this point in the history
  • Loading branch information
adinauer committed Oct 4, 2022
1 parent 7163f07 commit 54cebc8
Show file tree
Hide file tree
Showing 22 changed files with 457 additions and 36 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Features

- Provide API for attaching custom measurements to transactions ([#2260](https://github.com/getsentry/sentry-java/pull/2260))

## 6.5.0-beta.2

### Features
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package io.sentry.android.core;

import static io.sentry.protocol.MeasurementValue.NONE_UNIT;

import android.app.Activity;
import android.util.SparseIntArray;
import androidx.core.app.FrameMetricsAggregator;
import io.sentry.ILogger;
import io.sentry.MeasurementUnit;
import io.sentry.protocol.MeasurementValue;
import io.sentry.protocol.SentryId;
import java.util.HashMap;
Expand Down Expand Up @@ -104,9 +103,9 @@ public synchronized void setMetrics(
return;
}

final MeasurementValue tfValues = new MeasurementValue(totalFrames, NONE_UNIT);
final MeasurementValue sfValues = new MeasurementValue(slowFrames, NONE_UNIT);
final MeasurementValue ffValues = new MeasurementValue(frozenFrames, NONE_UNIT);
final MeasurementValue tfValues = new MeasurementValue(totalFrames, MeasurementUnit.NONE);
final MeasurementValue sfValues = new MeasurementValue(slowFrames, MeasurementUnit.NONE);
final MeasurementValue ffValues = new MeasurementValue(frozenFrames, MeasurementUnit.NONE);
final Map<String, @NotNull MeasurementValue> measurements = new HashMap<>();
measurements.put("frames_total", tfValues);
measurements.put("frames_slow", sfValues);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import static io.sentry.android.core.ActivityLifecycleIntegration.APP_START_COLD;
import static io.sentry.android.core.ActivityLifecycleIntegration.APP_START_WARM;
import static io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP;
import static io.sentry.protocol.MeasurementValue.MILLISECOND_UNIT;

import io.sentry.EventProcessor;
import io.sentry.Hint;
import io.sentry.MeasurementUnit;
import io.sentry.SentryEvent;
import io.sentry.SpanContext;
import io.sentry.protocol.MeasurementValue;
Expand Down Expand Up @@ -67,7 +67,8 @@ public SentryEvent process(@NotNull SentryEvent event, @NotNull Hint hint) {
// if appStartUpInterval is null, metrics are not ready to be sent
if (appStartUpInterval != null) {
final MeasurementValue value =
new MeasurementValue((float) appStartUpInterval, MILLISECOND_UNIT);
new MeasurementValue(
(float) appStartUpInterval, MeasurementUnit.Duration.MILLISECOND.apiName());

final String appStartKey =
AppStartState.getInstance().isColdStart() ? "app_start_cold" : "app_start_warm";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class ActivityFramesTrackerTest {
val metrics = sut.takeMetrics(fixture.sentryId)
val totalFrames = metrics!!["frames_total"]

assertEquals(totalFrames!!.value, 1f)
assertEquals(totalFrames!!.value, 1)
assertEquals(totalFrames.unit, "none")
}

Expand All @@ -57,7 +57,7 @@ class ActivityFramesTrackerTest {
val metrics = sut.takeMetrics(fixture.sentryId)
val frozenFrames = metrics!!["frames_frozen"]

assertEquals(frozenFrames!!.value, 5f)
assertEquals(frozenFrames!!.value, 5)
assertEquals(frozenFrames.unit, "none")
}

Expand All @@ -73,7 +73,7 @@ class ActivityFramesTrackerTest {
val metrics = sut.takeMetrics(fixture.sentryId)
val slowFrames = metrics!!["frames_slow"]

assertEquals(slowFrames!!.value, 5f)
assertEquals(slowFrames!!.value, 5)
assertEquals(slowFrames.unit, "none")
}

Expand All @@ -93,13 +93,13 @@ class ActivityFramesTrackerTest {
val metrics = sut.takeMetrics(fixture.sentryId)

val totalFrames = metrics!!["frames_total"]
assertEquals(totalFrames!!.value, 111f)
assertEquals(totalFrames!!.value, 111)

val frozenFrames = metrics["frames_frozen"]
assertEquals(frozenFrames!!.value, 6f)
assertEquals(frozenFrames!!.value, 6)

val slowFrames = metrics["frames_slow"]
assertEquals(slowFrames!!.value, 5f)
assertEquals(slowFrames!!.value, 5)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.whenever
import io.sentry.Hint
import io.sentry.IHub
import io.sentry.MeasurementUnit
import io.sentry.SentryTracer
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP
import io.sentry.protocol.MeasurementValue
import io.sentry.protocol.MeasurementValue.MILLISECOND_UNIT
import io.sentry.protocol.SentryTransaction
import java.util.Date
import kotlin.test.BeforeTest
Expand Down Expand Up @@ -156,7 +156,7 @@ class PerformanceAndroidEventProcessorTest {
val tracer = SentryTracer(context, fixture.hub)
var tr = SentryTransaction(tracer)

val metrics = mapOf("frames_total" to MeasurementValue(1f, MILLISECOND_UNIT))
val metrics = mapOf("frames_total" to MeasurementValue(1f, MeasurementUnit.Duration.MILLISECOND.apiName()))
whenever(fixture.activityFramesTracker.takeMetrics(any())).thenReturn(metrics)

tr = sut.process(tr, Hint())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import androidx.appcompat.app.AppCompatActivity;
import io.sentry.Attachment;
import io.sentry.ISpan;
import io.sentry.MeasurementUnit;
import io.sentry.Sentry;
import io.sentry.SpanStatus;
import io.sentry.UserFeedback;
Expand All @@ -27,6 +28,7 @@
public class MainActivity extends AppCompatActivity {

private int crashCount = 0;
private int screenLoadCount = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand Down Expand Up @@ -200,8 +202,10 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
protected void onResume() {
super.onResume();
screenLoadCount++;
final ISpan span = Sentry.getSpan();
if (span != null) {
span.setMeasurement("screen_load_count", screenLoadCount, new MeasurementUnit.Custom("test"));
span.finish(SpanStatus.OK);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.sentry.samples.spring.boot;

import io.sentry.ISpan;
import io.sentry.Sentry;
import io.sentry.spring.tracing.SentrySpan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -16,12 +18,19 @@ public class PersonService {
private static final Logger LOGGER = LoggerFactory.getLogger(PersonService.class);

private final JdbcTemplate jdbcTemplate;
private int createCount = 0;

public PersonService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

Person create(Person person) {
createCount++;
final ISpan span = Sentry.getSpan();
if (span != null) {
span.setMeasurement("create_count", createCount);
}

jdbcTemplate.update(
"insert into person (firstName, lastName) values (?, ?)",
person.getFirstName(),
Expand Down
68 changes: 63 additions & 5 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,8 @@ public abstract interface class io/sentry/ISpan {
public abstract fun isFinished ()Z
public abstract fun setData (Ljava/lang/String;Ljava/lang/Object;)V
public abstract fun setDescription (Ljava/lang/String;)V
public abstract fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;)V
public abstract fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;Lio/sentry/MeasurementUnit;)V
public abstract fun setOperation (Ljava/lang/String;)V
public abstract fun setStatus (Lio/sentry/SpanStatus;)V
public abstract fun setTag (Ljava/lang/String;Ljava/lang/String;)V
Expand Down Expand Up @@ -599,6 +601,56 @@ public final class io/sentry/MainEventProcessor : io/sentry/EventProcessor, java
public fun process (Lio/sentry/protocol/SentryTransaction;Lio/sentry/Hint;)Lio/sentry/protocol/SentryTransaction;
}

public abstract interface class io/sentry/MeasurementUnit {
public static final field NONE Ljava/lang/String;
public fun apiName ()Ljava/lang/String;
public abstract fun name ()Ljava/lang/String;
}

public final class io/sentry/MeasurementUnit$Custom : io/sentry/MeasurementUnit {
public fun <init> (Ljava/lang/String;)V
public fun name ()Ljava/lang/String;
}

public final class io/sentry/MeasurementUnit$Duration : java/lang/Enum, io/sentry/MeasurementUnit {
public static final field DAY Lio/sentry/MeasurementUnit$Duration;
public static final field HOUR Lio/sentry/MeasurementUnit$Duration;
public static final field MICROSECOND Lio/sentry/MeasurementUnit$Duration;
public static final field MILLISECOND Lio/sentry/MeasurementUnit$Duration;
public static final field MINUTE Lio/sentry/MeasurementUnit$Duration;
public static final field NANOSECOND Lio/sentry/MeasurementUnit$Duration;
public static final field SECOND Lio/sentry/MeasurementUnit$Duration;
public static final field WEEK Lio/sentry/MeasurementUnit$Duration;
public static fun valueOf (Ljava/lang/String;)Lio/sentry/MeasurementUnit$Duration;
public static fun values ()[Lio/sentry/MeasurementUnit$Duration;
}

public final class io/sentry/MeasurementUnit$Fraction : java/lang/Enum, io/sentry/MeasurementUnit {
public static final field PERCENT Lio/sentry/MeasurementUnit$Fraction;
public static final field RATIO Lio/sentry/MeasurementUnit$Fraction;
public static fun valueOf (Ljava/lang/String;)Lio/sentry/MeasurementUnit$Fraction;
public static fun values ()[Lio/sentry/MeasurementUnit$Fraction;
}

public final class io/sentry/MeasurementUnit$Information : java/lang/Enum, io/sentry/MeasurementUnit {
public static final field BIT Lio/sentry/MeasurementUnit$Information;
public static final field BYTE Lio/sentry/MeasurementUnit$Information;
public static final field EXABYTE Lio/sentry/MeasurementUnit$Information;
public static final field EXBIBYTE Lio/sentry/MeasurementUnit$Information;
public static final field GIBIBYTE Lio/sentry/MeasurementUnit$Information;
public static final field GIGABYTE Lio/sentry/MeasurementUnit$Information;
public static final field KIBIBYTE Lio/sentry/MeasurementUnit$Information;
public static final field KILOBYTE Lio/sentry/MeasurementUnit$Information;
public static final field MEBIBYTE Lio/sentry/MeasurementUnit$Information;
public static final field MEGABYTE Lio/sentry/MeasurementUnit$Information;
public static final field PEBIBYTE Lio/sentry/MeasurementUnit$Information;
public static final field PETABYTE Lio/sentry/MeasurementUnit$Information;
public static final field TEBIBYTE Lio/sentry/MeasurementUnit$Information;
public static final field TERABYTE Lio/sentry/MeasurementUnit$Information;
public static fun valueOf (Ljava/lang/String;)Lio/sentry/MeasurementUnit$Information;
public static fun values ()[Lio/sentry/MeasurementUnit$Information;
}

public final class io/sentry/NoOpEnvelopeReader : io/sentry/IEnvelopeReader {
public static fun getInstance ()Lio/sentry/NoOpEnvelopeReader;
public fun read (Ljava/io/InputStream;)Lio/sentry/SentryEnvelope;
Expand Down Expand Up @@ -670,6 +722,8 @@ public final class io/sentry/NoOpSpan : io/sentry/ISpan {
public fun isFinished ()Z
public fun setData (Ljava/lang/String;Ljava/lang/Object;)V
public fun setDescription (Ljava/lang/String;)V
public fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;)V
public fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;Lio/sentry/MeasurementUnit;)V
public fun setOperation (Ljava/lang/String;)V
public fun setStatus (Lio/sentry/SpanStatus;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
Expand Down Expand Up @@ -705,6 +759,8 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
public fun scheduleFinish ()V
public fun setData (Ljava/lang/String;Ljava/lang/Object;)V
public fun setDescription (Ljava/lang/String;)V
public fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;)V
public fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;Lio/sentry/MeasurementUnit;)V
public fun setName (Ljava/lang/String;)V
public fun setName (Ljava/lang/String;Lio/sentry/protocol/TransactionNameSource;)V
public fun setOperation (Ljava/lang/String;)V
Expand Down Expand Up @@ -1497,6 +1553,8 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction {
public fun scheduleFinish ()V
public fun setData (Ljava/lang/String;Ljava/lang/Object;)V
public fun setDescription (Ljava/lang/String;)V
public fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;)V
public fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;Lio/sentry/MeasurementUnit;)V
public fun setName (Ljava/lang/String;)V
public fun setName (Ljava/lang/String;Lio/sentry/protocol/TransactionNameSource;)V
public fun setOperation (Ljava/lang/String;)V
Expand Down Expand Up @@ -1603,6 +1661,8 @@ public final class io/sentry/Span : io/sentry/ISpan {
public fun isSampled ()Ljava/lang/Boolean;
public fun setData (Ljava/lang/String;Ljava/lang/Object;)V
public fun setDescription (Ljava/lang/String;)V
public fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;)V
public fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;Lio/sentry/MeasurementUnit;)V
public fun setOperation (Ljava/lang/String;)V
public fun setStatus (Lio/sentry/SpanStatus;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
Expand Down Expand Up @@ -2449,13 +2509,11 @@ public final class io/sentry/protocol/Gpu$JsonKeys {
}

public final class io/sentry/protocol/MeasurementValue : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public static final field MILLISECOND_UNIT Ljava/lang/String;
public static final field NONE_UNIT Ljava/lang/String;
public fun <init> (FLjava/lang/String;)V
public fun <init> (FLjava/lang/String;Ljava/util/Map;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/String;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/String;Ljava/util/Map;)V
public fun getUnit ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun getValue ()F
public fun getValue ()Ljava/lang/Number;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
}
Expand Down
25 changes: 25 additions & 0 deletions sentry/src/main/java/io/sentry/ISpan.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,29 @@ ISpan startChild(
*/
@Nullable
Object getData(@NotNull String key);

/**
* Set a measurement without unit. When setting the measurement without the unit, no formatting
* will be applied to the measurement value in the Sentry product, and the value will be shown as
* is.
*
* <p>NOTE: Setting a measurement with the same name on the same transaction multiple times only
* keeps the last value.
*
* @param name the name of the measurement
* @param value the value of the measurement
*/
void setMeasurement(@NotNull String name, @NotNull Number value);

/**
* Set a measurement with specific unit.
*
* <p>NOTE: Setting a measurement with the same name on the same transaction multiple times only
* keeps the last value.
*
* @param name the name of the measurement
* @param value the value of the measurement
* @param unit the unit the value is measured in
*/
void setMeasurement(@NotNull String name, @NotNull Number value, @NotNull MeasurementUnit unit);
}

0 comments on commit 54cebc8

Please sign in to comment.