-
Notifications
You must be signed in to change notification settings - Fork 1k
Virtual threads metrics #5067
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
shakuzen
merged 20 commits into
micrometer-metrics:main
from
ArtyomGabeev:virtual-threads-metrics
Sep 24, 2024
Merged
Virtual threads metrics #5067
Changes from 10 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
0e699be
Virtual threads metrics
ArtyomGabeev 41ce1be
cr changes
ArtyomGabeev 046bf08
extract java21 module
ArtyomGabeev 6f4efdb
fix format
ArtyomGabeev d44f305
add package info
ArtyomGabeev fa842aa
Merge branch 'master' into virtual-threads-metrics
ArtyomGabeev 609f103
rename maxSize to explicitly mention unit
ArtyomGabeev f1de36d
remove old jdk executors
ArtyomGabeev 1cd17b4
attempt to install openjdk21 as root
ArtyomGabeev da232cc
switch to latest ubuntu machine executor
ArtyomGabeev 9ddc77e
rollback previous CI executors
ArtyomGabeev 13291d3
cr changes
ArtyomGabeev d142cfe
rever machine executor image
ArtyomGabeev 1dc9470
Polish implementation and improve tests
ArtyomGabeev 784225c
rename metrics class and package
ArtyomGabeev b787eb2
Add a test for failed starting and unparking
jonatan-ivanov 063d3f2
Relax test value offsets
jonatan-ivanov 2fe817d
Fix VirtualThreadMetricsTests name in a comment
jonatan-ivanov ffb902a
Fix copyright year
jonatan-ivanov 11f1016
Separate tests that use reflection for java.lang
jonatan-ivanov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
description 'Micrometer core classes that require Java 21' | ||
|
||
dependencies { | ||
api project(":micrometer-core") | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
testImplementation 'org.awaitility:awaitility' | ||
testImplementation project(":micrometer-observation-test") | ||
shakuzen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
java { | ||
targetCompatibility = 21 | ||
} | ||
|
||
tasks.withType(JavaCompile).configureEach { | ||
sourceCompatibility = JavaVersion.VERSION_21 | ||
targetCompatibility = JavaVersion.VERSION_21 | ||
options.release = 21 | ||
} |
113 changes: 113 additions & 0 deletions
113
...rc/main/java/io/micrometer/java21/instrument/binder/jfr/JfrVirtualThreadEventMetrics.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* | ||
* Copyright 2024 VMware, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micrometer.java21.instrument.binder.jfr; | ||
|
||
import io.micrometer.core.instrument.Counter; | ||
import io.micrometer.core.instrument.MeterRegistry; | ||
import io.micrometer.core.instrument.Tag; | ||
import io.micrometer.core.instrument.Timer; | ||
import io.micrometer.core.instrument.binder.MeterBinder; | ||
import jdk.jfr.consumer.RecordingStream; | ||
|
||
import java.io.Closeable; | ||
import java.io.IOException; | ||
import java.time.Duration; | ||
import java.util.Objects; | ||
|
||
import static java.util.Collections.emptyList; | ||
|
||
public class JfrVirtualThreadEventMetrics implements MeterBinder, Closeable { | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public static final String PINNED_EVENT = "jdk.VirtualThreadPinned"; | ||
|
||
public static final String SUBMIT_FAILED_EVENT = "jdk.VirtualThreadSubmitFailed"; | ||
shakuzen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
private final RecordingSettings settings; | ||
|
||
private final Iterable<Tag> tags; | ||
|
||
private boolean started = false; | ||
|
||
private RecordingStream recordingStream; | ||
|
||
public JfrVirtualThreadEventMetrics() { | ||
this(new RecordingSettings(), emptyList()); | ||
} | ||
|
||
public JfrVirtualThreadEventMetrics(Iterable<Tag> tags) { | ||
this(new RecordingSettings(), tags); | ||
} | ||
|
||
public JfrVirtualThreadEventMetrics(RecordingSettings settings, Iterable<Tag> tags) { | ||
this.settings = settings; | ||
this.tags = tags; | ||
} | ||
|
||
@Override | ||
public void bindTo(MeterRegistry registry) { | ||
if (started) { | ||
return; | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
started = true; | ||
recordingStream = createRecordingStream(settings); | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
final Timer pinnedTimer = Timer.builder("jvm.virtual.thread.pinned") | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.tags(tags) | ||
.description("The duration of virtual threads that were pinned to a physical thread") | ||
.register(registry); | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
final Counter submitFailedCounter = Counter.builder("jvm.virtual.thread.submit.failed") | ||
.tags(tags) | ||
.description("The number of virtual thread submissions that failed") | ||
.register(registry); | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
recordingStream.onEvent(PINNED_EVENT, event -> pinnedTimer.record(event.getDuration())); | ||
recordingStream.onEvent(SUBMIT_FAILED_EVENT, event -> submitFailedCounter.increment()); | ||
} | ||
|
||
protected RecordingStream createRecordingStream(RecordingSettings settings) { | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
final RecordingStream recordingStream = new RecordingStream(); | ||
recordingStream.enable(PINNED_EVENT).withThreshold(settings.pinnedThreshold); | ||
recordingStream.enable(SUBMIT_FAILED_EVENT); | ||
recordingStream.setMaxAge(settings.maxAge); | ||
recordingStream.setMaxSize(settings.maxSizeBytes); | ||
recordingStream.startAsync(); | ||
return recordingStream; | ||
} | ||
|
||
@Override | ||
public void close() throws IOException { | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (started) { | ||
recordingStream.close(); | ||
} | ||
} | ||
|
||
public record RecordingSettings(Duration maxAge, long maxSizeBytes, Duration pinnedThreshold) { | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public RecordingSettings { | ||
Objects.requireNonNull(maxAge, "maxAge parameter must not be null"); | ||
Objects.requireNonNull(pinnedThreshold, "pinnedThreshold must not be null"); | ||
if (maxSizeBytes < 0) { | ||
throw new IllegalArgumentException("maxSizeBytes must be positive"); | ||
} | ||
} | ||
|
||
public RecordingSettings() { | ||
this(Duration.ofSeconds(5), 10L * 1024 * 1024, Duration.ofMillis(1)); | ||
shakuzen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
micrometer-java21/src/main/java/io/micrometer/java21/instrument/binder/jfr/package-info.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright 2024 VMware, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
/** | ||
* Instrumentation of JDK classes. | ||
*/ | ||
@NonNullApi | ||
@NonNullFields | ||
package io.micrometer.java21.instrument.binder.jfr; | ||
|
||
import io.micrometer.common.lang.NonNullApi; | ||
import io.micrometer.common.lang.NonNullFields; |
70 changes: 70 additions & 0 deletions
70
...st/java/io/micrometer/java21/instrument/binder/jfr/JfrVirtualThreadEventMetricsTests.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright 2022 VMware, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micrometer.java21.instrument.binder.jfr; | ||
|
||
import io.micrometer.core.instrument.MeterRegistry; | ||
import io.micrometer.core.instrument.Tags; | ||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.io.IOException; | ||
import java.time.Duration; | ||
|
||
import static org.awaitility.Awaitility.await; | ||
|
||
class JfrVirtualThreadEventMetricsTests { | ||
|
||
private static final Tags USER_TAGS = Tags.of("k", "v"); | ||
|
||
private MeterRegistry registry; | ||
|
||
private JfrVirtualThreadEventMetrics jfrMetrics; | ||
|
||
@BeforeEach | ||
void setup() { | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
registry = new SimpleMeterRegistry(); | ||
jfrMetrics = new JfrVirtualThreadEventMetrics(USER_TAGS); | ||
jfrMetrics.bindTo(registry); | ||
} | ||
|
||
@Test | ||
void registerPinnedEvent() throws Exception { | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Thread.ofVirtual().name("vt-test").start(() -> { | ||
synchronized (this) { | ||
sleep(Duration.ofMillis(100)); | ||
} | ||
}).join(); | ||
|
||
await().atMost(Duration.ofSeconds(2)) | ||
.until(() -> registry.get("jvm.virtual.thread.pinned").tags(USER_TAGS).timer().count() == 1); | ||
} | ||
|
||
private void sleep(Duration duration) { | ||
try { | ||
Thread.sleep(duration); | ||
} | ||
catch (InterruptedException ignored) { | ||
} | ||
} | ||
|
||
@AfterEach | ||
void cleanup() throws IOException { | ||
jonatan-ivanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
jfrMetrics.close(); | ||
} | ||
|
||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.