From 27d99023a29191ec59174909735a5472da085599 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Thu, 21 Aug 2025 17:23:48 -0700 Subject: [PATCH 1/4] Support custom exception handling --- .../appender/v1_1/LoggingEventMapper.java | 17 ++++++++------- .../log4j/appender/v1_2/LogEventMapper.java | 17 ++++++++------- .../v2_17/internal/LogEventMapper.java | 21 +++++++++++-------- .../v1_0/internal/LoggingEventMapper.java | 21 +++++++++++-------- 4 files changed, 44 insertions(+), 32 deletions(-) diff --git a/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java b/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java index b8e13d2f3e19..e6175f057615 100644 --- a/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java +++ b/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java @@ -15,6 +15,7 @@ import io.opentelemetry.api.logs.LogRecordBuilder; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; +import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; import io.opentelemetry.instrumentation.api.internal.cache.Cache; import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.semconv.ExceptionAttributes; @@ -81,13 +82,15 @@ public void capture(Logger logger, ExtLogRecord record) { Throwable throwable = record.getThrown(); if (throwable != null) { - // TODO (trask) extract method for recording exception into - // io.opentelemetry:opentelemetry-api - attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); - attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); - StringWriter writer = new StringWriter(); - throwable.printStackTrace(new PrintWriter(writer)); - attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString()); + if (builder instanceof ExtendedLogRecordBuilder) { + ((ExtendedLogRecordBuilder) builder).setException(throwable); + } else { + attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); + attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); + StringWriter writer = new StringWriter(); + throwable.printStackTrace(new PrintWriter(writer)); + attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString()); + } } captureMdcAttributes(attributes); diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index b2c3b6dea3ad..0cbe5c8b51ed 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -14,6 +14,7 @@ import io.opentelemetry.api.logs.LogRecordBuilder; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; +import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.api.internal.cache.Cache; import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; @@ -101,13 +102,15 @@ public void capture( // throwable if (throwable != null) { - // TODO (trask) extract method for recording exception into - // io.opentelemetry:opentelemetry-api - attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); - attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); - StringWriter writer = new StringWriter(); - throwable.printStackTrace(new PrintWriter(writer)); - attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString()); + if (builder instanceof ExtendedLogRecordBuilder) { + ((ExtendedLogRecordBuilder) builder).setException(throwable); + } else { + attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); + attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); + StringWriter writer = new StringWriter(); + throwable.printStackTrace(new PrintWriter(writer)); + attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString()); + } } captureMdcAttributes(attributes); diff --git a/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/internal/LogEventMapper.java b/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/internal/LogEventMapper.java index a167f5ebbb38..5338477d5d7c 100644 --- a/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/internal/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/internal/LogEventMapper.java @@ -8,6 +8,7 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; import io.opentelemetry.api.logs.LogRecordBuilder; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; @@ -117,7 +118,7 @@ public void mapLogEvent( } if (throwable != null) { - setThrowable(attributes, throwable); + setThrowable(builder, attributes, throwable); } captureContextDataAttributes(attributes, contextData); @@ -233,14 +234,16 @@ public static AttributeKey getMapMessageAttributeKey(String key) { key, k -> AttributeKey.stringKey("log4j.map_message." + k)); } - private static void setThrowable(AttributesBuilder attributes, Throwable throwable) { - // TODO (trask) extract method for recording exception into - // io.opentelemetry:opentelemetry-api - attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); - attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); - StringWriter writer = new StringWriter(); - throwable.printStackTrace(new PrintWriter(writer)); - attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString()); + private static void setThrowable(LogRecordBuilder builder, AttributesBuilder attributes, Throwable throwable) { + if (builder instanceof ExtendedLogRecordBuilder) { + ((ExtendedLogRecordBuilder) builder).setException(throwable); + } else { + attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); + attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); + StringWriter writer = new StringWriter(); + throwable.printStackTrace(new PrintWriter(writer)); + attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString()); + } } private static Severity levelToSeverity(Level level) { diff --git a/instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java b/instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java index 20f92ec2cc10..515a583b7189 100644 --- a/instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java +++ b/instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java @@ -17,6 +17,7 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; import io.opentelemetry.api.logs.LogRecordBuilder; import io.opentelemetry.api.logs.LoggerProvider; import io.opentelemetry.api.logs.Severity; @@ -147,7 +148,7 @@ private void mapLoggingEvent( throwable = ((ThrowableProxy) throwableProxy).getThrowable(); } if (throwable != null) { - setThrowable(attributes, throwable); + setThrowable(builder, attributes, throwable); } captureMdcAttributes(attributes, loggingEvent.getMDCPropertyMap()); @@ -269,14 +270,16 @@ public static AttributeKey getMdcAttributeKey(String key) { return mdcAttributeKeys.computeIfAbsent(key, AttributeKey::stringKey); } - private static void setThrowable(AttributesBuilder attributes, Throwable throwable) { - // TODO (trask) extract method for recording exception into - // io.opentelemetry:opentelemetry-api - attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); - attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); - StringWriter writer = new StringWriter(); - throwable.printStackTrace(new PrintWriter(writer)); - attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString()); + private static void setThrowable(LogRecordBuilder builder, AttributesBuilder attributes, Throwable throwable) { + if (builder instanceof ExtendedLogRecordBuilder) { + ((ExtendedLogRecordBuilder) builder).setException(throwable); + } else { + attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); + attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); + StringWriter writer = new StringWriter(); + throwable.printStackTrace(new PrintWriter(writer)); + attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString()); + } } private static Severity levelToSeverity(Level level) { From 40c7dd3a9d6ffc45398286e29a4f624617c9ffba Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 22 Aug 2025 08:37:13 -0700 Subject: [PATCH 2/4] Simplify Java agent instrumentation --- .../instrumentation/jul/JavaUtilLoggingHelper.java | 9 ++------- .../appender/v1_1/LoggingEventMapper.java | 11 ++--------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java b/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java index 780e7307c845..773844696639 100644 --- a/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java +++ b/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java @@ -85,13 +85,8 @@ private static void mapLogRecord(LogRecordBuilder builder, LogRecord logRecord) // throwable Throwable throwable = logRecord.getThrown(); if (throwable != null) { - // TODO (trask) extract method for recording exception into - // io.opentelemetry:opentelemetry-api - attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); - attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); - StringWriter writer = new StringWriter(); - throwable.printStackTrace(new PrintWriter(writer)); - attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString()); + // this cast is safe within java agent instrumentation + ((ExtendedLogRecordBuilder) builder).setException(throwable); } if (captureExperimentalAttributes) { diff --git a/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java b/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java index e6175f057615..2a28f6b3e16b 100644 --- a/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java +++ b/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java @@ -82,15 +82,8 @@ public void capture(Logger logger, ExtLogRecord record) { Throwable throwable = record.getThrown(); if (throwable != null) { - if (builder instanceof ExtendedLogRecordBuilder) { - ((ExtendedLogRecordBuilder) builder).setException(throwable); - } else { - attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); - attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); - StringWriter writer = new StringWriter(); - throwable.printStackTrace(new PrintWriter(writer)); - attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString()); - } + // this cast is safe within java agent instrumentation + ((ExtendedLogRecordBuilder) builder).setException(throwable); } captureMdcAttributes(attributes); From 09f25c5448167e6871a84184d02605f57a94e16f Mon Sep 17 00:00:00 2001 From: otelbot <197425009+otelbot@users.noreply.github.com> Date: Fri, 22 Aug 2025 15:49:00 +0000 Subject: [PATCH 3/4] ./gradlew spotlessApply --- .../javaagent/instrumentation/jul/JavaUtilLoggingHelper.java | 3 --- .../jbosslogmanager/appender/v1_1/LoggingEventMapper.java | 5 +---- .../instrumentation/log4j/appender/v1_2/LogEventMapper.java | 2 +- .../log4j/appender/v2_17/internal/LogEventMapper.java | 3 ++- .../logback/appender/v1_0/internal/LoggingEventMapper.java | 3 ++- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java b/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java index 773844696639..d0caa51d45d8 100644 --- a/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java +++ b/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java @@ -13,10 +13,7 @@ import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; -import io.opentelemetry.semconv.ExceptionAttributes; import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes; -import java.io.PrintWriter; -import java.io.StringWriter; import java.util.concurrent.TimeUnit; import java.util.logging.Formatter; import java.util.logging.Level; diff --git a/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java b/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java index 2a28f6b3e16b..344c831605ac 100644 --- a/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java +++ b/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java @@ -12,16 +12,13 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; import io.opentelemetry.api.logs.LogRecordBuilder; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; -import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; import io.opentelemetry.instrumentation.api.internal.cache.Cache; import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; -import io.opentelemetry.semconv.ExceptionAttributes; import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes; -import java.io.PrintWriter; -import java.io.StringWriter; import java.util.List; import java.util.Map; import org.jboss.logmanager.ExtLogRecord; diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index 0cbe5c8b51ed..1f6966503fde 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -11,10 +11,10 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; import io.opentelemetry.api.logs.LogRecordBuilder; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; -import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.api.internal.cache.Cache; import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; diff --git a/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/internal/LogEventMapper.java b/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/internal/LogEventMapper.java index 5338477d5d7c..36ec63fcd186 100644 --- a/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/internal/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/internal/LogEventMapper.java @@ -234,7 +234,8 @@ public static AttributeKey getMapMessageAttributeKey(String key) { key, k -> AttributeKey.stringKey("log4j.map_message." + k)); } - private static void setThrowable(LogRecordBuilder builder, AttributesBuilder attributes, Throwable throwable) { + private static void setThrowable( + LogRecordBuilder builder, AttributesBuilder attributes, Throwable throwable) { if (builder instanceof ExtendedLogRecordBuilder) { ((ExtendedLogRecordBuilder) builder).setException(throwable); } else { diff --git a/instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java b/instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java index 515a583b7189..0819c73a93d1 100644 --- a/instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java +++ b/instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java @@ -270,7 +270,8 @@ public static AttributeKey getMdcAttributeKey(String key) { return mdcAttributeKeys.computeIfAbsent(key, AttributeKey::stringKey); } - private static void setThrowable(LogRecordBuilder builder, AttributesBuilder attributes, Throwable throwable) { + private static void setThrowable( + LogRecordBuilder builder, AttributesBuilder attributes, Throwable throwable) { if (builder instanceof ExtendedLogRecordBuilder) { ((ExtendedLogRecordBuilder) builder).setException(throwable); } else { From f1e0aceff64fd60aed49dc916a1a8d4990bd297a Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 22 Aug 2025 10:15:46 -0700 Subject: [PATCH 4/4] fix --- .../javaagent/instrumentation/jul/JavaUtilLoggingHelper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java b/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java index d0caa51d45d8..dfc29d6ad673 100644 --- a/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java +++ b/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java @@ -9,6 +9,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; import io.opentelemetry.api.logs.LogRecordBuilder; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context;