BufferingApplicationStartup Class — spring-boot Architecture
Architecture documentation for the BufferingApplicationStartup class in BufferingApplicationStartup.java from the spring-boot codebase.
Entity Profile
Source Code
core/spring-boot/src/main/java/org/springframework/boot/context/metrics/buffering/BufferingApplicationStartup.java lines 55–175
public class BufferingApplicationStartup implements ApplicationStartup {
private final int capacity;
private final Clock clock;
private Instant startTime;
private final AtomicInteger idSeq = new AtomicInteger();
private Predicate<StartupStep> filter = (step) -> true;
private final AtomicReference<@Nullable BufferedStartupStep> current = new AtomicReference<>();
private final AtomicInteger estimatedSize = new AtomicInteger();
private final ConcurrentLinkedQueue<TimelineEvent> events = new ConcurrentLinkedQueue<>();
/**
* Create a new buffered {@link ApplicationStartup} with a limited capacity and starts
* the recording of steps.
* @param capacity the configured capacity; once reached, new steps are not recorded.
*/
public BufferingApplicationStartup(int capacity) {
this(capacity, Clock.systemDefaultZone());
}
BufferingApplicationStartup(int capacity, Clock clock) {
this.capacity = capacity;
this.clock = clock;
this.startTime = clock.instant();
}
/**
* Start the recording of steps and mark the beginning of the {@link StartupTimeline}.
* The class constructor already implicitly calls this, but it is possible to reset it
* as long as steps have not been recorded already.
* @throws IllegalStateException if called and {@link StartupStep} have been recorded
* already.
*/
public void startRecording() {
Assert.state(this.events.isEmpty(), "Cannot restart recording once steps have been buffered");
this.startTime = this.clock.instant();
}
/**
* Add a predicate filter to the list of existing ones.
* <p>
* A {@link StartupStep step} that doesn't match all filters will not be recorded.
* @param filter the predicate filter to add.
*/
public void addFilter(Predicate<StartupStep> filter) {
this.filter = this.filter.and(filter);
}
@Override
public StartupStep start(String name) {
int id = this.idSeq.getAndIncrement();
Instant start = this.clock.instant();
while (true) {
BufferedStartupStep current = this.current.get();
BufferedStartupStep parent = getLatestActive(current);
BufferedStartupStep next = new BufferedStartupStep(parent, name, id, start, this::record);
if (this.current.compareAndSet(current, next)) {
return next;
}
}
}
private void record(BufferedStartupStep step) {
if (this.filter.test(step) && this.estimatedSize.get() < this.capacity) {
this.estimatedSize.incrementAndGet();
this.events.add(new TimelineEvent(step, this.clock.instant()));
}
while (true) {
BufferedStartupStep current = this.current.get();
BufferedStartupStep next = getLatestActive(current);
if (this.current.compareAndSet(current, next)) {
return;
}
}
}
private @Nullable BufferedStartupStep getLatestActive(@Nullable BufferedStartupStep step) {
while (step != null && step.isEnded()) {
step = step.getParent();
}
return step;
}
/**
* Return the {@link StartupTimeline timeline} as a snapshot of currently buffered
* steps.
* <p>
* This will not remove steps from the buffer, see {@link #drainBufferedTimeline()}
* for its counterpart.
* @return a snapshot of currently buffered steps.
*/
public StartupTimeline getBufferedTimeline() {
return new StartupTimeline(this.startTime, new ArrayList<>(this.events));
}
/**
* Return the {@link StartupTimeline timeline} by pulling steps from the buffer.
* <p>
* This removes steps from the buffer, see {@link #getBufferedTimeline()} for its
* read-only counterpart.
* @return buffered steps drained from the buffer.
*/
public StartupTimeline drainBufferedTimeline() {
List<TimelineEvent> events = new ArrayList<>();
Iterator<TimelineEvent> iterator = this.events.iterator();
while (iterator.hasNext()) {
events.add(iterator.next());
iterator.remove();
}
this.estimatedSize.set(0);
return new StartupTimeline(this.startTime, events);
}
}
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free