Use synchronized

Closes gh-14445
This commit is contained in:
Josh Cummings 2024-02-07 08:48:15 -07:00
parent 54a407b159
commit 75fdcd10f7
No known key found for this signature in database
GPG Key ID: A306A51F43B8E5A5
1 changed files with 40 additions and 55 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,10 +19,6 @@ package org.springframework.security.web.server;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import io.micrometer.common.KeyValue; import io.micrometer.common.KeyValue;
import io.micrometer.common.KeyValues; import io.micrometer.common.KeyValues;
@ -258,12 +254,13 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
class SimpleAroundWebFilterObservation implements AroundWebFilterObservation { class SimpleAroundWebFilterObservation implements AroundWebFilterObservation {
private final Object lock = new Object();
private final PhasedObservation before; private final PhasedObservation before;
private final PhasedObservation after; private final PhasedObservation after;
private final AtomicReference<PhasedObservation> currentObservation = new AtomicReference<>( private volatile PhasedObservation currentObservation = PhasedObservation.NOOP;
PhasedObservation.NOOP);
SimpleAroundWebFilterObservation(Observation before, Observation after) { SimpleAroundWebFilterObservation(Observation before, Observation after) {
this.before = new PhasedObservation(before); this.before = new PhasedObservation(before);
@ -272,22 +269,26 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
@Override @Override
public Observation start() { public Observation start() {
if (this.currentObservation.compareAndSet(PhasedObservation.NOOP, this.before)) { synchronized (this.lock) {
if (this.currentObservation == PhasedObservation.NOOP) {
this.before.start(); this.before.start();
return this.before.observation; this.currentObservation = this.before;
return this.currentObservation;
} }
if (this.currentObservation.compareAndSet(this.before, this.after)) { if (this.currentObservation == this.before) {
this.before.stop(); this.before.stop();
this.after.start(); this.after.start();
return this.after.observation; this.currentObservation = this.after;
return this.currentObservation;
}
} }
return Observation.NOOP; return Observation.NOOP;
} }
@Override @Override
public Observation error(Throwable ex) { public Observation error(Throwable ex) {
this.currentObservation.get().error(ex); this.currentObservation.error(ex);
return this.currentObservation.get().observation; return this.currentObservation.observation;
} }
@Override @Override
@ -303,42 +304,42 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
@Override @Override
public Observation contextualName(String contextualName) { public Observation contextualName(String contextualName) {
return this.currentObservation.get().observation.contextualName(contextualName); return this.currentObservation.observation.contextualName(contextualName);
} }
@Override @Override
public Observation parentObservation(Observation parentObservation) { public Observation parentObservation(Observation parentObservation) {
return this.currentObservation.get().observation.parentObservation(parentObservation); return this.currentObservation.observation.parentObservation(parentObservation);
} }
@Override @Override
public Observation lowCardinalityKeyValue(KeyValue keyValue) { public Observation lowCardinalityKeyValue(KeyValue keyValue) {
return this.currentObservation.get().observation.lowCardinalityKeyValue(keyValue); return this.currentObservation.observation.lowCardinalityKeyValue(keyValue);
} }
@Override @Override
public Observation highCardinalityKeyValue(KeyValue keyValue) { public Observation highCardinalityKeyValue(KeyValue keyValue) {
return this.currentObservation.get().observation.highCardinalityKeyValue(keyValue); return this.currentObservation.observation.highCardinalityKeyValue(keyValue);
} }
@Override @Override
public Observation observationConvention(ObservationConvention<?> observationConvention) { public Observation observationConvention(ObservationConvention<?> observationConvention) {
return this.currentObservation.get().observation.observationConvention(observationConvention); return this.currentObservation.observation.observationConvention(observationConvention);
} }
@Override @Override
public Observation event(Event event) { public Observation event(Event event) {
return this.currentObservation.get().observation.event(event); return this.currentObservation.observation.event(event);
} }
@Override @Override
public Context getContext() { public Context getContext() {
return this.currentObservation.get().observation.getContext(); return this.currentObservation.observation.getContext();
} }
@Override @Override
public Scope openScope() { public Scope openScope() {
return this.currentObservation.get().observation.openScope(); return this.currentObservation.observation.openScope();
} }
@Override @Override
@ -386,7 +387,7 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
@Override @Override
public String toString() { public String toString() {
return this.currentObservation.get().observation.toString(); return this.currentObservation.observation.toString();
} }
} }
@ -665,9 +666,9 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
private static final PhasedObservation NOOP = new PhasedObservation(Observation.NOOP); private static final PhasedObservation NOOP = new PhasedObservation(Observation.NOOP);
private final Lock lock = new ReentrantLock(); private final Object lock = new Object();
private final AtomicInteger phase = new AtomicInteger(0); private volatile int phase = 0;
private final Observation observation; private final Observation observation;
@ -717,57 +718,41 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
@Override @Override
public PhasedObservation start() { public PhasedObservation start() {
try { synchronized (this.lock) {
this.lock.lock(); if (this.phase == 0) {
if (this.phase.compareAndSet(0, 1)) {
this.observation.start(); this.observation.start();
this.phase = 1;
} }
} }
finally {
this.lock.unlock();
}
return this; return this;
} }
@Override @Override
public PhasedObservation error(Throwable ex) { public PhasedObservation error(Throwable ex) {
try { synchronized (this.lock) {
this.lock.lock(); if (this.phase == 1) {
if (this.phase.get() == 1) {
this.observation.error(ex); this.observation.error(ex);
} }
} }
finally {
this.lock.unlock();
}
return this; return this;
} }
@Override @Override
public void stop() { public void stop() {
try { synchronized (this.lock) {
this.lock.lock(); if (this.phase == 1) {
if (this.phase.compareAndSet(1, 2)) {
this.observation.stop(); this.observation.stop();
this.phase = 2;
} }
} }
finally {
this.lock.unlock();
}
} }
void close() { void close() {
try { synchronized (this.lock) {
this.lock.lock(); if (this.phase == 1) {
if (this.phase.compareAndSet(1, 3)) {
this.observation.stop(); this.observation.stop();
} }
else { this.phase = 3;
this.phase.set(3);
}
}
finally {
this.lock.unlock();
} }
} }