diff --git a/README.md b/README.md
index 572d6a77..e26867fb 100644
--- a/README.md
+++ b/README.md
@@ -25,8 +25,8 @@ Java реализация [Библиотеки RPC вызовов][rpc-lib] д
## Ключевые возможности
- Сквозная трассировка вызовов через `TraceData`, автоматическое измерение
- длительности и интеграция со SLF4J MDC и OpenTelemetry.
-- Расширенный MDC: автоматически публикует идентификаторы Woody/OTel, дедлайны,
+ длительности и интеграция со SLF4J MDC.
+- Расширенный MDC: автоматически публикует идентификаторы Woody, дедлайны,
RPC-метаданные и может отключаться через `-Dwoody.mdc.extended=false`.
- Потокобезопасная обработка фоновых задач с сохранением контекста
(`WFlow.create`, `createServiceFork`).
@@ -57,14 +57,14 @@ _woody-pom_ и в корневой директории проекта выпо
`woody-api`, интеграция `woody-thrift`, а также пропатченный `libthrift`
(форк Apache Thrift, переиспользующий HttpClient5 и подключающийся как
модуль).
-- Основной стек: Java 11, SLF4J, Apache Commons Pool 2, OpenTelemetry
- (API/SDK/OTLP), Jakarta Servlet 5, Jetty и EasyMock в тестах.
+- Основной стек: Java 11, SLF4J, Apache Commons Pool 2, Jakarta Servlet 5,
+ Jetty и EasyMock в тестах.
## Woody API
- `TraceContext`/`TraceData` управляют client/service span’ами в
`ThreadLocal`, автоматически создают `trace_id/span_id`, фиксируют
- длительность, синхронизируют SLF4J MDC и завершают OTEL-спаны.
+ длительность и синхронизируют SLF4J MDC.
- `WFlow` и `flow.concurrent` оборачивают `Runnable`/`Callable`/
`ExecutorService`, сохраняя контекст при выполнении в других потоках,
поддерживают форки с новыми root- и service-span’ами.
@@ -88,7 +88,7 @@ _woody-pom_ и в корневой директории проекта выпо
- Thrift over HTTP поверх Woody.
- Клиенты (`THClientBuilder`, `THSpawnClientBuilder`,
`THPooledClientBuilder`) создают `TServiceClient`, добавляют
- транспортные и message перехватчики (метаданные, traceparent, события),
+ транспортные и message перехватчики (метаданные, события),
управляют ресурсами HttpClient5.
- Сервисы (`THServiceBuilder`) собирают `TServlet` с обёртками над
`TProcessor`, прокидывая `TraceContext.forService`, подключая
@@ -98,8 +98,7 @@ _woody-pom_ и в корневой директории проекта выпо
- Транспорт и сообщения расширяются через bundles
(`MetadataExtensionBundle` и др.), создавая `THCExtensionContext`/
`THSExtensionContext` для клиента и сервиса.
- - Поддержка W3C traceparent (`TraceParentUtils`), заполнение
- дедлайнов/ошибок в метаданные, HTTP-логгеры.
+ - Заполнение дедлайнов/ошибок в метаданные, HTTP-логгеры.
- Дополнительные пакеты: `error` (конвертация исключений и
HTTP-статусов), `event` (логирование), `transport` (конфигурация HTTP
servlet’ов и клиентов).
@@ -115,16 +114,9 @@ _woody-pom_ и в корневой директории проекта выпо
- `woody-api/src/test` покрывает генераторы идентификаторов, трассировку и
прокси.
- `woody-thrift/src/test` (Jetty quickstart + EasyMock) проверяет
- HTTP-интеграцию, обработку исключений и метаданные, включая
- интеграционные сценарии `TraceLifecycleIntegrationTest` для проверки
- сквозной OpenTelemetry-трассировки, восстановления контекста, ошибок и
- работы с неполными заголовками.
+ HTTP-интеграцию, обработку исключений и метаданные.
- Профиль `gen_thrift_classes` включает `thrift-maven-plugin` для генерации
Thrift IDL.
-- Интеграционные тесты `MetadataMdcPropagationTest` и
- `TraceLifecycleIntegrationTest` контролируют перенос MDC-метаданных,
- OpenTelemetry-трассировку и восстановление контекста при ошибках.
-
## Дополнительные материалы
- [Контекст Woody Java](context.md) — сводный обзор модулей,
@@ -134,8 +126,8 @@ _woody-pom_ и в корневой директории проекта выпо
Реализация обеспечивает сквозную трассировку, управление временем жизни
span’ов и доступ к событиям через единую API-обвязку; `woody-thrift` поверх
-неё инкапсулирует создание HTTP-клиентов и сервисов Thrift с `traceparent`,
-логированием и расширяемыми метаданными, опираясь на локально
+неё инкапсулирует создание HTTP-клиентов и сервисов Thrift с логированием и
+расширяемыми метаданными, опираясь на локально
модифицированный `libthrift`.
[rpc-lib]: http://52.29.202.218/design/ms/platform/rpc-lib/
diff --git a/context.md b/context.md
index b92993b3..df92acd4 100644
--- a/context.md
+++ b/context.md
@@ -5,8 +5,7 @@
- Maven multi-module library delivering RPC tracing infrastructure for
microservices.
- Java 11 baseline; core dependencies include SLF4J, Apache Commons Pool 2,
- OpenTelemetry (API/SDK/OTLP exporter), Jakarta Servlet 5, HttpClient5, Jetty
- (tests), EasyMock.
+ Jakarta Servlet 5, HttpClient5, Jetty (tests), EasyMock.
- Modules share version `woody` (root POM); `dependencyManagement` keeps `woody-
api` version-aligned.
@@ -15,9 +14,8 @@
### woody-api
- Thread-local tracing via `TraceContext`/`TraceData` managing client/service
- spans, auto ID generation, duration tracking, SLF4J MDC sync, OTEL span
- lifecycle.
-- `MDCUtils` публикует trace/span идентификаторы Woody и OpenTelemetry,
+ spans, auto ID generation, duration tracking and SLF4J MDC sync.
+- `MDCUtils` публикует trace/span идентификаторы Woody,
дедлайны и RPC-метаданные (отключаемо через системное свойство
`woody.mdc.extended`).
- Concurrency helpers (`WFlow`, `WCallable`, `WRunnable`, `WExecutorService`)
@@ -42,13 +40,12 @@
- Thrift-over-HTTP implementation layered on woody-api.
- Client builders (`THClientBuilder`, `THSpawnClientBuilder`,
`THPooledClientBuilder`) construct `TServiceClient`, inject message/transport
- interceptors, traceparent propagation, metadata extensions, logging
- (`THCEventLogListener`); support custom or pooled HttpClient5.
+ interceptors, metadata extensions, logging (`THCEventLogListener`); support
+ custom or pooled HttpClient5.
- Service builder (`THServiceBuilder`) wraps `TProcessor` into `TServlet`,
applies transport interceptors, `THErrorMapProcessor`, logging
(`THSEventLogListener`), and ensures `TraceContext.forService`.
-- Extension bundles produce `THCExtensionContext`/`THSExtensionContext`;
- `TraceParentUtils` handles W3C traceparent parsing/serialization.
+- Extension bundles produce `THCExtensionContext`/`THSExtensionContext`.
- Supplemental packages: `error` (exception ↔ response mapping), `event` (HTTP
logging), `transport` (servlet/client wiring).
- Обновлённый `THProviderErrorMapper` синхронизирует статус, источники ошибок,
@@ -72,17 +69,13 @@
- `woody-api/src/test`: ID generators, tracing logic, proxy behavior.
- `woody-thrift/src/test`: Jetty quickstart servers + EasyMock cover HTTP
- integration, metadata propagation, error mapping, а также свежие
- интеграционные сценарии `TraceLifecycleIntegrationTest`, проверяющие
- сквозную OpenTelemetry-трассировку (новый/восстановленный контекст,
- обработку ошибок, отсутствие обязательных метаданных).
-- Дополнительно `THProviderErrorMapperTest` и `MetadataMdcPropagationTest`
- контролируют обработку ошибок и перенос MDC/OTel данных.
+ integration, metadata propagation and error mapping.
+- Дополнительно `THProviderErrorMapperTest` контролирует обработку ошибок.
## Key Concepts for Agents
- Always maintain root/service/client span consistency; `TraceContext`
- orchestrates init/destroy hooks and ensures MDC/Otel sync.
+ orchestrates init/destroy hooks and ensures MDC sync.
- Cross-thread execution must wrap tasks with
`WFlow.create`/`createServiceFork`.
- Interceptors are composable; metadata extensions rely on extension bundles
@@ -122,4 +115,4 @@
- For new metadata, implement `MetadataExtensionKit` and include via builder
`withMetaExtensions`.
- Для фоновых задач используйте `WFlow.createServiceFork(...)` — он создаёт
- новый service-span и корректно инициализирует OpenTelemetry контекст.
+ новый service-span и корректно инициализирует контекст.
diff --git a/libthrift/pom.xml b/libthrift/pom.xml
index a82dc6b1..4db41875 100644
--- a/libthrift/pom.xml
+++ b/libthrift/pom.xml
@@ -7,7 +7,7 @@
woody
dev.vality.woody
- 2.1.0
+ 3.0.0
libthrift
diff --git a/pom.xml b/pom.xml
index 0608f425..41682045 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
pom
dev.vality.woody
woody
- 2.1.0
+ 3.0.0
Woody Java
Java implementation for Woody spec
@@ -46,8 +46,6 @@
UTF-8
11
11
- 1.49.0
- 1.37.0
@@ -68,26 +66,6 @@
slf4j-api
1.7.36
-
- io.opentelemetry.semconv
- opentelemetry-semconv
- ${opentelemetry-semconv.version}
-
-
- io.opentelemetry
- opentelemetry-api
- ${opentelemetry.version}
-
-
- io.opentelemetry
- opentelemetry-sdk
- ${opentelemetry.version}
-
-
- io.opentelemetry
- opentelemetry-exporter-otlp
- ${opentelemetry.version}
-
diff --git a/woody-api/pom.xml b/woody-api/pom.xml
index 0197580d..a98dc6ea 100644
--- a/woody-api/pom.xml
+++ b/woody-api/pom.xml
@@ -7,7 +7,7 @@
woody
dev.vality.woody
- 2.1.0
+ 3.0.0
woody-api
@@ -51,23 +51,6 @@
commons-pool2
2.12.1
-
-
- io.opentelemetry
- opentelemetry-api
-
-
- io.opentelemetry
- opentelemetry-sdk
-
-
- io.opentelemetry
- opentelemetry-exporter-otlp
-
-
- io.opentelemetry.semconv
- opentelemetry-semconv
-
junit
diff --git a/woody-api/src/main/java/dev/vality/woody/api/AbstractClientBuilder.java b/woody-api/src/main/java/dev/vality/woody/api/AbstractClientBuilder.java
index c10e6018..e6ae846f 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/AbstractClientBuilder.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/AbstractClientBuilder.java
@@ -12,7 +12,6 @@
import dev.vality.woody.api.trace.ContextSpan;
import dev.vality.woody.api.proxy.tracer.*;
import dev.vality.woody.api.trace.context.TraceContext;
-import io.opentelemetry.sdk.resources.Resource;
import java.net.URI;
import java.util.concurrent.atomic.AtomicBoolean;
diff --git a/woody-api/src/main/java/dev/vality/woody/api/AbstractServiceBuilder.java b/woody-api/src/main/java/dev/vality/woody/api/AbstractServiceBuilder.java
index 5c57c1b9..fd968135 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/AbstractServiceBuilder.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/AbstractServiceBuilder.java
@@ -5,7 +5,6 @@
import dev.vality.woody.api.proxy.ProxyFactory;
import dev.vality.woody.api.proxy.SingleTargetProvider;
import dev.vality.woody.api.proxy.tracer.*;
-import io.opentelemetry.sdk.resources.Resource;
import java.util.concurrent.atomic.AtomicBoolean;
diff --git a/woody-api/src/main/java/dev/vality/woody/api/ClientBuilder.java b/woody-api/src/main/java/dev/vality/woody/api/ClientBuilder.java
index 6b91b783..6e5a4e85 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/ClientBuilder.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/ClientBuilder.java
@@ -2,7 +2,6 @@
import dev.vality.woody.api.event.ClientEventListener;
import dev.vality.woody.api.generator.IdGenerator;
-import io.opentelemetry.sdk.resources.Resource;
import java.net.URI;
diff --git a/woody-api/src/main/java/dev/vality/woody/api/MDCUtils.java b/woody-api/src/main/java/dev/vality/woody/api/MDCUtils.java
index 21fe75c7..50af1fda 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/MDCUtils.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/MDCUtils.java
@@ -16,9 +16,6 @@
public class MDCUtils {
public static final String SPAN_ID = "span_id";
- public static final String OTEL_TRACE_ID = "otel_trace_id";
- public static final String OTEL_SPAN_ID = "otel_span_id";
- public static final String OTEL_TRACE_FLAGS = "otel_trace_flags";
public static final String TRACE_ID = "trace_id";
public static final String PARENT_ID = "parent_id";
public static final String DEADLINE = "deadline";
@@ -37,61 +34,40 @@ public static void putTraceData(TraceData traceData, ContextSpan contextSpan) {
return;
}
- io.opentelemetry.api.trace.Span otelSpan = traceData.getOtelSpan();
- io.opentelemetry.api.trace.SpanContext spanContext = otelSpan != null ? otelSpan.getSpanContext() : null;
-
- populateSpanIdentifiers(contextSpan.getSpan(), otelSpan);
- populateOtelIdentifiers(spanContext, otelSpan);
+ populateSpanIdentifiers(contextSpan.getSpan());
boolean updatingClientSpan = traceData.getClientSpan() == contextSpan;
boolean updatingServiceSpan = traceData.getServiceSpan() == contextSpan;
if (isExtendedFieldsEnabled()) {
if (updatingClientSpan) {
- clearExtendedEntriesWithPrefix(TRACE_RPC_CLIENT_PREFIX, otelSpan);
+ clearExtendedEntriesWithPrefix(TRACE_RPC_CLIENT_PREFIX);
}
if (updatingServiceSpan) {
- clearExtendedEntriesWithPrefix(TRACE_RPC_SERVER_PREFIX, otelSpan);
+ clearExtendedEntriesWithPrefix(TRACE_RPC_SERVER_PREFIX);
}
if (!updatingClientSpan && !updatingServiceSpan) {
- clearExtendedEntries(false, otelSpan);
+ clearExtendedEntries(false);
}
- populateExtendedFields(traceData, otelSpan);
+ populateExtendedFields(traceData);
} else {
- clearExtendedEntries(false, otelSpan);
+ clearExtendedEntries(false);
}
- updateDeadlineEntries(traceData, contextSpan, otelSpan);
- }
-
- private static void populateSpanIdentifiers(Span span, io.opentelemetry.api.trace.Span otelSpan) {
- putTraceValue(otelSpan, SPAN_ID, span.getId());
- putTraceValue(otelSpan, TRACE_ID, span.getTraceId());
- putTraceValue(otelSpan, PARENT_ID, span.getParentId());
+ updateDeadlineEntries(traceData, contextSpan);
}
- private static void populateOtelIdentifiers(io.opentelemetry.api.trace.SpanContext spanContext,
- io.opentelemetry.api.trace.Span otelSpan) {
- if (spanContext == null) {
- putTraceValue(otelSpan, OTEL_TRACE_ID, null);
- putTraceValue(otelSpan, OTEL_SPAN_ID, null);
- putTraceValue(otelSpan, OTEL_TRACE_FLAGS, null);
- return;
- }
- putTraceValue(otelSpan, OTEL_TRACE_ID, spanContext.getTraceId());
- putTraceValue(otelSpan, OTEL_SPAN_ID, spanContext.getSpanId());
- putTraceValue(otelSpan, OTEL_TRACE_FLAGS,
- spanContext.getTraceFlags() != null ? spanContext.getTraceFlags().asHex() : null);
+ private static void populateSpanIdentifiers(Span span) {
+ putTraceValue(SPAN_ID, span.getId());
+ putTraceValue(TRACE_ID, span.getTraceId());
+ putTraceValue(PARENT_ID, span.getParentId());
}
public static void removeTraceData() {
MDC.remove(SPAN_ID);
MDC.remove(TRACE_ID);
- MDC.remove(OTEL_TRACE_ID);
- MDC.remove(OTEL_SPAN_ID);
- MDC.remove(OTEL_TRACE_FLAGS);
MDC.remove(DEADLINE);
- clearExtendedEntries(true, null);
+ clearExtendedEntries(true);
}
public static void putDeadline(TraceData traceData, ContextSpan contextSpan, Instant deadline) {
@@ -99,14 +75,11 @@ public static void putDeadline(TraceData traceData, ContextSpan contextSpan, Ins
removeDeadline(traceData, contextSpan);
return;
}
-
- io.opentelemetry.api.trace.Span otelSpan = traceData != null ? traceData.getOtelSpan() : null;
- updateDeadlineEntries(traceData, contextSpan, otelSpan);
+ updateDeadlineEntries(traceData, contextSpan);
}
public static void removeDeadline(TraceData traceData, ContextSpan contextSpan) {
- io.opentelemetry.api.trace.Span otelSpan = traceData != null ? traceData.getOtelSpan() : null;
- updateDeadlineEntries(traceData, contextSpan, otelSpan);
+ updateDeadlineEntries(traceData, contextSpan);
}
public static void enableExtendedFields() {
@@ -115,40 +88,38 @@ public static void enableExtendedFields() {
public static void disableExtendedFields() {
extendedFieldsEnabled = false;
- clearExtendedEntries(false, null);
+ clearExtendedEntries(false);
}
public static boolean isExtendedFieldsEnabled() {
return extendedFieldsEnabled;
}
- private static void populateExtendedFields(TraceData traceData, io.opentelemetry.api.trace.Span otelSpan) {
- addSpanDetails(traceData.getClientSpan(), TRACE_RPC_CLIENT_PREFIX, otelSpan);
- addSpanDetails(traceData.getServiceSpan(), TRACE_RPC_SERVER_PREFIX, otelSpan);
+ private static void populateExtendedFields(TraceData traceData) {
+ addSpanDetails(traceData.getClientSpan(), TRACE_RPC_CLIENT_PREFIX);
+ addSpanDetails(traceData.getServiceSpan(), TRACE_RPC_SERVER_PREFIX);
}
- private static void addSpanDetails(ContextSpan contextSpan, String prefix,
- io.opentelemetry.api.trace.Span otelSpan) {
+ private static void addSpanDetails(ContextSpan contextSpan, String prefix) {
if (contextSpan == null || !contextSpan.isFilled()) {
return;
}
- addExtendedEntry(otelSpan, prefix + "service", resolveServiceName(contextSpan));
- addExtendedEntry(otelSpan, prefix + "function", resolveFunctionName(contextSpan));
- addExtendedEntry(otelSpan, prefix + "type", resolveCallType(contextSpan));
- addExtendedEntry(otelSpan, prefix + "event", resolveEvent(contextSpan));
- addExtendedEntry(otelSpan, prefix + "url", resolveEndpoint(contextSpan));
+ addExtendedEntry(prefix + "service", resolveServiceName(contextSpan));
+ addExtendedEntry(prefix + "function", resolveFunctionName(contextSpan));
+ addExtendedEntry(prefix + "type", resolveCallType(contextSpan));
+ addExtendedEntry(prefix + "event", resolveEvent(contextSpan));
+ addExtendedEntry(prefix + "url", resolveEndpoint(contextSpan));
long duration = contextSpan.getSpan().getDuration();
if (duration > 0) {
- addExtendedEntry(otelSpan, prefix + "execution_duration_ms", Long.toString(duration));
+ addExtendedEntry(prefix + "execution_duration_ms", Long.toString(duration));
}
- addCustomMetadataEntries(contextSpan, prefix + TRACE_RPC_METADATA_SUFFIX, otelSpan);
+ addCustomMetadataEntries(contextSpan, prefix + TRACE_RPC_METADATA_SUFFIX);
}
- private static void addCustomMetadataEntries(ContextSpan contextSpan, String prefix,
- io.opentelemetry.api.trace.Span otelSpan) {
+ private static void addCustomMetadataEntries(ContextSpan contextSpan, String prefix) {
Metadata metadata = contextSpan.getCustomMetadata();
if (metadata == null) {
return;
@@ -156,7 +127,7 @@ private static void addCustomMetadataEntries(ContextSpan contextSpan, String pre
for (String key : metadata.getKeys()) {
Object value = metadata.getValue(key);
if (value != null) {
- addExtendedEntry(otelSpan, prefix + key, Objects.toString(value));
+ addExtendedEntry(prefix + key, Objects.toString(value));
}
}
}
@@ -224,11 +195,11 @@ private static String formatEnum(Enum> value) {
return value == null ? null : value.name().toLowerCase(Locale.ROOT).replace('_', ' ');
}
- private static void addExtendedEntry(io.opentelemetry.api.trace.Span otelSpan, String key, String value) {
+ private static void addExtendedEntry(String key, String value) {
if (key == null || value == null || value.isEmpty()) {
return;
}
- putTraceValue(otelSpan, key, value);
+ putTraceValue(key, value);
EXTENDED_MDC_KEYS.get().add(key);
}
@@ -236,24 +207,17 @@ private static void putMdcValue(String key, String value) {
MDC.put(key, value != null ? value : "");
}
- public static void removeExtendedEntry(io.opentelemetry.api.trace.Span otelSpan, String key) {
+ public static void removeExtendedEntry(String key) {
MDC.remove(key);
EXTENDED_MDC_KEYS.get().remove(key);
- if (otelSpan != null) {
- otelSpan.setAttribute(key, null);
- }
}
- private static void updateDeadlineEntries(TraceData traceData, ContextSpan contextSpan,
- io.opentelemetry.api.trace.Span otelSpan) {
+ private static void updateDeadlineEntries(TraceData traceData, ContextSpan contextSpan) {
Instant activeDeadline = contextSpan != null ? ContextUtils.getDeadline(contextSpan) : null;
if (activeDeadline != null) {
- putTraceValue(otelSpan, DEADLINE, activeDeadline.toString());
+ putTraceValue(DEADLINE, activeDeadline.toString());
} else {
MDC.remove(DEADLINE);
- if (otelSpan != null) {
- otelSpan.setAttribute(DEADLINE, null);
- }
}
boolean updatingClientSpan = traceData != null && traceData.getClientSpan() == contextSpan;
@@ -261,54 +225,48 @@ private static void updateDeadlineEntries(TraceData traceData, ContextSpan conte
if (!isExtendedFieldsEnabled()) {
if (updatingClientSpan || (!updatingClientSpan && !updatingServiceSpan)) {
- removeExtendedEntry(otelSpan, TRACE_RPC_CLIENT_PREFIX + "deadline");
+ removeExtendedEntry(TRACE_RPC_CLIENT_PREFIX + "deadline");
}
if (updatingServiceSpan || (!updatingClientSpan && !updatingServiceSpan)) {
- removeExtendedEntry(otelSpan, TRACE_RPC_SERVER_PREFIX + "deadline");
+ removeExtendedEntry(TRACE_RPC_SERVER_PREFIX + "deadline");
}
return;
}
if (traceData != null) {
if (updatingClientSpan) {
- removeExtendedEntry(otelSpan, TRACE_RPC_CLIENT_PREFIX + "deadline");
+ removeExtendedEntry(TRACE_RPC_CLIENT_PREFIX + "deadline");
}
if (updatingServiceSpan) {
- removeExtendedEntry(otelSpan, TRACE_RPC_SERVER_PREFIX + "deadline");
+ removeExtendedEntry(TRACE_RPC_SERVER_PREFIX + "deadline");
}
if (!updatingClientSpan && !updatingServiceSpan) {
- removeExtendedEntry(otelSpan, TRACE_RPC_CLIENT_PREFIX + "deadline");
- removeExtendedEntry(otelSpan, TRACE_RPC_SERVER_PREFIX + "deadline");
+ removeExtendedEntry(TRACE_RPC_CLIENT_PREFIX + "deadline");
+ removeExtendedEntry(TRACE_RPC_SERVER_PREFIX + "deadline");
}
- addDeadlineEntry(traceData.getClientSpan(), TRACE_RPC_CLIENT_PREFIX, otelSpan);
- addDeadlineEntry(traceData.getServiceSpan(), TRACE_RPC_SERVER_PREFIX, otelSpan);
+ addDeadlineEntry(traceData.getClientSpan(), TRACE_RPC_CLIENT_PREFIX);
+ addDeadlineEntry(traceData.getServiceSpan(), TRACE_RPC_SERVER_PREFIX);
}
}
- private static void addDeadlineEntry(ContextSpan span, String prefix, io.opentelemetry.api.trace.Span otelSpan) {
+ private static void addDeadlineEntry(ContextSpan span, String prefix) {
if (span == null) {
return;
}
Instant deadline = ContextUtils.getDeadline(span);
if (deadline != null) {
- addExtendedEntry(otelSpan, prefix + "deadline", deadline.toString());
+ addExtendedEntry(prefix + "deadline", deadline.toString());
}
}
- private static void putTraceValue(io.opentelemetry.api.trace.Span otelSpan, String key, String value) {
+ private static void putTraceValue(String key, String value) {
putMdcValue(key, value);
- if (otelSpan != null) {
- otelSpan.setAttribute(key, value != null ? value : "");
- }
}
- private static void clearExtendedEntries(boolean removeThreadLocal, io.opentelemetry.api.trace.Span otelSpan) {
+ private static void clearExtendedEntries(boolean removeThreadLocal) {
Set keys = EXTENDED_MDC_KEYS.get();
for (String key : keys) {
MDC.remove(key);
- if (otelSpan != null) {
- otelSpan.setAttribute(key, null);
- }
}
if (removeThreadLocal) {
@@ -318,17 +276,13 @@ private static void clearExtendedEntries(boolean removeThreadLocal, io.opentelem
}
}
- private static void clearExtendedEntriesWithPrefix(String prefix,
- io.opentelemetry.api.trace.Span otelSpan) {
+ private static void clearExtendedEntriesWithPrefix(String prefix) {
Set keys = EXTENDED_MDC_KEYS.get();
Iterator iterator = keys.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
if (key.startsWith(prefix)) {
MDC.remove(key);
- if (otelSpan != null) {
- otelSpan.setAttribute(key, null);
- }
iterator.remove();
}
}
diff --git a/woody-api/src/main/java/dev/vality/woody/api/ServiceBuilder.java b/woody-api/src/main/java/dev/vality/woody/api/ServiceBuilder.java
index 9730facf..f75ac382 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/ServiceBuilder.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/ServiceBuilder.java
@@ -1,7 +1,6 @@
package dev.vality.woody.api;
import dev.vality.woody.api.event.ServiceEventListener;
-import io.opentelemetry.sdk.resources.Resource;
public interface ServiceBuilder {
ServiceBuilder withEventListener(ServiceEventListener listener);
diff --git a/woody-api/src/main/java/dev/vality/woody/api/flow/concurrent/WCallable.java b/woody-api/src/main/java/dev/vality/woody/api/flow/concurrent/WCallable.java
index 36ea2ff3..e58b9595 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/flow/concurrent/WCallable.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/flow/concurrent/WCallable.java
@@ -56,15 +56,10 @@ public T call() throws Exception {
clonedTraceData.getClientSpan().getSpan().setDeadline(deadline);
}
}
- if (clonedTraceData.getServiceSpan().getSpan().isStarted()) {
- clonedTraceData.clearPreserveOtelSpan();
- } else {
+ if (!clonedTraceData.getServiceSpan().getSpan().isStarted()) {
clonedTraceData.getServiceSpan().getSpan().setTimestamp(0);
clonedTraceData.getServiceSpan().getSpan().setDuration(0);
- clonedTraceData.clearPreserveOtelSpan();
}
- } else {
- clonedTraceData.clearPreserveOtelSpan();
}
TraceContext.setCurrentTraceData(clonedTraceData);
diff --git a/woody-api/src/main/java/dev/vality/woody/api/flow/concurrent/WRunnable.java b/woody-api/src/main/java/dev/vality/woody/api/flow/concurrent/WRunnable.java
index 8e2f0630..710acf98 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/flow/concurrent/WRunnable.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/flow/concurrent/WRunnable.java
@@ -55,15 +55,10 @@ public void run() {
clonedTraceData.getClientSpan().getSpan().setDeadline(deadline);
}
}
- if (clonedTraceData.getServiceSpan().getSpan().isStarted()) {
- clonedTraceData.clearPreserveOtelSpan();
- } else {
+ if (!clonedTraceData.getServiceSpan().getSpan().isStarted()) {
clonedTraceData.getServiceSpan().getSpan().setTimestamp(0);
clonedTraceData.getServiceSpan().getSpan().setDuration(0);
- clonedTraceData.clearPreserveOtelSpan();
}
- } else {
- clonedTraceData.clearPreserveOtelSpan();
}
TraceContext.setCurrentTraceData(clonedTraceData);
diff --git a/woody-api/src/main/java/dev/vality/woody/api/trace/ContextSpan.java b/woody-api/src/main/java/dev/vality/woody/api/trace/ContextSpan.java
index 697f7f39..4a62be25 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/trace/ContextSpan.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/trace/ContextSpan.java
@@ -1,9 +1,5 @@
package dev.vality.woody.api.trace;
-import io.opentelemetry.api.trace.SpanKind;
-import io.opentelemetry.api.trace.Tracer;
-import io.opentelemetry.api.OpenTelemetry;
-
public class ContextSpan {
protected final Span span;
diff --git a/woody-api/src/main/java/dev/vality/woody/api/trace/TraceData.java b/woody-api/src/main/java/dev/vality/woody/api/trace/TraceData.java
index e0e324d6..bd2ded1a 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/trace/TraceData.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/trace/TraceData.java
@@ -1,33 +1,12 @@
package dev.vality.woody.api.trace;
-import io.opentelemetry.api.GlobalOpenTelemetry;
-import io.opentelemetry.api.trace.Span;
-import io.opentelemetry.api.trace.SpanKind;
-import io.opentelemetry.context.Context;
-import io.opentelemetry.context.Scope;
-
public class TraceData {
- public static final String OTEL_SERVER = "server";
- public static final String OTEL_CLIENT = "client";
- public static final String WOODY = "woody";
-
private final ClientSpan clientSpan;
private final ServiceSpan serviceSpan;
- private Span otelSpan;
- private Context otelContext;
- private Scope activeScope;
- private boolean ownsOtelSpan;
- private boolean preserveOtelSpan;
- private Context pendingParentContext;
- private String inboundTraceParent;
- private String inboundTraceState;
-
public TraceData() {
this.clientSpan = new ClientSpan();
this.serviceSpan = new ServiceSpan();
- setPendingParentContext(Context.root());
- startPlaceholderSpan();
}
public TraceData(TraceData oldTraceData) {
@@ -39,14 +18,6 @@ public TraceData(TraceData oldTraceData, boolean copyCustomServiceMetadata) {
? new ClientSpan(oldTraceData.clientSpan, oldTraceData.serviceSpan.getCustomMetadata())
: oldTraceData.clientSpan.cloneObject();
this.serviceSpan = oldTraceData.serviceSpan.cloneObject();
- adoptOtelContext(oldTraceData.getOtelContext());
- this.otelSpan = oldTraceData.otelSpan;
- this.ownsOtelSpan = false;
- this.activeScope = null;
- this.pendingParentContext = oldTraceData.pendingParentContext;
- this.inboundTraceParent = oldTraceData.inboundTraceParent;
- this.inboundTraceState = oldTraceData.inboundTraceState;
- this.preserveOtelSpan = true;
}
public TraceData(TraceData oldTraceData, boolean copyCustomServiceMetadata, String resource) {
@@ -61,86 +32,6 @@ public ServiceSpan getServiceSpan() {
return serviceSpan;
}
- public Span getOtelSpan() {
- return otelSpan;
- }
-
- public Context getOtelContext() {
- return otelContext;
- }
-
- public void setPendingParentContext(Context context) {
- this.pendingParentContext = context == null ? Context.root() : context;
- }
-
- public Context consumePendingParentContext() {
- Context context = pendingParentContext;
- pendingParentContext = Context.root();
- return context;
- }
-
- public void setInboundTraceParent(String traceParent) {
- this.inboundTraceParent = traceParent;
- }
-
- public String getInboundTraceParent() {
- return inboundTraceParent;
- }
-
- public void setInboundTraceState(String traceState) {
- this.inboundTraceState = traceState;
- }
-
- public String getInboundTraceState() {
- return inboundTraceState;
- }
-
- public void startNewOtelSpan(String spanName, SpanKind spanKind, Context parentContext) {
- closeActiveScope();
- if (otelSpan != null && otelSpan.getSpanContext().isValid()) {
- otelSpan.end();
- }
- Context context = parentContext != null ? parentContext : Context.root();
- Span span = GlobalOpenTelemetry.getTracer(WOODY)
- .spanBuilder(spanName)
- .setSpanKind(spanKind)
- .setParent(context)
- .startSpan();
- this.otelSpan = span;
- this.otelContext = context.with(span);
- this.ownsOtelSpan = true;
- this.preserveOtelSpan = false;
- }
-
- public void openOtelScope() {
- closeActiveScope();
- this.activeScope = otelContext.makeCurrent();
- }
-
- public void finishOtelSpan() {
- closeActiveScope();
- if (ownsOtelSpan && otelSpan != null) {
- otelSpan.end();
- }
- otelSpan = Span.getInvalid();
- otelContext = Context.root();
- ownsOtelSpan = false;
- preserveOtelSpan = false;
- inboundTraceParent = null;
- inboundTraceState = null;
- }
-
- private void closeActiveScope() {
- if (activeScope != null) {
- activeScope.close();
- activeScope = null;
- }
- }
-
- private void adoptOtelContext(Context context) {
- this.otelContext = context == null ? Context.root() : context;
- }
-
/**
* Checks if {@link ServiceSpan} is filled to determine root:
* - request initialized by server: span must be filled by server with data referred from client:
@@ -198,29 +89,9 @@ public ContextSpan getSpan(boolean isClient) {
public void reset() {
clientSpan.reset();
serviceSpan.reset();
- finishOtelSpan();
- setPendingParentContext(Context.root());
- inboundTraceParent = null;
- inboundTraceState = null;
}
public TraceData cloneObject() {
return new TraceData(this);
}
-
- public boolean shouldPreserveOtelSpan() {
- return preserveOtelSpan && otelSpan != null && otelSpan.getSpanContext().isValid();
- }
-
- public void clearPreserveOtelSpan() {
- this.preserveOtelSpan = false;
- }
-
- private void startPlaceholderSpan() {
- this.otelSpan = Span.getInvalid();
- this.otelContext = Context.root();
- this.ownsOtelSpan = false;
- this.activeScope = null;
- this.preserveOtelSpan = false;
- }
}
diff --git a/woody-api/src/main/java/dev/vality/woody/api/trace/context/TraceContext.java b/woody-api/src/main/java/dev/vality/woody/api/trace/context/TraceContext.java
index 34a054ce..0a2eccb6 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/trace/context/TraceContext.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/trace/context/TraceContext.java
@@ -4,8 +4,6 @@
import dev.vality.woody.api.generator.IdGenerator;
import dev.vality.woody.api.trace.Span;
import dev.vality.woody.api.trace.TraceData;
-import io.opentelemetry.api.trace.SpanKind;
-import io.opentelemetry.context.Context;
import java.util.Optional;
@@ -158,7 +156,6 @@ public void init() {
traceData = initServiceContext(traceData);
}
setCurrentTraceData(traceData);
- initializeOtelSpan(traceData, clientInit);
MDCUtils.putTraceData(traceData, traceData.getActiveSpan());
postInit.run();
@@ -185,7 +182,6 @@ public void destroy(boolean onError) {
preDestroy.run();
}
} finally {
- traceData.finishOtelSpan();
if (isClient) {
restored = destroyClientContext(traceData);
clearContext = restored == null;
@@ -212,30 +208,6 @@ private void setDuration(TraceData traceData, boolean isClient) {
span.setDuration(System.currentTimeMillis() - span.getTimestamp());
}
- private void initializeOtelSpan(TraceData traceData, boolean clientInit) {
- if (traceData.shouldPreserveOtelSpan()) {
- traceData.setPendingParentContext(Context.root());
- traceData.openOtelScope();
- traceData.clearPreserveOtelSpan();
- return;
- }
-
- if (clientInit) {
- traceData.startNewOtelSpan(TraceData.OTEL_CLIENT, SpanKind.CLIENT, Context.current());
- traceData.setPendingParentContext(Context.root());
- traceData.openOtelScope();
- return;
- }
-
- Context parentContext = traceData.consumePendingParentContext();
- if (parentContext == null) {
- parentContext = Context.current();
- }
- traceData.startNewOtelSpan(TraceData.OTEL_SERVER, SpanKind.SERVER, parentContext);
- traceData.setPendingParentContext(Context.root());
- traceData.openOtelScope();
- }
-
private TraceData initClientContext(TraceData traceData) {
savedTraceData.set(traceData);
traceData = createNewTraceData(traceData);
diff --git a/woody-api/src/main/java/dev/vality/woody/api/transport/TransportEventInterceptor.java b/woody-api/src/main/java/dev/vality/woody/api/transport/TransportEventInterceptor.java
index 997bb6ec..f734ba20 100644
--- a/woody-api/src/main/java/dev/vality/woody/api/transport/TransportEventInterceptor.java
+++ b/woody-api/src/main/java/dev/vality/woody/api/transport/TransportEventInterceptor.java
@@ -5,8 +5,6 @@
import dev.vality.woody.api.interceptor.CommonInterceptor;
import dev.vality.woody.api.trace.MetadataProperties;
import dev.vality.woody.api.trace.TraceData;
-import io.opentelemetry.api.trace.Span;
-import io.opentelemetry.api.trace.StatusCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,10 +30,6 @@ public boolean interceptRequest(TraceData traceData, Object providerContext, Obj
LOG.trace("Intercept request transportEvent");
traceData.getActiveSpan().getMetadata().putValue(MetadataProperties.EVENT_TYPE,
traceData.isClient() ? ClientEventType.CLIENT_SEND : ServiceEventType.SERVICE_RECEIVE);
- traceData.getOtelSpan()
- .setStatus(StatusCode.OK)
- .addEvent(traceData.isClient() ? ClientEventType.CLIENT_SEND.name() :
- ServiceEventType.SERVICE_RECEIVE.name());
reqListener.run();
return true;
}
@@ -45,10 +39,6 @@ public boolean interceptResponse(TraceData traceData, Object providerContext, Ob
LOG.trace("Intercept response transportEvent");
traceData.getActiveSpan().getMetadata().putValue(MetadataProperties.EVENT_TYPE,
traceData.isClient() ? ClientEventType.CLIENT_RECEIVE : ServiceEventType.SERVICE_RESULT);
- traceData.getOtelSpan()
- .setStatus(StatusCode.OK)
- .addEvent(traceData.isClient() ? ClientEventType.CLIENT_RECEIVE.name() :
- ServiceEventType.SERVICE_RESULT.name());
respListener.run();
return true;
}
@@ -56,28 +46,16 @@ public boolean interceptResponse(TraceData traceData, Object providerContext, Ob
@Override
public boolean interceptError(TraceData traceData, Throwable t, boolean isClient) {
LOG.trace("Intercept error transportEvent");
- Span span = traceData.getOtelSpan();
Object lastEvent = traceData.getActiveSpan().getMetadata().getValue(MetadataProperties.EVENT_TYPE);
if (isClient && !ClientEventType.CLIENT_RECEIVE.equals(lastEvent)) {
traceData.getActiveSpan().getMetadata().putValue(MetadataProperties.EVENT_TYPE,
ClientEventType.CLIENT_RECEIVE);
- if (span.getSpanContext().isValid()) {
- span.addEvent(ClientEventType.CLIENT_RECEIVE.name());
- }
respListener.run();
} else if (!isClient && !ServiceEventType.SERVICE_RESULT.equals(lastEvent)) {
traceData.getActiveSpan().getMetadata().putValue(MetadataProperties.EVENT_TYPE,
ServiceEventType.SERVICE_RESULT);
- if (span.getSpanContext().isValid()) {
- span.addEvent(ServiceEventType.SERVICE_RESULT.name());
- }
respListener.run();
}
- if (span.getSpanContext().isValid()) {
- span.recordException(t);
- span.setStatus(StatusCode.ERROR);
- span.addEvent("ERROR");
- }
errListener.run();
return (CommonInterceptor.super.interceptError(traceData, t, isClient));
}
diff --git a/woody-api/src/test/java/dev/vality/woody/api/MdcUtilsExtendedTest.java b/woody-api/src/test/java/dev/vality/woody/api/MdcUtilsExtendedTest.java
index dd1f5756..5c143d81 100644
--- a/woody-api/src/test/java/dev/vality/woody/api/MdcUtilsExtendedTest.java
+++ b/woody-api/src/test/java/dev/vality/woody/api/MdcUtilsExtendedTest.java
@@ -61,7 +61,6 @@ public void testExtendedFieldsPopulated() throws Exception {
assertEquals("client-request-1", MDC.get("rpc.client.metadata.user-identity.x-request-id"));
assertEquals("client-deadline-iso", MDC.get("rpc.client.metadata.user-identity.x-request-deadline"));
- traceData.getOtelSpan().end();
}
@Test
@@ -75,7 +74,6 @@ public void testDisableExtendedFields() throws Exception {
assertNull(MDC.get("rpc.client.service"));
assertNull(MDC.get("rpc.client.metadata.user-identity.x-request-id"));
- traceData.getOtelSpan().end();
}
private TraceData buildTraceData() throws Exception {
diff --git a/woody-api/src/test/java/dev/vality/woody/api/flow/concurrent/TestMDCInConcurent.java b/woody-api/src/test/java/dev/vality/woody/api/flow/concurrent/TestMDCInConcurent.java
index 39cdc328..25b74216 100644
--- a/woody-api/src/test/java/dev/vality/woody/api/flow/concurrent/TestMDCInConcurent.java
+++ b/woody-api/src/test/java/dev/vality/woody/api/flow/concurrent/TestMDCInConcurent.java
@@ -4,7 +4,6 @@
import dev.vality.woody.api.trace.Span;
import dev.vality.woody.api.trace.TraceData;
import dev.vality.woody.api.trace.context.TraceContext;
-import io.opentelemetry.api.trace.SpanContext;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -26,15 +25,10 @@ public class TestMDCInConcurent {
Runnable runnable = () -> {
try {
Span span = TraceContext.getCurrentTraceData().getActiveSpan().getSpan();
- io.opentelemetry.api.trace.Span otelSpan = TraceContext.getCurrentTraceData().getOtelSpan();
- SpanContext spanContext = otelSpan.getSpanContext();
- log.info("Runnable {} {} {} {} {}", span.getId(), span.getParentId(), span.getTraceId(),
- spanContext.getSpanId(), spanContext.getTraceId());
+ log.info("Runnable {} {} {}", span.getId(), span.getParentId(), span.getTraceId());
assertEquals(MDC.get(MDCUtils.SPAN_ID), span.getId());
assertEquals(MDC.get(MDCUtils.TRACE_ID), span.getTraceId());
assertEquals(MDC.get(MDCUtils.PARENT_ID), span.getParentId());
- assertEquals(MDC.get(MDCUtils.OTEL_SPAN_ID), spanContext.getSpanId());
- assertEquals(MDC.get(MDCUtils.OTEL_TRACE_ID), spanContext.getTraceId());
} catch (Throwable t) {
log.error("Error: ", t);
}
@@ -42,15 +36,10 @@ public class TestMDCInConcurent {
Callable callable = () -> {
try {
Span span = TraceContext.getCurrentTraceData().getActiveSpan().getSpan();
- io.opentelemetry.api.trace.Span otelSpan = TraceContext.getCurrentTraceData().getOtelSpan();
- SpanContext spanContext = otelSpan.getSpanContext();
- log.info("Callable {} {} {} {} {}", span.getId(), span.getParentId(), span.getTraceId(),
- spanContext.getSpanId(), spanContext.getTraceId());
+ log.info("Callable {} {} {}", span.getId(), span.getParentId(), span.getTraceId());
assertEquals(MDC.get(MDCUtils.SPAN_ID), span.getId());
assertEquals(MDC.get(MDCUtils.TRACE_ID), span.getTraceId());
assertEquals(MDC.get(MDCUtils.PARENT_ID), span.getParentId());
- assertEquals(MDC.get(MDCUtils.OTEL_TRACE_ID), spanContext.getTraceId());
- assertEquals(MDC.get(MDCUtils.OTEL_SPAN_ID), spanContext.getSpanId());
} catch (Throwable t) {
log.error("Error: ", t);
}
diff --git a/woody-api/src/test/java/dev/vality/woody/api/interceptor/ContextInterceptorTest.java b/woody-api/src/test/java/dev/vality/woody/api/interceptor/ContextInterceptorTest.java
index 8484ad60..02f108c1 100644
--- a/woody-api/src/test/java/dev/vality/woody/api/interceptor/ContextInterceptorTest.java
+++ b/woody-api/src/test/java/dev/vality/woody/api/interceptor/ContextInterceptorTest.java
@@ -26,9 +26,6 @@ public void setUp() {
@After
public void tearDown() {
MDC.clear();
- if (testTraceData != null) {
- testTraceData.getOtelSpan().end();
- }
TraceContext.setCurrentTraceData(originalTraceData);
}
diff --git a/woody-api/woody-api.md b/woody-api/woody-api.md
index 9f9e6cdf..569e6b93 100644
--- a/woody-api/woody-api.md
+++ b/woody-api/woody-api.md
@@ -1,12 +1,12 @@
# dev.vality.woody.api
Java API, предоставляющее основу для реализации сквозной трассировки событий в распределенной системе.
-Основан на thread-context подходе (информация о цепочке хранится в контексте, который привязан к потоку, в котором началось выполнение или обработка запроса) и синхронизирован с OpenTelemetry span’ами, что проверяется свежими интеграционными тестами в модуле `woody-thrift`.
+Основан на thread-context подходе (информация о цепочке хранится в контексте, который привязан к потоку, в котором началось выполнение или обработка запроса).
-## OpenTelemetry и MDC
+## MDC
-- `TraceData` содержит ссылку на активный OTEL-span; `MDCUtils` автоматически
- публикует `otel_trace_id`, `otel_span_id`, флаги трассировки и дедлайны.
+- `MDCUtils` автоматически публикует `trace_id`, `span_id`, `parent_id`,
+ дедлайны и расширенные RPC-поля.
- Расширенные MDC-поля (`rpc.client.*`, `rpc.server.*`, RPC-метаданные)
включены по умолчанию и могут быть отключены системным параметром
`-Dwoody.mdc.extended=false`.
@@ -15,7 +15,7 @@ Java API, предоставляющее основу для реализаци
- `WFlow.createServiceFork(...)` создаёт новый service-span с переданными
генераторами идентификаторов, очищая длительность/временные метки и
- синхронизируя OTEL-контекст.
+ синхронизируя контекст.
- Фабрики `WCallable`/`WRunnable` принимают заранее подготовленный `TraceData`,
что позволяет запускать задачи в пулах с сохранением или форком контекста.
@@ -70,4 +70,4 @@ WRunnable.createFork(yourForkedRunnable).run(); // All requests here're root req
```
Аналогично для `Callable`:
-`WCallable.createFork(yourForkedCallable).call();`.
\ No newline at end of file
+`WCallable.createFork(yourForkedCallable).call();`.
diff --git a/woody-thrift/pom.xml b/woody-thrift/pom.xml
index 28dd8f19..22d9ed51 100644
--- a/woody-thrift/pom.xml
+++ b/woody-thrift/pom.xml
@@ -7,7 +7,7 @@
woody
dev.vality.woody
- 2.1.0
+ 3.0.0
woody-thrift
@@ -94,10 +94,6 @@
httpclient5
5.5.1
-
- io.opentelemetry.semconv
- opentelemetry-semconv
-
org.easymock
easymock
diff --git a/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/THSpawnClientBuilder.java b/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/THSpawnClientBuilder.java
index 5639049a..07efc093 100644
--- a/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/THSpawnClientBuilder.java
+++ b/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/THSpawnClientBuilder.java
@@ -7,7 +7,6 @@
import dev.vality.woody.api.proxy.InvocationTargetProvider;
import dev.vality.woody.api.proxy.SpawnTargetProvider;
import dev.vality.woody.api.trace.context.metadata.MetadataExtensionKit;
-import io.opentelemetry.sdk.resources.Resource;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
diff --git a/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/TraceParentUtils.java b/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/TraceParentUtils.java
deleted file mode 100644
index 97ca6a20..00000000
--- a/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/TraceParentUtils.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package dev.vality.woody.thrift.impl.http;
-
-public class TraceParentUtils {
-
- public static String DEFAULT_VERSION = "00";
-
- public static String initParentTrace(String version, String trace, String span, String flag) {
- return version + "-" + trace + "-" + span + "-" + flag;
- }
-
- public static String parseVersion(String parentTraceId) {
- return parentTraceId.split("-").length > 0 ? parentTraceId.split("-")[0] : "";
- }
-
- public static String parseTraceId(String parentTraceId) {
- return parentTraceId.split("-").length > 1 ? parentTraceId.split("-")[1] : "";
- }
-
- public static String parseSpanId(String parentTraceId) {
- return parentTraceId.split("-").length > 2 ? parentTraceId.split("-")[2] : "";
- }
-
- public static String parseFlag(String parentTraceId) {
- return parentTraceId.split("-").length > 3 ? parentTraceId.split("-")[3] : "";
- }
-
-}
diff --git a/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/interceptor/ext/TransportExtensionBundles.java b/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/interceptor/ext/TransportExtensionBundles.java
index dedf74e4..ffd69c1d 100644
--- a/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/interceptor/ext/TransportExtensionBundles.java
+++ b/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/interceptor/ext/TransportExtensionBundles.java
@@ -12,13 +12,6 @@
import dev.vality.woody.thrift.impl.http.transport.THttpHeader;
import dev.vality.woody.thrift.impl.http.transport.TTransportErrorType;
import dev.vality.woody.thrift.impl.http.transport.UrlStringEndpoint;
-import io.opentelemetry.api.GlobalOpenTelemetry;
-import io.opentelemetry.api.trace.StatusCode;
-import io.opentelemetry.context.Context;
-import io.opentelemetry.context.propagation.TextMapGetter;
-import io.opentelemetry.context.propagation.TextMapPropagator;
-import io.opentelemetry.context.propagation.TextMapSetter;
-import io.opentelemetry.semconv.HttpAttributes;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
@@ -141,11 +134,8 @@ private static String resolveClientEndpoint(THCExtensionContext reqCCtx) {
reqCCtx.setRequestHeader(THttpHeader.TRACE_ID.getKey(), span.getTraceId());
reqCCtx.setRequestHeader(THttpHeader.SPAN_ID.getKey(), span.getId());
reqCCtx.setRequestHeader(THttpHeader.PARENT_ID.getKey(), span.getParentId());
- injectTraceHeaders(reqCCtx);
}, (InterceptorExtension) respCCtx -> {
- applyResponseStatus(respCCtx.getTraceData(), respCCtx.getResponseStatus());
}), createCtxBundle((InterceptorExtension) reqSCtx -> {
- extractTraceContext(reqSCtx);
HttpServletRequest request = reqSCtx.getProviderRequest();
Span span = reqSCtx.getTraceData().getServiceSpan().getSpan();
List>> headerConsumers =
@@ -160,8 +150,6 @@ private static String resolveClientEndpoint(THCExtensionContext reqCCtx) {
respSCtx.setResponseHeader(THttpHeader.TRACE_ID.getKey(), span.getTraceId());
respSCtx.setResponseHeader(THttpHeader.PARENT_ID.getKey(), span.getParentId());
respSCtx.setResponseHeader(THttpHeader.SPAN_ID.getKey(), span.getId());
- injectTraceHeaders(respSCtx);
- applyResponseStatus(respSCtx.getTraceData(), respSCtx.getProviderResponse().getStatus());
}));
public static final ExtensionBundle TRANSPORT_STATE_MAPPING_BUNDLE = createExtBundle(createCtxBundle(
@@ -207,7 +195,6 @@ private static String resolveClientEndpoint(THCExtensionContext reqCCtx) {
response.setHeader(THttpHeader.ERROR_REASON.getKey(), val);
});
serviceSpan.getMetadata().putValue(THMetadataProperties.TH_TRANSPORT_RESPONSE_SET_FLAG, true);
- applyResponseStatus(respSCtx.getTraceData(), responseInfo.getStatus());
}
}));
@@ -219,31 +206,6 @@ private static String resolveClientEndpoint(THCExtensionContext reqCCtx) {
Arrays.asList(TRANSPORT_CONFIG_BUNDLE, RPC_ID_BUNDLE, CALL_ENDPOINT_BUNDLE, TRANSPORT_STATE_MAPPING_BUNDLE,
TRANSPORT_INJECTION_BUNDLE, DEADLINE_BUNDLE));
- private static final TextMapGetter REQUEST_HEADER_GETTER = new TextMapGetter<>() {
- @Override
- public Iterable keys(HttpServletRequest carrier) {
- if (carrier == null) {
- return Collections.emptyList();
- }
- Enumeration headerNames = carrier.getHeaderNames();
- return headerNames == null ? Collections.emptyList() : Collections.list(headerNames);
- }
-
- @Override
- public String get(HttpServletRequest carrier, String key) {
- if (carrier == null || key == null) {
- return null;
- }
- return carrier.getHeader(key);
- }
- };
-
- private static final TextMapSetter CLIENT_REQUEST_SETTER = (carrier, key, value) -> {
- if (carrier != null && key != null && value != null) {
- carrier.setRequestHeader(key, value);
- }
- };
-
public static List getClientExtensions() {
return clientList;
}
@@ -256,50 +218,6 @@ public static List getExtensions(boolean isClient) {
return isClient ? getClientExtensions() : getServiceExtensions();
}
- private static TextMapPropagator propagator() {
- return GlobalOpenTelemetry.get().getPropagators().getTextMapPropagator();
- }
-
- private static void extractTraceContext(THSExtensionContext context) {
- HttpServletRequest request = context.getProviderRequest();
- Context extracted = propagator().extract(Context.root(), request, REQUEST_HEADER_GETTER);
- if (io.opentelemetry.api.trace.Span.fromContext(extracted).getSpanContext().isValid()) {
- context.getTraceData().setInboundTraceParent(request.getHeader(THttpHeader.TRACE_PARENT.getKey()));
- context.getTraceData().setInboundTraceState(request.getHeader(THttpHeader.TRACE_STATE.getKey()));
- } else {
- context.getTraceData().setInboundTraceParent(null);
- context.getTraceData().setInboundTraceState(null);
- }
- context.getTraceData().setPendingParentContext(extracted);
- }
-
- private static void injectTraceHeaders(THCExtensionContext context) {
- propagator().inject(context.getTraceData().getOtelContext(), context, CLIENT_REQUEST_SETTER);
- }
-
- private static void injectTraceHeaders(THSExtensionContext context) {
- String traceParent = context.getTraceData().getInboundTraceParent();
- if (traceParent != null && !traceParent.isEmpty()) {
- context.setResponseHeader(THttpHeader.TRACE_PARENT.getKey(), traceParent);
- String traceState = context.getTraceData().getInboundTraceState();
- if (traceState != null && !traceState.isEmpty()) {
- context.setResponseHeader(THttpHeader.TRACE_STATE.getKey(), traceState);
- }
- }
- }
-
- private static void applyResponseStatus(TraceData traceData, int status) {
- if (status <= 0) {
- return;
- }
- io.opentelemetry.api.trace.Span span = traceData.getOtelSpan();
- if (span == null || !span.getSpanContext().isValid()) {
- return;
- }
- span.setAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, status);
- span.setStatus(status >= 500 ? StatusCode.ERROR : StatusCode.OK);
- }
-
private static void logIfError(ContextSpan contextSpan) {
Throwable t = ContextUtils.getCallError(contextSpan);
if (t != null) {
diff --git a/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/transport/THttpHeader.java b/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/transport/THttpHeader.java
index a3e378fd..e62dc1d3 100644
--- a/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/transport/THttpHeader.java
+++ b/woody-thrift/src/main/java/dev/vality/woody/thrift/impl/http/transport/THttpHeader.java
@@ -3,8 +3,6 @@
public enum THttpHeader {
TRACE_ID("woody.trace-id", false),
SPAN_ID("woody.span-id", false),
- TRACE_PARENT("traceparent", true),
- TRACE_STATE("tracestate", true),
PARENT_ID("woody.parent-id", false),
DEADLINE("woody.deadline", false),
ERROR_CLASS("woody.error-class", false),
diff --git a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/AbstractTest.java b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/AbstractTest.java
index d24dd893..62e6f38f 100644
--- a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/AbstractTest.java
+++ b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/AbstractTest.java
@@ -5,11 +5,6 @@
import dev.vality.woody.api.generator.IdGenerator;
import dev.vality.woody.api.trace.context.metadata.MetadataExtensionKit;
import dev.vality.woody.rpc.OwnerServiceSrv;
-import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
-import io.opentelemetry.context.propagation.ContextPropagators;
-import io.opentelemetry.sdk.OpenTelemetrySdk;
-import io.opentelemetry.sdk.trace.SdkTracerProvider;
-import io.opentelemetry.sdk.trace.samplers.Sampler;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
@@ -45,13 +40,6 @@ public class AbstractTest {
protected TProcessor tProcessor;
private HandlerCollection handlerCollection;
- static {
- OpenTelemetrySdk.builder()
- .setTracerProvider(SdkTracerProvider.builder().setSampler(Sampler.alwaysOn()).build())
- .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
- .buildAndRegisterGlobal();
- }
-
@Before
public void startJetty() throws Exception {
diff --git a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/MDCLogTest.java b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/MDCLogTest.java
index feab367e..00955492 100644
--- a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/MDCLogTest.java
+++ b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/MDCLogTest.java
@@ -12,7 +12,6 @@
import dev.vality.woody.api.generator.TimestampIdGenerator;
import dev.vality.woody.thrift.impl.http.event.THClientEvent;
import dev.vality.woody.thrift.impl.http.event.THServiceEvent;
-import io.opentelemetry.api.trace.SpanContext;
import org.apache.thrift.TException;
import org.junit.Assert;
import org.junit.Before;
@@ -37,34 +36,20 @@ public class MDCLogTest extends AbstractTest {
assertNotNull(MDC.get(MDCUtils.SPAN_ID));
assertNotNull(MDC.get(MDCUtils.TRACE_ID));
assertNotNull(MDC.get(MDCUtils.PARENT_ID));
- assertNotNull(MDC.get(MDCUtils.OTEL_SPAN_ID));
- assertNotNull(MDC.get(MDCUtils.OTEL_TRACE_ID));
- assertNotNull(MDC.get(MDCUtils.OTEL_TRACE_FLAGS));
assertEquals(MDC.get(MDCUtils.SPAN_ID), event.getSpanId());
assertEquals(MDC.get(MDCUtils.TRACE_ID), event.getTraceId());
assertEquals(MDC.get(MDCUtils.PARENT_ID), event.getParentId());
- SpanContext spanContext = event.getTraceData().getOtelSpan().getSpanContext();
- assertEquals(MDC.get(MDCUtils.OTEL_SPAN_ID), spanContext.getSpanId());
- assertEquals(MDC.get(MDCUtils.OTEL_TRACE_ID), spanContext.getTraceId());
- assertEquals(MDC.get(MDCUtils.OTEL_TRACE_FLAGS), spanContext.getTraceFlags().asHex());
};
ServiceEventListener serviceEventListener = (ServiceEventListener) event -> {
assertNotNull(MDC.get(MDCUtils.SPAN_ID));
assertNotNull(MDC.get(MDCUtils.TRACE_ID));
assertNotNull(MDC.get(MDCUtils.PARENT_ID));
- assertNotNull(MDC.get(MDCUtils.OTEL_SPAN_ID));
- assertNotNull(MDC.get(MDCUtils.OTEL_TRACE_FLAGS));
- assertNotNull(MDC.get(MDCUtils.OTEL_TRACE_ID));
assertEquals(MDC.get(MDCUtils.SPAN_ID), event.getSpanId());
assertEquals(MDC.get(MDCUtils.TRACE_ID), event.getTraceId());
assertEquals(MDC.get(MDCUtils.PARENT_ID), event.getParentId());
- SpanContext spanContext = event.getTraceData().getOtelSpan().getSpanContext();
- assertEquals(MDC.get(MDCUtils.OTEL_SPAN_ID), spanContext.getSpanId());
- assertEquals(MDC.get(MDCUtils.OTEL_TRACE_ID), spanContext.getTraceId());
- assertEquals(MDC.get(MDCUtils.OTEL_TRACE_FLAGS), spanContext.getTraceFlags().asHex());
};
OwnerServiceSrv.Iface client1 = createThriftRPCClient(OwnerServiceSrv.Iface.class, new TimestampIdGenerator(),
diff --git a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/MetadataMdcPropagationTest.java b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/MetadataMdcPropagationTest.java
index e83b05d1..949b3d34 100644
--- a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/MetadataMdcPropagationTest.java
+++ b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/MetadataMdcPropagationTest.java
@@ -27,7 +27,9 @@
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
public class MetadataMdcPropagationTest extends AbstractTest {
@@ -35,7 +37,6 @@ public class MetadataMdcPropagationTest extends AbstractTest {
private static final String X_REQUEST_DEADLINE = "2025-01-01T12:30:00Z";
private static final String TRACE_ID = "4e0e9f8d8d8044f9b65a3b0f5cdfc2d1";
private static final String SPAN_ID = "1a2b3c4d5e6f7081";
- private static final String TRACE_STATE = "rojo=00f067aa0ba902b7,congo=t61rcWkgMzE";
private final AtomicReference upstreamMetadataId = new AtomicReference<>();
private final AtomicReference upstreamMetadataDeadline = new AtomicReference<>();
@@ -48,14 +49,6 @@ public class MetadataMdcPropagationTest extends AbstractTest {
private final AtomicReference downstreamRpcServerService = new AtomicReference<>();
private final AtomicReference downstreamRpcServerFunction = new AtomicReference<>();
private final AtomicReference downstreamRpcServerUrl = new AtomicReference<>();
- private final AtomicReference upstreamOtelTraceId = new AtomicReference<>();
- private final AtomicReference downstreamOtelTraceId = new AtomicReference<>();
- private final AtomicReference upstreamTraceState = new AtomicReference<>();
- private final AtomicReference downstreamTraceState = new AtomicReference<>();
- private final AtomicReference upstreamTraceParent = new AtomicReference<>();
- private final AtomicReference downstreamTraceParent = new AtomicReference<>();
- private final AtomicReference responseTraceParent = new AtomicReference<>();
- private final AtomicReference responseTraceState = new AtomicReference<>();
private final AtomicReference upstreamRpcServerService = new AtomicReference<>();
private final AtomicReference upstreamRpcServerFunction = new AtomicReference<>();
private final AtomicReference upstreamRpcServerUrl = new AtomicReference<>();
@@ -90,10 +83,6 @@ public Owner getOwner(int id) throws TException {
"user-identity.x-request-deadline"));
downstreamMdcId.set(MDC.get("rpc.server.metadata.user-identity.x-request-id"));
downstreamMdcDeadline.set(MDC.get("rpc.server.metadata.user-identity.x-request-deadline"));
- downstreamOtelTraceId.set(
- TraceContext.getCurrentTraceData().getOtelSpan().getSpanContext().getTraceId());
- downstreamTraceState.set(TraceContext.getCurrentTraceData().getInboundTraceState());
- downstreamTraceParent.set(TraceContext.getCurrentTraceData().getInboundTraceParent());
downstreamRpcServerService.set(MDC.get("rpc.server.service"));
downstreamRpcServerFunction.set(MDC.get("rpc.server.function"));
downstreamRpcServerUrl.set(MDC.get("rpc.server.url"));
@@ -112,10 +101,6 @@ public Owner getOwner(int id) throws TException {
"user-identity.x-request-deadline"));
upstreamMdcId.set(MDC.get("rpc.server.metadata.user-identity.x-request-id"));
upstreamMdcDeadline.set(MDC.get("rpc.server.metadata.user-identity.x-request-deadline"));
- upstreamOtelTraceId.set(
- TraceContext.getCurrentTraceData().getOtelSpan().getSpanContext().getTraceId());
- upstreamTraceState.set(TraceContext.getCurrentTraceData().getInboundTraceState());
- upstreamTraceParent.set(TraceContext.getCurrentTraceData().getInboundTraceParent());
upstreamRpcServerService.set(MDC.get("rpc.server.service"));
upstreamRpcServerFunction.set(MDC.get("rpc.server.function"));
upstreamRpcServerUrl.set(MDC.get("rpc.server.url"));
@@ -160,7 +145,6 @@ public void shouldPropagateMetadataHeadersAndPopulateMdc() throws Exception {
try (CloseableHttpClient httpClient = HttpClients.custom()
.addRequestInterceptorLast(this::injectHeaders)
- .addResponseInterceptorLast(this::captureResponseHeaders)
.build()) {
OwnerServiceSrv.Iface entryClient = createThriftRPCClient(OwnerServiceSrv.Iface.class,
new TimestampIdGenerator(), null, null, getUrlString("/upstream"), networkTimeout, httpClient);
@@ -181,25 +165,6 @@ public void shouldPropagateMetadataHeadersAndPopulateMdc() throws Exception {
assertEquals("getOwner", downstreamRpcServerFunction.get());
assertTrue("Server URL should contain downstream path",
downstreamRpcServerUrl.get() != null && downstreamRpcServerUrl.get().contains("/downstream"));
- String upstreamTraceId = upstreamOtelTraceId.get();
- String downstreamTraceId = downstreamOtelTraceId.get();
- assertNotNull(upstreamTraceId);
- assertNotNull(downstreamTraceId);
- assertEquals(upstreamTraceId, downstreamTraceId);
- assertEquals(32, upstreamTraceId.length());
- assertNotEquals("00000000000000000000000000000000", upstreamTraceId);
- assertEquals(TRACE_STATE, upstreamTraceState.get());
- assertEquals(TRACE_STATE, downstreamTraceState.get());
- assertNotNull("Upstream traceparent must be captured", upstreamTraceParent.get());
- assertNotNull("Downstream traceparent must be captured", downstreamTraceParent.get());
- assertNotNull("traceparent in HTTP response must be present", responseTraceParent.get());
- assertTrue("Upstream traceparent should contain the original trace ID",
- upstreamTraceParent.get().contains(TRACE_ID));
- assertTrue("Downstream traceparent should contain the original trace ID",
- downstreamTraceParent.get().contains(TRACE_ID));
- assertTrue("Response traceparent should contain the original trace ID",
- responseTraceParent.get().contains(TRACE_ID));
- assertEquals(TRACE_STATE, responseTraceState.get());
assertEquals("OwnerService", upstreamRpcServerService.get());
assertEquals("getOwner", upstreamRpcServerFunction.get());
assertTrue("Server URL should contain upstream path",
@@ -223,27 +188,6 @@ private void injectHeaders(HttpRequest request, EntityDetails entity, HttpContex
request.setHeader("woody.trace-id", TRACE_ID);
request.setHeader("woody.span-id", SPAN_ID);
request.setHeader("woody.parent-id", TraceContext.NO_PARENT_ID);
- request.setHeader("traceparent", String.format("00-%s-%s-01", TRACE_ID, SPAN_ID));
- request.setHeader("tracestate", TRACE_STATE);
- }
-
- private void captureResponseHeaders(org.apache.hc.core5.http.HttpResponse response,
- EntityDetails entityDetails,
- HttpContext context) throws HttpException, IOException {
- if (entityDetails != null) {
- entityDetails.getContentType();
- }
- if (context != null) {
- context.hashCode();
- }
- var traceParentHeader = response.getFirstHeader("traceparent");
- if (traceParentHeader != null) {
- responseTraceParent.set(traceParentHeader.getValue());
- }
- var traceStateHeader = response.getFirstHeader("tracestate");
- if (traceStateHeader != null) {
- responseTraceState.set(traceStateHeader.getValue());
- }
}
private void clearCapturedValues() {
@@ -258,14 +202,6 @@ private void clearCapturedValues() {
downstreamRpcServerService.set(null);
downstreamRpcServerFunction.set(null);
downstreamRpcServerUrl.set(null);
- upstreamOtelTraceId.set(null);
- downstreamOtelTraceId.set(null);
- upstreamTraceState.set(null);
- downstreamTraceState.set(null);
- upstreamTraceParent.set(null);
- downstreamTraceParent.set(null);
- responseTraceParent.set(null);
- responseTraceState.set(null);
upstreamRpcServerService.set(null);
upstreamRpcServerFunction.set(null);
upstreamRpcServerUrl.set(null);
diff --git a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/TestClientAndServerHttpHeaders.java b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/TestClientAndServerHttpHeaders.java
index 12bf5ee0..afede99d 100644
--- a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/TestClientAndServerHttpHeaders.java
+++ b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/TestClientAndServerHttpHeaders.java
@@ -183,67 +183,4 @@ public void testWhenTraceDataIsEmpty() throws TException {
}
}
- @Test
- public void testTraceDataOtel() throws TException {
- addServlet(testServlet, servletContextPath);
- CloseableHttpClient httpClient =
- HttpClients.custom().addRequestInterceptorLast((httpRequest, entityDetails, httpContext) ->
- httpRequest.setHeader(
- THttpHeader.TRACE_PARENT.getKey(),
- "00-80e1afed08e019fc1110464cfa66635c-7a085853722dc6d2-01"
- )
- )
- .addResponseInterceptorLast((httpResponse, entityDetails, httpContext) ->
- assertEquals(
- "00-80e1afed08e019fc1110464cfa66635c-7a085853722dc6d2-01",
- httpResponse.getHeader(THttpHeader.TRACE_PARENT.getKey()).getValue()
- )
- )
- .build();
-
- OwnerServiceSrv.Iface client = createThriftRPCClient(
- OwnerServiceSrv.Iface.class, getUrlString(servletContextPath), httpClient
- );
- client.getIntValue();
- }
-
- @Test
- public void testWhenTraceDataOtelIsEmpty() throws TException {
- addServlet(testServlet, servletContextPath);
- CloseableHttpClient httpClient =
- HttpClients.custom().addRequestInterceptorLast((httpRequest, entityDetails, httpContext) ->
- assertNotNull(httpRequest.getHeader(THttpHeader.TRACE_PARENT.getKey()))
- )
- .addResponseInterceptorLast((httpResponse, entityDetails, httpContext) ->
- assertNotNull(httpResponse.getHeader(THttpHeader.TRACE_PARENT.getKey()))
- )
- .build();
-
- OwnerServiceSrv.Iface client = createThriftRPCClient(
- OwnerServiceSrv.Iface.class, getUrlString(servletContextPath), httpClient
- );
- client.getIntValue();
- }
-
- @Test
- public void testWhenTraceDataOtelIsInvalid() throws TException {
- addServlet(testServlet, servletContextPath);
- CloseableHttpClient httpClient =
- HttpClients.custom().addRequestInterceptorLast((httpRequest, entityDetails, httpContext) ->
- httpRequest.setHeader(
- THttpHeader.TRACE_PARENT.getKey(),
- "invalid"
- )
- )
- .addResponseInterceptorLast((httpResponse, entityDetails, httpContext) ->
- assertNull(httpResponse.getHeader(THttpHeader.TRACE_PARENT.getKey()))
- )
- .build();
-
- OwnerServiceSrv.Iface client = createThriftRPCClient(
- OwnerServiceSrv.Iface.class, getUrlString(servletContextPath), httpClient
- );
- client.getIntValue();
- }
-
}
diff --git a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/TraceLifecycleIntegrationTest.java b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/TraceLifecycleIntegrationTest.java
deleted file mode 100644
index 8f215bcb..00000000
--- a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/TraceLifecycleIntegrationTest.java
+++ /dev/null
@@ -1,607 +0,0 @@
-package dev.vality.woody.thrift.impl.http;
-
-import dev.vality.woody.api.generator.TimestampIdGenerator;
-import dev.vality.woody.api.trace.ContextSpan;
-import dev.vality.woody.api.trace.ContextUtils;
-import dev.vality.woody.api.trace.TraceData;
-import dev.vality.woody.api.trace.context.TraceContext;
-import dev.vality.woody.rpc.Owner;
-import dev.vality.woody.rpc.OwnerServiceSrv;
-import io.opentelemetry.api.GlobalOpenTelemetry;
-import io.opentelemetry.api.trace.SpanContext;
-import io.opentelemetry.api.trace.SpanId;
-import io.opentelemetry.api.trace.SpanKind;
-import io.opentelemetry.api.trace.StatusCode;
-import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
-import io.opentelemetry.context.propagation.ContextPropagators;
-import io.opentelemetry.sdk.OpenTelemetrySdk;
-import io.opentelemetry.sdk.common.CompletableResultCode;
-import io.opentelemetry.sdk.trace.SdkTracerProvider;
-import io.opentelemetry.sdk.trace.data.SpanData;
-import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
-import io.opentelemetry.sdk.trace.export.SpanExporter;
-import jakarta.servlet.Servlet;
-import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
-import org.apache.hc.client5.http.impl.classic.HttpClients;
-import org.apache.hc.core5.http.EntityDetails;
-import org.apache.hc.core5.http.HttpException;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.HttpResponse;
-import org.apache.hc.core5.http.protocol.HttpContext;
-import org.apache.thrift.TException;
-import org.eclipse.jetty.server.handler.HandlerCollection;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.slf4j.MDC;
-
-import java.io.IOException;
-import java.time.Instant;
-import java.util.Collection;
-import java.util.List;
-import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
-
-import static org.junit.Assert.*;
-
-public class TraceLifecycleIntegrationTest extends AbstractTest {
-
- private static final String REQUEST_ID_KEY = "user-identity.x-request-id";
- private static final String DEADLINE_KEY = "user-identity.x-request-deadline";
- private static final String TRACE_PARENT_HEADER = "traceparent";
- private static final String TRACE_STATE_HEADER = "tracestate";
- private static final RecordingSpanExporter SPAN_EXPORTER = new RecordingSpanExporter();
- private static SdkTracerProvider sdkTracerProvider;
-
- private final AtomicReference scenario = new AtomicReference<>();
- private final AtomicReference upstreamInitial = new AtomicReference<>();
- private final AtomicReference upstreamAfterCall = new AtomicReference<>();
- private final AtomicReference downstreamSnapshot = new AtomicReference<>();
- private final AtomicReference responseTraceParent = new AtomicReference<>();
- private final AtomicReference responseTraceState = new AtomicReference<>();
-
- private OwnerServiceSrv.Iface downstreamClient;
-
- @BeforeClass
- public static void configureOpenTelemetry() {
- GlobalOpenTelemetry.resetForTest();
- SPAN_EXPORTER.reset();
- sdkTracerProvider = SdkTracerProvider.builder()
- .addSpanProcessor(SimpleSpanProcessor.create(SPAN_EXPORTER))
- .build();
- OpenTelemetrySdk.builder()
- .setTracerProvider(sdkTracerProvider)
- .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
- .buildAndRegisterGlobal();
- }
-
- @Before
- public void setUpServices() throws Exception {
- scenario.set(ScenarioSettings.fresh("noop"));
- SPAN_EXPORTER.reset();
- upstreamInitial.set(null);
- upstreamAfterCall.set(null);
- downstreamSnapshot.set(null);
- responseTraceParent.set(null);
- responseTraceState.set(null);
-
- OwnerServiceSrv.Iface downstreamHandler = new OwnerServiceStub() {
- @Override
- public Owner getOwner(int id) throws TException {
- InvocationSnapshot snapshot = InvocationSnapshot.capture();
- downstreamSnapshot.set(snapshot);
- ScenarioSettings settings = scenario.get();
- assertEquals(settings.expectedRequestId(), snapshot.serviceMetadataRequestId);
- assertEquals(settings.expectedDeadline(), snapshot.serviceMetadataDeadline);
- if (settings.expectTraceHeaders()) {
- assertNotNull(snapshot.inboundTraceParent);
- assertTrue(snapshot.inboundTraceParent.contains(settings.inboundTraceId));
- assertEquals(settings.traceState, snapshot.inboundTraceState);
- }
- if (settings.downstreamThrows) {
- throw settings.downstreamException;
- }
- return new Owner(id, "downstream" + id);
- }
- };
-
- Servlet downstreamServlet = createThriftRPCService(OwnerServiceSrv.Iface.class, downstreamHandler);
-
- OwnerServiceSrv.Iface upstreamHandler = new OwnerServiceStub() {
- @Override
- public Owner getOwner(int id) throws TException {
- ScenarioSettings settings = scenario.get();
- upstreamInitial.set(InvocationSnapshot.capture());
- if (settings.expectTraceHeaders()) {
- InvocationSnapshot initial = upstreamInitial.get();
- assertNotNull(initial);
- assertEquals(settings.inboundTraceId, initial.serviceTraceId);
- assertEquals(TraceContext.NO_PARENT_ID, initial.serviceParentId);
- assertEquals(settings.traceState, initial.inboundTraceState);
- assertEquals(settings.inboundTraceParent(), initial.inboundTraceParent);
- assertEquals(settings.inboundRequestId, initial.serviceMetadataRequestId);
- assertEquals(settings.inboundDeadline, initial.serviceMetadataDeadline);
- assertEquals(settings.inboundRequestId,
- initial.mdcServerMetadataId);
- assertEquals(settings.inboundDeadline,
- initial.mdcServerMetadataDeadline);
- }
-
- if (settings.propagateLocalMetadata) {
- ContextUtils.setCustomMetadataValue(REQUEST_ID_KEY, settings.localRequestId);
- ContextUtils.setCustomMetadataValue(DEADLINE_KEY, settings.localDeadline);
- Instant deadline = settings.localDeadline != null ? Instant.parse(settings.localDeadline) : null;
- ContextUtils.setDeadline(deadline);
- ContextUtils.setDeadline(TraceContext.getCurrentTraceData().getServiceSpan(), deadline);
- }
-
- try {
- Owner owner = downstreamClient.getOwner(id);
- upstreamAfterCall.set(InvocationSnapshot.capture());
- return owner;
- } catch (RuntimeException ex) {
- upstreamAfterCall.set(InvocationSnapshot.capture());
- throw ex;
- }
- }
- };
-
- Servlet upstreamServlet = createThriftRPCService(OwnerServiceSrv.Iface.class, upstreamHandler);
-
- ServletContextHandler context = new ServletContextHandler();
- context.setContextPath("/");
- context.addServlet(new ServletHolder("downstream", downstreamServlet), "/downstream");
- context.addServlet(new ServletHolder("upstream", upstreamServlet), "/upstream");
- HandlerCollection collection = (HandlerCollection) server.getHandler();
- collection.addHandler(context);
- context.start();
-
- downstreamClient = createThriftRPCClient(OwnerServiceSrv.Iface.class, new TimestampIdGenerator(), null,
- getUrlString("/downstream"));
- }
-
- @Test
- public void shouldStartFreshTraceAndPropagateMetadata() throws Exception {
- ScenarioSettings settings = ScenarioSettings.fresh("fresh-trace");
- scenario.set(settings);
-
- try (CloseableHttpClient httpClient = HttpClients.custom()
- .addResponseInterceptorLast(this::captureResponseHeaders)
- .build()) {
- OwnerServiceSrv.Iface client = createThriftRPCClient(OwnerServiceSrv.Iface.class,
- new TimestampIdGenerator(), null, null, getUrlString("/upstream"), networkTimeout, httpClient);
-
- Owner owner = client.getOwner(42);
- assertEquals(new Owner(42, "downstream42"), owner);
- }
-
- InvocationSnapshot upstream = upstreamInitial.get();
- InvocationSnapshot after = upstreamAfterCall.get();
- InvocationSnapshot downstream = downstreamSnapshot.get();
-
- assertNotNull(upstream);
- assertNotNull(after);
- assertNotNull(downstream);
-
- assertEquals(TraceContext.NO_PARENT_ID, upstream.serviceParentId);
- assertEquals(upstream.serviceTraceId, downstream.serviceTraceId);
- assertEquals(settings.localRequestId, downstream.serviceMetadataRequestId);
- assertEquals(settings.localDeadline, downstream.serviceMetadataDeadline);
- assertEquals(settings.localRequestId, downstream.mdcServerMetadataId);
- assertEquals(settings.localDeadline, downstream.mdcServerMetadataDeadline);
- assertEquals(settings.localRequestId, after.mdcServerMetadataId);
- assertEquals(settings.localDeadline, after.mdcServerMetadataDeadline);
- assertFalse(upstream.clientSpanFilled);
-
- assertNotNull(upstream.otelTraceId);
- assertEquals(32, upstream.otelTraceId.length());
- assertNotEquals("00000000000000000000000000000000", upstream.otelTraceId);
- assertEquals(upstream.otelTraceId, downstream.otelTraceId);
- assertEquals(upstream.otelTraceId, after.otelTraceId);
- assertFalse(after.clientSpanFilled);
- assertNull(responseTraceState.get());
- assertNotNull(responseTraceParent.get());
- assertTrue(responseTraceParent.get().contains(upstream.otelTraceId));
-
- SpanStructure spans = SpanStructure.from(finishedSpans());
- spans.assertServerTraceConsistency();
- spans.assertHasRootServer();
- spans.assertHasServerHierarchy();
- spans.assertServerStatus(StatusCode.UNSET, StatusCode.OK);
- spans.assertClientStatus(StatusCode.UNSET, StatusCode.OK);
- }
-
- @Test
- public void shouldRestoreIncomingTraceHeadersAndEchoResponse() throws Exception {
- ScenarioSettings settings = ScenarioSettings.restored(
- "c9a6462b3f4e40c4baf3972f9b9b9d10",
- "3d2a1f0e5c7b4821",
- "vendor=ot",
- "req-restored",
- "2026-06-01T10:15:30Z");
- scenario.set(settings);
-
- try (CloseableHttpClient httpClient = HttpClients.custom()
- .addRequestInterceptorLast((request, entity, ctx) -> injectInboundHeaders(request, settings))
- .addResponseInterceptorLast(this::captureResponseHeaders)
- .build()) {
- OwnerServiceSrv.Iface client = createThriftRPCClient(OwnerServiceSrv.Iface.class,
- new TimestampIdGenerator(), null, null, getUrlString("/upstream"), networkTimeout, httpClient);
-
- Owner owner = client.getOwner(7);
- assertEquals(new Owner(7, "downstream7"), owner);
- }
-
- InvocationSnapshot upstream = upstreamInitial.get();
-
- assertNotNull(upstream);
- assertEquals(settings.inboundTraceId, upstream.serviceTraceId);
- assertEquals(TraceContext.NO_PARENT_ID, upstream.serviceParentId);
- assertEquals(settings.inboundRequestId, upstream.serviceMetadataRequestId);
- assertEquals(settings.inboundDeadline, upstream.serviceMetadataDeadline);
- assertEquals(settings.inboundRequestId, upstream.mdcServerMetadataId);
- assertEquals(settings.inboundDeadline, upstream.mdcServerMetadataDeadline);
-
- InvocationSnapshot downstream = downstreamSnapshot.get();
- assertNotNull(downstream);
- assertEquals(settings.inboundTraceId, downstream.serviceTraceId);
- assertEquals(settings.expectedRequestId(), downstream.serviceMetadataRequestId);
- assertEquals(settings.expectedDeadline(), downstream.serviceMetadataDeadline);
- assertEquals(settings.traceState, downstream.inboundTraceState);
- assertEquals(settings.expectedRequestId(), downstream.mdcServerMetadataId);
- assertEquals(settings.expectedDeadline(), downstream.mdcServerMetadataDeadline);
- InvocationSnapshot after = upstreamAfterCall.get();
- assertEquals(settings.expectedRequestId(), after.mdcServerMetadataId);
- assertEquals(settings.expectedDeadline(), after.mdcServerMetadataDeadline);
-
- assertNotNull(responseTraceParent.get());
- assertEquals(settings.inboundTraceParent(), responseTraceParent.get());
- assertEquals(settings.traceState, responseTraceState.get());
-
- SpanStructure spans = SpanStructure.from(finishedSpans());
- spans.assertServerTraceConsistency();
- spans.assertHasRootServer();
- spans.assertHasServerHierarchy();
- spans.assertServerStatus(StatusCode.UNSET, StatusCode.OK);
- spans.assertClientStatus(StatusCode.UNSET, StatusCode.OK);
- assertFalse(after.clientSpanFilled);
- }
-
- @Test
- public void shouldMarkErrorSpanWhenDownstreamThrows() throws Exception {
- ScenarioSettings settings = ScenarioSettings.error("downstream failure");
- scenario.set(settings);
-
- try (CloseableHttpClient httpClient = HttpClients.custom()
- .addResponseInterceptorLast(this::captureResponseHeaders)
- .build()) {
- OwnerServiceSrv.Iface client = createThriftRPCClient(OwnerServiceSrv.Iface.class,
- new TimestampIdGenerator(), null, null, getUrlString("/upstream"), networkTimeout, httpClient);
-
- try {
- client.getOwner(5);
- fail("Expected WRuntimeException");
- } catch (dev.vality.woody.api.flow.error.WRuntimeException ex) {
- assertEquals(dev.vality.woody.api.flow.error.WErrorType.UNEXPECTED_ERROR,
- ex.getErrorDefinition().getErrorType());
- assertEquals(dev.vality.woody.api.flow.error.WErrorSource.EXTERNAL,
- ex.getErrorDefinition().getGenerationSource());
- assertEquals(dev.vality.woody.api.flow.error.WErrorSource.EXTERNAL,
- ex.getErrorDefinition().getErrorSource());
- assertEquals("RuntimeException:downstream failure",
- ex.getErrorDefinition().getErrorReason());
- }
- }
-
- InvocationSnapshot upstream = upstreamInitial.get();
- InvocationSnapshot downstream = downstreamSnapshot.get();
- InvocationSnapshot after = upstreamAfterCall.get();
-
- assertNotNull(upstream);
- assertNotNull(downstream);
- assertNotNull(after);
-
- SpanStructure spans = SpanStructure.from(finishedSpans());
- spans.assertHasRootServer();
- spans.assertHasServerHierarchy();
- }
-
- @Test
- public void shouldHandleMissingMetadataGracefully() throws Exception {
- ScenarioSettings settings = ScenarioSettings.missingMetadata();
- scenario.set(settings);
-
- try (CloseableHttpClient httpClient = HttpClients.custom()
- .addRequestInterceptorLast((request, entity, ctx) -> {
- request.setHeader(TRACE_PARENT_HEADER,
- String.format("00-%s-%s-01", settings.inboundTraceId, settings.inboundSpanId));
- request.setHeader("woody.trace-id", settings.inboundTraceId);
- request.setHeader("woody.span-id", settings.inboundSpanId);
- request.setHeader("woody.parent-id", TraceContext.NO_PARENT_ID);
- })
- .addResponseInterceptorLast(this::captureResponseHeaders)
- .build()) {
- OwnerServiceSrv.Iface client = createThriftRPCClient(OwnerServiceSrv.Iface.class,
- new TimestampIdGenerator(), null, null, getUrlString("/upstream"), networkTimeout, httpClient);
-
- Owner owner = client.getOwner(9);
- assertEquals(new Owner(9, "downstream9"), owner);
- }
-
- InvocationSnapshot upstream = upstreamInitial.get();
- InvocationSnapshot downstream = downstreamSnapshot.get();
-
- assertNotNull(upstream);
- assertNotNull(downstream);
- assertNull(upstream.serviceMetadataRequestId);
- assertNull(downstream.serviceMetadataRequestId);
- assertNull(downstream.mdcServerMetadataId);
-
- SpanStructure spans = SpanStructure.from(finishedSpans());
- spans.assertServerStatus(StatusCode.UNSET, StatusCode.OK);
- spans.assertClientStatus(StatusCode.UNSET, StatusCode.OK);
- }
-
- private void injectInboundHeaders(HttpRequest request, ScenarioSettings settings) {
- request.setHeader(TRACE_PARENT_HEADER, settings.inboundTraceParent());
- request.setHeader(TRACE_STATE_HEADER, settings.traceState);
- request.setHeader("woody.trace-id", settings.inboundTraceId);
- request.setHeader("woody.span-id", settings.inboundSpanId);
- request.setHeader("woody.parent-id", TraceContext.NO_PARENT_ID);
- request.setHeader("woody.meta." + REQUEST_ID_KEY, settings.inboundRequestId);
- request.setHeader("woody.meta." + DEADLINE_KEY, settings.inboundDeadline);
- }
-
- private void captureResponseHeaders(HttpResponse response, EntityDetails entityDetails, HttpContext context)
- throws HttpException, IOException {
- if (entityDetails != null) {
- entityDetails.getContentLength();
- }
- if (context != null) {
- context.hashCode();
- }
- if (response.getFirstHeader(TRACE_PARENT_HEADER) != null) {
- responseTraceParent.set(response.getFirstHeader(TRACE_PARENT_HEADER).getValue());
- }
- if (response.getFirstHeader(TRACE_STATE_HEADER) != null) {
- responseTraceState.set(response.getFirstHeader(TRACE_STATE_HEADER).getValue());
- }
- }
-
- private static List finishedSpans() {
- if (sdkTracerProvider != null) {
- sdkTracerProvider.forceFlush().join(5, TimeUnit.SECONDS);
- }
- return SPAN_EXPORTER.getFinishedSpans();
- }
-
- private static final class ScenarioSettings {
- private final boolean propagateLocalMetadata;
- private final boolean downstreamThrows;
- private final RuntimeException downstreamException;
- private final String localRequestId;
- private final String localDeadline;
- private final String inboundTraceId;
- private final String inboundSpanId;
- private final String traceState;
- private final String inboundRequestId;
- private final String inboundDeadline;
-
- private ScenarioSettings(boolean propagateLocalMetadata, boolean downstreamThrows,
- RuntimeException downstreamException, String localRequestId,
- String localDeadline, String inboundTraceId, String inboundSpanId,
- String traceState, String inboundRequestId, String inboundDeadline) {
- this.propagateLocalMetadata = propagateLocalMetadata;
- this.downstreamThrows = downstreamThrows;
- this.downstreamException = downstreamException;
- this.localRequestId = localRequestId;
- this.localDeadline = localDeadline;
- this.inboundTraceId = inboundTraceId;
- this.inboundSpanId = inboundSpanId;
- this.traceState = traceState;
- this.inboundRequestId = inboundRequestId;
- this.inboundDeadline = inboundDeadline;
- }
-
- static ScenarioSettings fresh(String prefix) {
- String futureDeadline = Instant.now().plusSeconds(600).toString();
- return new ScenarioSettings(true, false, null,
- prefix + "-req",
- futureDeadline,
- null, null, null, null, null);
- }
-
- static ScenarioSettings restored(String traceId, String spanId, String traceState,
- String requestId, String deadline) {
- return new ScenarioSettings(false, false, null,
- null, null, traceId, spanId, traceState, requestId, deadline);
- }
-
- static ScenarioSettings error(String message) {
- return new ScenarioSettings(false, true, new RuntimeException(message),
- null, null, null, null, null, null, null);
- }
-
- static ScenarioSettings missingMetadata() {
- return new ScenarioSettings(false, false, null,
- null, null,
- "d4c1ecdb5e9240b1964280a8f1f34ce1",
- "71a3f955acbd42c9",
- null, null, null);
- }
-
- boolean expectTraceHeaders() {
- return inboundTraceId != null && inboundSpanId != null;
- }
-
- String inboundTraceParent() {
- if (!expectTraceHeaders()) {
- return null;
- }
- return String.format("00-%s-%s-01", inboundTraceId, inboundSpanId);
- }
-
- String expectedRequestId() {
- if (propagateLocalMetadata && localRequestId != null) {
- return localRequestId;
- }
- return inboundRequestId;
- }
-
- String expectedDeadline() {
- if (propagateLocalMetadata && localDeadline != null) {
- return localDeadline;
- }
- return inboundDeadline;
- }
- }
-
- private static final class InvocationSnapshot {
- private final boolean clientSpanFilled;
- private final String serviceTraceId;
- private final String serviceSpanId;
- private final String serviceParentId;
- private final String serviceMetadataRequestId;
- private final String serviceMetadataDeadline;
- private final String inboundTraceParent;
- private final String inboundTraceState;
- private final String otelTraceId;
- private final String otelSpanId;
- private final String mdcServerMetadataId;
- private final String mdcServerMetadataDeadline;
-
- private InvocationSnapshot(boolean clientSpanFilled, String serviceTraceId, String serviceSpanId,
- String serviceParentId, String serviceMetadataRequestId,
- String serviceMetadataDeadline, String inboundTraceParent,
- String inboundTraceState, String otelTraceId, String otelSpanId,
- String mdcServerMetadataId, String mdcServerMetadataDeadline) {
- this.clientSpanFilled = clientSpanFilled;
- this.serviceTraceId = serviceTraceId;
- this.serviceSpanId = serviceSpanId;
- this.serviceParentId = serviceParentId;
- this.serviceMetadataRequestId = serviceMetadataRequestId;
- this.serviceMetadataDeadline = serviceMetadataDeadline;
- this.inboundTraceParent = inboundTraceParent;
- this.inboundTraceState = inboundTraceState;
- this.otelTraceId = otelTraceId;
- this.otelSpanId = otelSpanId;
- this.mdcServerMetadataId = mdcServerMetadataId;
- this.mdcServerMetadataDeadline = mdcServerMetadataDeadline;
- }
-
- private static InvocationSnapshot capture() {
- TraceData traceData = TraceContext.getCurrentTraceData();
- if (traceData == null) {
- return new InvocationSnapshot(false, null, null, null, null, null,
- null, null, null, null, null, null);
- }
- ContextSpan serviceSpan = traceData.getServiceSpan();
- SpanContext spanContext = traceData.getOtelSpan().getSpanContext();
- return new InvocationSnapshot(traceData.getClientSpan().isFilled(),
- serviceSpan.getSpan().getTraceId(),
- serviceSpan.getSpan().getId(),
- serviceSpan.getSpan().getParentId(),
- ContextUtils.getCustomMetadataValue(serviceSpan, String.class, REQUEST_ID_KEY),
- ContextUtils.getCustomMetadataValue(serviceSpan, String.class, DEADLINE_KEY),
- traceData.getInboundTraceParent(),
- traceData.getInboundTraceState(),
- spanContext.getTraceId(),
- spanContext.getSpanId(),
- MDC.get("rpc.server.metadata." + REQUEST_ID_KEY),
- MDC.get("rpc.server.metadata." + DEADLINE_KEY));
- }
- }
-
- private static final class SpanStructure {
- private final List clientSpans;
- private final List serverSpans;
-
- private SpanStructure(List clientSpans, List serverSpans) {
- this.clientSpans = clientSpans;
- this.serverSpans = serverSpans;
- }
-
- static SpanStructure from(List spans) {
- List clients = spans.stream()
- .filter(span -> span.getKind() == SpanKind.CLIENT)
- .collect(Collectors.toList());
- List servers = spans.stream()
- .filter(span -> span.getKind() == SpanKind.SERVER)
- .collect(Collectors.toList());
- if (clients.isEmpty()) {
- throw new AssertionError("Missing client spans");
- }
- if (servers.isEmpty()) {
- throw new AssertionError("Missing server spans");
- }
- return new SpanStructure(clients, servers);
- }
-
- void assertServerTraceConsistency() {
- var serverTraceIds = serverSpans.stream()
- .map(SpanData::getTraceId)
- .collect(Collectors.toSet());
- assertEquals("Server spans must share trace", 1, serverTraceIds.size());
- }
-
- void assertHasRootServer() {
- var serverIds = serverSpans.stream().map(SpanData::getSpanId).collect(Collectors.toSet());
- boolean hasRoot = serverSpans.stream()
- .anyMatch(span -> !serverIds.contains(span.getParentSpanId()));
- assertTrue("Expected upstream server span", hasRoot);
- }
-
- void assertHasServerHierarchy() {
- var serverIds = serverSpans.stream().map(SpanData::getSpanId).collect(Collectors.toSet());
- boolean hasHierarchy = serverSpans.stream()
- .anyMatch(span -> serverIds.contains(span.getParentSpanId()));
- assertTrue("Expected downstream server span", hasHierarchy);
- }
-
- void assertServerStatus(StatusCode... expected) {
- var allowed = Arrays.stream(expected).collect(Collectors.toSet());
- serverSpans.forEach(span -> assertTrue("Unexpected server status " + span.getStatus(),
- allowed.contains(span.getStatus().getStatusCode())));
- }
-
- void assertClientStatus(StatusCode... expected) {
- var allowed = Arrays.stream(expected).collect(Collectors.toSet());
- clientSpans.forEach(span -> assertTrue("Unexpected client status " + span.getStatus(),
- allowed.contains(span.getStatus().getStatusCode())));
- }
-
- }
-
- private static final class RecordingSpanExporter implements SpanExporter {
- private final List spans = new java.util.concurrent.CopyOnWriteArrayList<>();
-
- @Override
- public CompletableResultCode export(Collection spans) {
- this.spans.addAll(spans);
- return CompletableResultCode.ofSuccess();
- }
-
- @Override
- public CompletableResultCode flush() {
- return CompletableResultCode.ofSuccess();
- }
-
- @Override
- public CompletableResultCode shutdown() {
- spans.clear();
- return CompletableResultCode.ofSuccess();
- }
-
- List getFinishedSpans() {
- return spans;
- }
-
- void reset() {
- spans.clear();
- }
- }
-}
diff --git a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/error/THProviderErrorMapperTest.java b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/error/THProviderErrorMapperTest.java
index ec3e0a8f..685f0e69 100644
--- a/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/error/THProviderErrorMapperTest.java
+++ b/woody-thrift/src/test/java/dev/vality/woody/thrift/impl/http/error/THProviderErrorMapperTest.java
@@ -33,9 +33,6 @@ public void setUp() {
@After
public void tearDown() {
- if (testTraceData != null) {
- testTraceData.getOtelSpan().end();
- }
TraceContext.setCurrentTraceData(originalTraceData);
}
diff --git a/woody-thrift/src/test/resources/log4j.properties b/woody-thrift/src/test/resources/log4j.properties
index 4443f630..2d3654fa 100644
--- a/woody-thrift/src/test/resources/log4j.properties
+++ b/woody-thrift/src/test/resources/log4j.properties
@@ -2,4 +2,4 @@ log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=[%t] %d{yyyy-MM-dd HH:mm:ss.SSS} %-5p Span[%X{trace_id}-%X{span_id}-%X{parent_id}, deadline: %X{deadline}] OtelSpan[%X{otel_trace_id}-%X{otel_span_id}] - %m%n
+log4j.appender.stdout.layout.ConversionPattern=[%t] %d{yyyy-MM-dd HH:mm:ss.SSS} %-5p Span[%X{trace_id}-%X{span_id}-%X{parent_id}, deadline: %X{deadline}] - %m%n
diff --git a/woody-thrift/woody-thrift.md b/woody-thrift/woody-thrift.md
index fb83ebfb..60f15015 100644
--- a/woody-thrift/woody-thrift.md
+++ b/woody-thrift/woody-thrift.md
@@ -81,17 +81,14 @@ Servlet service = serviceBuilder.build(ThriftServiceSrv.Iface.class, handler);
### Интеграционные тесты
-Для проверки сквозной OpenTelemetry-трассировки, восстановления контекста,
-обработки ошибок и работы без обязательных метаданных используйте
-интеграционный набор `TraceLifecycleIntegrationTest` в модуле `woody-thrift`.
+Для проверки обработки ошибок и HTTP-интеграции используйте тесты модуля
+`woody-thrift`.
### Обработка ошибок и метаданных
- Маппер `THProviderErrorMapper` сопоставляет HTTP/Thrift ошибки с
`WErrorDefinition`, заполняет `THMetadataProperties` (тип/подтип) и учитывает
перехваченные ошибки транспортных интерсепторов.
-- `MetadataMdcPropagationTest` и `THProviderErrorMapperTest` служат примерами
- того, как проверять перенос MDC-метаданных и корректность кодификации
- транспортных исключений.
-
-
+- `THProviderErrorMapperTest` и `TestClientAndServerHttpHeaders` служат
+ примерами того, как проверять перенос MDC-метаданных и корректность
+ кодификации транспортных исключений.