Skip to content

Commit 5dba18b

Browse files
committed
Metrics counter basic API
1 parent 1df9f12 commit 5dba18b

File tree

1 file changed

+212
-1
lines changed

1 file changed

+212
-1
lines changed

sentry/src/main/java/io/sentry/metrics/MetricsApi.java

Lines changed: 212 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
11
package io.sentry.metrics;
22

3+
import io.sentry.HostnameCache;
4+
import io.sentry.IScope;
5+
import io.sentry.ISpan;
6+
import io.sentry.PropagationContext;
37
import io.sentry.Scopes;
8+
import io.sentry.SentryAttribute;
9+
import io.sentry.SentryAttributeType;
10+
import io.sentry.SentryAttributes;
11+
import io.sentry.SentryDate;
12+
import io.sentry.SentryLevel;
13+
import io.sentry.SentryLogEventAttributeValue;
14+
import io.sentry.SentryMetricsEvent;
15+
import io.sentry.SentryOptions;
16+
import io.sentry.SpanId;
17+
import io.sentry.logger.SentryLogParameters;
18+
import io.sentry.protocol.SdkVersion;
19+
import io.sentry.protocol.SentryId;
20+
import io.sentry.protocol.User;
21+
import io.sentry.util.Platform;
22+
import io.sentry.util.TracingUtils;
23+
import java.util.HashMap;
424
import org.jetbrains.annotations.NotNull;
25+
import org.jetbrains.annotations.Nullable;
526

