|
|
|
@ -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) { |
|
|
|
this.before.start(); |
|
|
|
if (this.currentObservation == PhasedObservation.NOOP) { |
|
|
|
return this.before.observation; |
|
|
|
this.before.start(); |
|
|
|
} |
|
|
|
this.currentObservation = this.before; |
|
|
|
if (this.currentObservation.compareAndSet(this.before, this.after)) { |
|
|
|
return this.currentObservation; |
|
|
|
this.before.stop(); |
|
|
|
} |
|
|
|
this.after.start(); |
|
|
|
if (this.currentObservation == this.before) { |
|
|
|
return this.after.observation; |
|
|
|
this.before.stop(); |
|
|
|
|
|
|
|
this.after.start(); |
|
|
|
|
|
|
|
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(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|