Close Both Observations
Depending on when a request is cancelled, the before and after observation starts and stops may be called out of order due to the order in which their doOnCancel handlers are invoked. To address this, the before filter-wrapper now always closes both the before observation and the after observation. Since the before filter- wrapper wraps the entire request, this ensures that either that was started is stopped, and either that has not been started yet cannot inadvertently be started by any unexpected ordering of events that follows. Closes gh-14031
This commit is contained in:
@@ -292,7 +292,13 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
this.currentObservation.get().stop();
|
||||
this.before.stop();
|
||||
this.after.stop();
|
||||
}
|
||||
|
||||
private void close() {
|
||||
this.before.close();
|
||||
this.after.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -357,11 +363,11 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
|
||||
start();
|
||||
// @formatter:off
|
||||
return filter.filter(exchange, chain)
|
||||
.doOnSuccess((v) -> stop())
|
||||
.doOnCancel(this::stop)
|
||||
.doOnSuccess((v) -> close())
|
||||
.doOnCancel(this::close)
|
||||
.doOnError((t) -> {
|
||||
error(t);
|
||||
stop();
|
||||
close();
|
||||
})
|
||||
.contextWrite((context) -> context.put(ObservationThreadLocalAccessor.KEY, this));
|
||||
// @formatter:on
|
||||
@@ -433,6 +439,21 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
|
||||
}
|
||||
}
|
||||
|
||||
private void close() {
|
||||
try {
|
||||
this.lock.lock();
|
||||
if (this.state.compareAndSet(1, 3)) {
|
||||
this.observation.stop();
|
||||
}
|
||||
else {
|
||||
this.state.set(3);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user