627
public final class MetricsApi implements IMetricsApi {
728

@@ -13,6 +34,196 @@ public MetricsApi(final @NotNull Scopes scopes) {
1334

1435
@Override
1536
public void count(@NotNull String name) {
16-
scopes.getOptions();
37+
captureMetrics(SentryLogParameters.create(null, null), name, "counter", 1.0);
38+
}
39+
40+
@SuppressWarnings("AnnotateFormatMethod")
41+
private void captureMetrics(
42+
final @NotNull SentryLogParameters params,
43+
final @Nullable String name,
44+
final @Nullable String type,
45+
final @Nullable Double value) {
46+
final @NotNull SentryOptions options = scopes.getOptions();
47+
try {
48+
if (!scopes.isEnabled()) {
49+
options
50+
.getLogger()
51+
.log(SentryLevel.WARNING, "Instance is disabled and this 'metrics' call is a no-op.");
52+
return;
53+
}
54+
55+
if (!options.getMetrics().isEnabled()) {
56+
options
57+
.getLogger()
58+
.log(
59+
SentryLevel.WARNING,
60+
"Sentry Metrics is disabled and this 'metrics' call is a no-op.");
61+
return;
62+
}
63+
64+
if (name == null) {
65+
return;
66+
}
67+
68+
if (type == null) {
69+
return;
70+
}
71+
72+
if (value == null) {
73+
return;
74+
}
75+
76+
final @Nullable SentryDate timestamp = params.getTimestamp();
77+
final @NotNull SentryDate timestampToUse =
78+
timestamp == null ? options.getDateProvider().now() : timestamp;
79+
80+
final @NotNull IScope combinedScope = scopes.getCombinedScopeView();
81+
final @NotNull PropagationContext propagationContext = combinedScope.getPropagationContext();
82+
final @Nullable ISpan span = combinedScope.getSpan();
83+
if (span == null) {
84+
TracingUtils.maybeUpdateBaggage(combinedScope, options);
85+
}
86+
final @NotNull SentryId traceId =
87+
span == null ? propagationContext.getTraceId() : span.getSpanContext().getTraceId();
88+
final @NotNull SpanId spanId =
89+
span == null ? propagationContext.getSpanId() : span.getSpanContext().getSpanId();
90+
final SentryMetricsEvent metricsEvent =
91+
new SentryMetricsEvent(traceId, timestampToUse, name, type, value);
92+
metricsEvent.setSpanId(spanId);
93+
metricsEvent.setAttributes(createAttributes(params));
94+
95+
scopes.getClient().captureMetric(metricsEvent, combinedScope);
96+
} catch (Throwable e) {
97+
options.getLogger().log(SentryLevel.ERROR, "Error while capturing log event", e);
98+
}
99+
}
100+
101+
private @NotNull HashMap<String, SentryLogEventAttributeValue> createAttributes(
102+
final @NotNull SentryLogParameters params) {
103+
final @NotNull HashMap<String, SentryLogEventAttributeValue> attributes = new HashMap<>();
104+
final @NotNull String origin = params.getOrigin();
105+
if (!"manual".equalsIgnoreCase(origin)) {
106+
attributes.put(
107+
"sentry.origin", new SentryLogEventAttributeValue(SentryAttributeType.STRING, origin));
108+
}
109+
110+
final @Nullable SentryAttributes incomingAttributes = params.getAttributes();
111+
112+
if (incomingAttributes != null) {
113+
for (SentryAttribute attribute : incomingAttributes.getAttributes().values()) {
114+
final @Nullable Object value = attribute.getValue();
115+
final @NotNull SentryAttributeType type =
116+
attribute.getType() == null ? getType(value) : attribute.getType();
117+
attributes.put(attribute.getName(), new SentryLogEventAttributeValue(type, value));
118+
}
119+
}
120+
121+
final @Nullable SdkVersion sdkVersion = scopes.getOptions().getSdkVersion();
122+
if (sdkVersion != null) {
123+
attributes.put(
124+
"sentry.sdk.name",
125+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, sdkVersion.getName()));
126+
attributes.put(
127+
"sentry.sdk.version",
128+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, sdkVersion.getVersion()));
129+
}
130+
131+
final @Nullable String environment = scopes.getOptions().getEnvironment();
132+
if (environment != null) {
133+
attributes.put(
134+
"sentry.environment",
135+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, environment));
136+
}
137+
138+
final @NotNull SentryId scopeReplayId = scopes.getCombinedScopeView().getReplayId();
139+
if (!SentryId.EMPTY_ID.equals(scopeReplayId)) {
140+
attributes.put(
141+
"sentry.replay_id",
142+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, scopeReplayId.toString()));
143+
} else {
144+
final @NotNull SentryId controllerReplayId =
145+
scopes.getOptions().getReplayController().getReplayId();
146+
if (!SentryId.EMPTY_ID.equals(controllerReplayId)) {
147+
attributes.put(
148+
"sentry.replay_id",
149+
new SentryLogEventAttributeValue(
150+
SentryAttributeType.STRING, controllerReplayId.toString()));
151+
attributes.put(
152+
"sentry._internal.replay_is_buffering",
153+
new SentryLogEventAttributeValue(SentryAttributeType.BOOLEAN, true));
154+
}
155+
}
156+
157+
final @Nullable String release = scopes.getOptions().getRelease();
158+
if (release != null) {
159+
attributes.put(
160+
"sentry.release", new SentryLogEventAttributeValue(SentryAttributeType.STRING, release));
161+
}
162+
163+
if (Platform.isJvm()) {
164+
setServerName(attributes);
165+
}
166+
167+
setUser(attributes);
168+
169+
return attributes;
170+
}
171+
172+
private void setServerName(
173+
final @NotNull HashMap<String, SentryLogEventAttributeValue> attributes) {
174+
final @NotNull SentryOptions options = scopes.getOptions();
175+
final @Nullable String optionsServerName = options.getServerName();
176+
if (optionsServerName != null) {
177+
attributes.put(
178+
"server.address",
179+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, optionsServerName));
180+
} else if (options.isAttachServerName()) {
181+
final @Nullable String hostname = HostnameCache.getInstance().getHostname();
182+
if (hostname != null) {
183+
attributes.put(
184+
"server.address",
185+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, hostname));
186+
}
187+
}
188+
}
189+
190+
private void setUser(final @NotNull HashMap<String, SentryLogEventAttributeValue> attributes) {
191+
final @Nullable User user = scopes.getCombinedScopeView().getUser();
192+
if (user == null) {
193+
// In case no user is set, we should fallback to the distinct id, known as installation id,
194+
// which is used on Android as default user id
195+
final @Nullable String id = scopes.getOptions().getDistinctId();
196+
if (id != null) {
197+
attributes.put("user.id", new SentryLogEventAttributeValue(SentryAttributeType.STRING, id));
198+
}
199+
} else {
200+
final @Nullable String id = user.getId();
201+
if (id != null) {
202+
attributes.put("user.id", new SentryLogEventAttributeValue(SentryAttributeType.STRING, id));
203+
}
204+
final @Nullable String username = user.getUsername();
205+
if (username != null) {
206+
attributes.put(
207+
"user.name", new SentryLogEventAttributeValue(SentryAttributeType.STRING, username));
208+
}
209+
final @Nullable String email = user.getEmail();
210+
if (email != null) {
211+
attributes.put(
212+
"user.email", new SentryLogEventAttributeValue(SentryAttributeType.STRING, email));
213+
}
214+
}
215+
}
216+
217+
private @NotNull SentryAttributeType getType(final @Nullable Object arg) {
218+
if (arg instanceof Boolean) {
219+
return SentryAttributeType.BOOLEAN;
220+
}
221+
if (arg instanceof Integer) {
222+
return SentryAttributeType.INTEGER;
223+
}
224+
if (arg instanceof Number) {
225+
return SentryAttributeType.DOUBLE;
226+
}
227+
return SentryAttributeType.STRING;
17228
}
18229
}

0 commit comments

Comments
 (0)