diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6b443290c..f4cfc2adde 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,9 @@
### Features
- Add scope-level attributes API ([#5118](https://github.com/getsentry/sentry-java/pull/5118))
+<<<<<<< feat/scope-attributes-logger-metrics
+- Automatically include scope attributes in logs and metrics ([#5120](https://github.com/getsentry/sentry-java/pull/5120))
+=======
- Create `sentry-opentelemetry-otlp` and `sentry-opentelemetry-otlp-spring` modules for combining OpenTelemetry SDK OTLP export with Sentry SDK ([#5100](https://github.com/getsentry/sentry-java/pull/5100))
- OpenTelemetry is configured to send spans to Sentry directly using an OTLP endpoint.
- Sentry only uses trace and span ID from OpenTelemetry (via `OpenTelemetryOtlpEventProcessor`) but will not send spans through OpenTelemetry nor use OpenTelemetry `Context` for `Scopes` propagation.
@@ -28,6 +31,7 @@
```
+>>>>>>> feat/global-attributes-api
### Fixes
diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api
index d725b18313..7ca00d80c7 100644
--- a/sentry/api/sentry.api
+++ b/sentry/api/sentry.api
@@ -2829,6 +2829,7 @@ public final class io/sentry/SentryAttributeType : java/lang/Enum {
public static final field INTEGER Lio/sentry/SentryAttributeType;
public static final field STRING Lio/sentry/SentryAttributeType;
public fun apiName ()Ljava/lang/String;
+ public static fun inferFrom (Ljava/lang/Object;)Lio/sentry/SentryAttributeType;
public static fun valueOf (Ljava/lang/String;)Lio/sentry/SentryAttributeType;
public static fun values ()[Lio/sentry/SentryAttributeType;
}
@@ -3338,6 +3339,7 @@ public final class io/sentry/SentryLogEvent$JsonKeys {
public final class io/sentry/SentryLogEventAttributeValue : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public fun (Lio/sentry/SentryAttributeType;Ljava/lang/Object;)V
public fun (Ljava/lang/String;Ljava/lang/Object;)V
+ public static fun fromAttribute (Lio/sentry/SentryAttribute;)Lio/sentry/SentryLogEventAttributeValue;
public fun getType ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun getValue ()Ljava/lang/Object;
diff --git a/sentry/src/main/java/io/sentry/SentryAttributeType.java b/sentry/src/main/java/io/sentry/SentryAttributeType.java
index a47d7e71f0..8de00d277d 100644
--- a/sentry/src/main/java/io/sentry/SentryAttributeType.java
+++ b/sentry/src/main/java/io/sentry/SentryAttributeType.java
@@ -2,6 +2,7 @@
import java.util.Locale;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
public enum SentryAttributeType {
STRING,
@@ -12,4 +13,17 @@ public enum SentryAttributeType {
public @NotNull String apiName() {
return name().toLowerCase(Locale.ROOT);
}
+
+ public static @NotNull SentryAttributeType inferFrom(final @Nullable Object value) {
+ if (value instanceof Boolean) {
+ return BOOLEAN;
+ }
+ if (value instanceof Integer) {
+ return INTEGER;
+ }
+ if (value instanceof Number) {
+ return DOUBLE;
+ }
+ return STRING;
+ }
}
diff --git a/sentry/src/main/java/io/sentry/SentryLogEventAttributeValue.java b/sentry/src/main/java/io/sentry/SentryLogEventAttributeValue.java
index 1fd7c8c452..6f6542927f 100644
--- a/sentry/src/main/java/io/sentry/SentryLogEventAttributeValue.java
+++ b/sentry/src/main/java/io/sentry/SentryLogEventAttributeValue.java
@@ -27,6 +27,21 @@ public SentryLogEventAttributeValue(
this(type.apiName(), value);
}
+ /**
+ * Creates a {@link SentryLogEventAttributeValue} from a {@link SentryAttribute}, inferring the
+ * type if not explicitly set.
+ *
+ * @param attribute the attribute
+ * @return the attribute value
+ */
+ public static @NotNull SentryLogEventAttributeValue fromAttribute(
+ final @NotNull SentryAttribute attribute) {
+ final @Nullable Object value = attribute.getValue();
+ final @NotNull SentryAttributeType type =
+ attribute.getType() == null ? SentryAttributeType.inferFrom(value) : attribute.getType();
+ return new SentryLogEventAttributeValue(type, value);
+ }
+
public @NotNull String getType() {
return type;
}
diff --git a/sentry/src/main/java/io/sentry/logger/LoggerApi.java b/sentry/src/main/java/io/sentry/logger/LoggerApi.java
index 37a485df31..c203dcbfb8 100644
--- a/sentry/src/main/java/io/sentry/logger/LoggerApi.java
+++ b/sentry/src/main/java/io/sentry/logger/LoggerApi.java
@@ -21,6 +21,7 @@
import io.sentry.util.Platform;
import io.sentry.util.TracingUtils;
import java.util.HashMap;
+import java.util.Map;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -163,6 +164,14 @@ private void captureLog(
final @NotNull String message,
final @Nullable Object... args) {
final @NotNull HashMap attributes = new HashMap<>();
+
+ final @NotNull Map scopeAttributes =
+ scopes.getCombinedScopeView().getAttributes();
+ for (SentryAttribute scopeAttribute : scopeAttributes.values()) {
+ attributes.put(
+ scopeAttribute.getName(), SentryLogEventAttributeValue.fromAttribute(scopeAttribute));
+ }
+
final @NotNull String origin = params.getOrigin();
if (!"manual".equalsIgnoreCase(origin)) {
attributes.put(
@@ -173,17 +182,14 @@ private void captureLog(
if (incomingAttributes != null) {
for (SentryAttribute attribute : incomingAttributes.getAttributes().values()) {
- final @Nullable Object value = attribute.getValue();
- final @NotNull SentryAttributeType type =
- attribute.getType() == null ? getType(value) : attribute.getType();
- attributes.put(attribute.getName(), new SentryLogEventAttributeValue(type, value));
+ attributes.put(attribute.getName(), SentryLogEventAttributeValue.fromAttribute(attribute));
}
}
if (args != null) {
int i = 0;
for (Object arg : args) {
- final @NotNull SentryAttributeType type = getType(arg);
+ final @NotNull SentryAttributeType type = SentryAttributeType.inferFrom(arg);
attributes.put(
"sentry.message.parameter." + i, new SentryLogEventAttributeValue(type, arg));
i++;
@@ -292,17 +298,4 @@ private void setUser(final @NotNull HashMap createAttributes(
final @NotNull SentryMetricsParameters params) {
final @NotNull HashMap attributes = new HashMap<>();
+
+ final @NotNull Map scopeAttributes =
+ scopes.getCombinedScopeView().getAttributes();
+ for (SentryAttribute scopeAttribute : scopeAttributes.values()) {
+ attributes.put(
+ scopeAttribute.getName(), SentryLogEventAttributeValue.fromAttribute(scopeAttribute));
+ }
+
final @NotNull String origin = params.getOrigin();
if (!"manual".equalsIgnoreCase(origin)) {
attributes.put(
@@ -177,10 +186,7 @@ private void captureMetrics(
if (incomingAttributes != null) {
for (SentryAttribute attribute : incomingAttributes.getAttributes().values()) {
- final @Nullable Object value = attribute.getValue();
- final @NotNull SentryAttributeType type =
- attribute.getType() == null ? getType(value) : attribute.getType();
- attributes.put(attribute.getName(), new SentryLogEventAttributeValue(type, value));
+ attributes.put(attribute.getName(), SentryLogEventAttributeValue.fromAttribute(attribute));
}
}
@@ -279,17 +285,4 @@ private void setUser(final @NotNull HashMap