Drop instrumentation-api-caching module and move weak cache implementation to instrumentation-api (#4667)
* Drop instrumentation-api-caching module and move weak cache implementation to instrumentation-api * Some test fixes * Some cleanup * Temporary workaround for using weak values in FutureListenerWrappers * Spotless * Update ClassNames and SpanNames * Compilation and comment * Add bounded cache and clean interface * Polish * Add comment * Vendor ConcurrentLinkedHashMap in * Let errorprone ignore vendored CLHM for now * Keep license in java files too * Convert Netty wrapper cache to VirtualField * Work around lambda instrumentation failure Ideally we would ignore instrumenting helper classes... * Revert "Work around lambda instrumentation failure" This reverts commit6d63815b44
. * Revert "Convert Netty wrapper cache to VirtualField" This reverts commitdac1522a3f
. * Handle cleared weak values * Fix comment * Delete instrumentation-api-caching * Copy in weak-lock-free * Remove caffeine remnants * Fix checkstyle * Rename BoundedCache to MapBackedCached * Remove duplicate LICENSE * Remove outdated comment * Sync with SDK copy of weaklockfree * Enable checkstyle:off comment * Re-generate license report * Move NOTICE file to package-info.java Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
parent
a5326344bd
commit
821a4b870b
|
@ -21,7 +21,7 @@ dependencies {
|
|||
jmh(project(":javaagent-tooling"))
|
||||
jmh(project(":javaagent-extension-api"))
|
||||
|
||||
jmh("com.github.ben-manes.caffeine:caffeine:$caffeine2Version")
|
||||
jmh("com.github.ben-manes.caffeine:caffeine:2.9.2")
|
||||
|
||||
jmh("javax.servlet:javax.servlet-api:4.0.1")
|
||||
jmh("com.google.http-client:google-http-client:1.19.0")
|
||||
|
|
|
@ -373,6 +373,8 @@
|
|||
</module>
|
||||
<!-- this enables @SuppressWarnings("checkstyle:...") annotations -->
|
||||
<module name="SuppressWarningsHolder"/>
|
||||
<!-- this enables CHECKSTYLE:OFF and CHECKSTYLE:ON comments -->
|
||||
<module name="SuppressionCommentFilter"/>
|
||||
</module>
|
||||
<!-- this enables @SuppressWarnings("checkstyle:...") annotations -->
|
||||
<module name="SuppressWarningsFilter"/>
|
||||
|
|
|
@ -8,7 +8,6 @@ tasks.withType<ShadowJar>().configureEach {
|
|||
mergeServiceFiles()
|
||||
|
||||
exclude("**/module-info.class")
|
||||
exclude("META-INF/jandex.idx") // from caffeine
|
||||
|
||||
// Prevents conflict with other SLF4J instances. Important for premain.
|
||||
relocate("org.slf4j", "io.opentelemetry.javaagent.slf4j")
|
||||
|
|
|
@ -19,7 +19,7 @@ tasks {
|
|||
disableWarningsInGeneratedCode.set(true)
|
||||
allDisabledChecksAsWarnings.set(true)
|
||||
|
||||
excludedPaths.set(".*/build/generated/.*")
|
||||
excludedPaths.set(".*/build/generated/.*|.*/concurrentlinkedhashmap/.*")
|
||||
|
||||
if (System.getenv("CI") == null) {
|
||||
disable("SystemOut")
|
||||
|
|
|
@ -12,8 +12,4 @@ dependencies {
|
|||
compileOnly("io.opentelemetry:opentelemetry-api")
|
||||
compileOnly(project(":instrumentation-api"))
|
||||
compileOnly(project(":javaagent-instrumentation-api"))
|
||||
|
||||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our
|
||||
// inclusion of this artifact inside of :instrumentation-api
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
}
|
||||
|
|
|
@ -7,10 +7,4 @@ plugins {
|
|||
|
||||
extra["mavenGroupId"] = "io.opentelemetry.javaagent.instrumentation"
|
||||
|
||||
base.archivesName.set(projectDir.parentFile.name)
|
||||
|
||||
dependencies {
|
||||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our
|
||||
// inclusion of this artifact inside of :instrumentation-api
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
}
|
||||
base.archivesName.set(projectDir.parentFile.name)
|
|
@ -8,10 +8,4 @@ plugins {
|
|||
|
||||
extra["mavenGroupId"] = "io.opentelemetry.instrumentation"
|
||||
|
||||
base.archivesName.set(projectDir.parentFile.name)
|
||||
|
||||
dependencies {
|
||||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our
|
||||
// inclusion of this artifact inside of :instrumentation-api
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
}
|
||||
base.archivesName.set(projectDir.parentFile.name)
|
|
@ -17,9 +17,6 @@ rootProject.extra["otelVersion"] = otelVersion
|
|||
// Need both BOM and -all
|
||||
val groovyVersion = "2.5.14"
|
||||
|
||||
rootProject.extra["caffeine2Version"] = "2.9.2"
|
||||
rootProject.extra["caffeine3Version"] = "3.0.4"
|
||||
|
||||
// We don't force libraries we instrument to new versions since we compile and test against specific
|
||||
// old baseline versions
|
||||
// but we do try to force those libraries' transitive dependencies to new versions where possible
|
||||
|
@ -87,7 +84,6 @@ val DEPENDENCY_SETS = listOf(
|
|||
|
||||
val DEPENDENCIES = listOf(
|
||||
"ch.qos.logback:logback-classic:1.2.3",
|
||||
"com.blogspot.mydailyjava:weak-lock-free:0.18",
|
||||
"com.github.stefanbirkner:system-lambda:1.2.0",
|
||||
"com.github.stefanbirkner:system-rules:1.19.0",
|
||||
"com.google.auto.service:auto-service:1.0",
|
||||
|
|
|
@ -10,11 +10,6 @@ group = "io.opentelemetry.instrumentation"
|
|||
dependencies {
|
||||
implementation(project(":instrumentation-api"))
|
||||
|
||||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our
|
||||
// inclusion of this artifact inside of :instrumentation-api
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
testCompileOnly(project(":instrumentation-api-caching"))
|
||||
|
||||
api("io.opentelemetry:opentelemetry-api")
|
||||
api("io.opentelemetry:opentelemetry-semconv")
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package io.opentelemetry.instrumentation.api.annotation.support;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
package io.opentelemetry.instrumentation.api.annotation.support;
|
||||
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.tracer.AttributeSetter;
|
||||
import java.lang.reflect.Method;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
package io.opentelemetry.instrumentation.api.annotation.support
|
||||
|
||||
import io.opentelemetry.api.common.AttributesBuilder
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache
|
||||
import spock.lang.Specification
|
||||
|
||||
import java.lang.reflect.Method
|
||||
|
|
|
@ -11,7 +11,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
|
|||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Function;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
plugins {
|
||||
id("com.github.johnrengelman.shadow")
|
||||
|
||||
id("otel.java-conventions")
|
||||
}
|
||||
|
||||
group = "io.opentelemetry.javaagent"
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
val caffeine2ShadedDeps = project(":instrumentation-api-caching:caffeine2")
|
||||
output.dir(caffeine2ShadedDeps.file("build/extracted/shadow"), "builtBy" to ":instrumentation-api-caching:caffeine2:extractShadowJar")
|
||||
}
|
||||
}
|
||||
|
||||
val shadowInclude by configurations.creating {
|
||||
isCanBeResolved = true
|
||||
isCanBeConsumed = false
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":instrumentation-api-caching:caffeine2", configuration = "shadow"))
|
||||
compileOnly(project(":instrumentation-api-caching:caffeine3", configuration = "shadow"))
|
||||
|
||||
compileOnly("org.checkerframework:checker-qual:3.14.0")
|
||||
compileOnly("com.blogspot.mydailyjava:weak-lock-free")
|
||||
shadowInclude("com.blogspot.mydailyjava:weak-lock-free")
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
configurations = listOf(shadowInclude)
|
||||
|
||||
relocate("com.blogspot.mydailyjava.weaklockfree", "io.opentelemetry.instrumentation.api.internal.shaded.weaklockfree")
|
||||
}
|
||||
|
||||
val extractShadowJar by registering(Copy::class) {
|
||||
dependsOn(shadowJar)
|
||||
from(zipTree(shadowJar.get().archiveFile)) {
|
||||
exclude("META-INF/**")
|
||||
}
|
||||
into("build/extracted/shadow")
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
plugins {
|
||||
id("com.github.johnrengelman.shadow")
|
||||
|
||||
id("otel.java-conventions")
|
||||
}
|
||||
|
||||
group = "io.opentelemetry.javaagent"
|
||||
|
||||
val shadowInclude by configurations.creating {
|
||||
isCanBeResolved = true
|
||||
isCanBeConsumed = false
|
||||
}
|
||||
|
||||
val caffeine2Version: String by project
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.github.ben-manes.caffeine:caffeine:$caffeine2Version")
|
||||
shadowInclude("com.github.ben-manes.caffeine:caffeine:$caffeine2Version") {
|
||||
exclude("com.google.errorprone", "error_prone_annotations")
|
||||
exclude("org.checkerframework", "checker-qual")
|
||||
}
|
||||
}
|
||||
|
||||
// patch inner class from Caffeine to avoid ForkJoinTask from being loaded too early in the javaagent
|
||||
val patch by sourceSets.creating {
|
||||
java {}
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
configurations = listOf(shadowInclude)
|
||||
|
||||
relocate("com.github.benmanes.caffeine", "io.opentelemetry.instrumentation.api.internal.shaded.caffeine2")
|
||||
|
||||
minimize()
|
||||
}
|
||||
|
||||
javadoc {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
val extractShadowJar by registering(Copy::class) {
|
||||
dependsOn(shadowJar)
|
||||
|
||||
// replace caffeine class with our patched version
|
||||
from(zipTree(shadowJar.get().archiveFile)) {
|
||||
exclude("io/opentelemetry/instrumentation/api/internal/shaded/caffeine2/cache/BoundedLocalCache\$PerformCleanupTask.class")
|
||||
exclude("META-INF/**")
|
||||
}
|
||||
from(patch.output) {
|
||||
include("io/opentelemetry/instrumentation/api/internal/shaded/caffeine2/cache/BoundedLocalCache\$PerformCleanupTask.class")
|
||||
}
|
||||
|
||||
into("build/extracted/shadow")
|
||||
// prevents empty com/github/benmanes/caffeine/cache path from ending up in instrumentation-api
|
||||
includeEmptyDirs = false
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.github.benmanes.caffeine.cache;
|
||||
|
||||
// Caffeine uses reflection to load cache implementations based on parameters specified by a user.
|
||||
// We use gradle-shadow-plugin to minimize the dependency on Caffeine, but it does not allow
|
||||
// specifying classes to keep, only artifacts. It's a relatively simple workaround for us to use
|
||||
// this non-public class to create a static link to the required implementations we use.
|
||||
final class CacheImplementations {
|
||||
|
||||
// Each type of cache has a cache implementation and a node implementation.
|
||||
|
||||
// Strong keys, strong values, maximum size
|
||||
SSMS<?, ?> ssms; // cache
|
||||
PSMS<?, ?> psms; // node
|
||||
|
||||
// Weak keys, strong values, maximum size
|
||||
WSMS<?, ?> wsms; // cache
|
||||
FSMS<?, ?> fsms; // node
|
||||
|
||||
// Weak keys, weak values
|
||||
WI<?, ?> wi; // cache
|
||||
FW<?, ?> fw; // node
|
||||
|
||||
private CacheImplementations() {}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Includes work from:
|
||||
/*
|
||||
* Copyright 2017 Datadog, 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2014 Ben Manes. All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.opentelemetry.instrumentation.api.internal.shaded.caffeine2.cache;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/** skeleton outer class just for compilation purposes, not included in the final patch. */
|
||||
abstract class BoundedLocalCache<K, V> {
|
||||
abstract void performCleanUp(Runnable task);
|
||||
|
||||
/** patched to not extend ForkJoinTask as we don't want that class loaded too early. */
|
||||
static final class PerformCleanupTask implements Runnable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
final WeakReference<BoundedLocalCache<?, ?>> reference;
|
||||
|
||||
PerformCleanupTask(BoundedLocalCache<?, ?> cache) {
|
||||
reference = new WeakReference<>(cache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
BoundedLocalCache<?, ?> cache = reference.get();
|
||||
if (cache != null) {
|
||||
cache.performCleanUp(/* ignored */ null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
plugins {
|
||||
id("com.github.johnrengelman.shadow")
|
||||
|
||||
id("otel.java-conventions")
|
||||
}
|
||||
|
||||
group = "io.opentelemetry.javaagent"
|
||||
|
||||
val shadowInclude by configurations.creating {
|
||||
isCanBeResolved = true
|
||||
isCanBeConsumed = false
|
||||
}
|
||||
|
||||
val caffeine3Version: String by project
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.github.ben-manes.caffeine:caffeine:$caffeine3Version")
|
||||
shadowInclude("com.github.ben-manes.caffeine:caffeine:$caffeine3Version") {
|
||||
exclude("com.google.errorprone", "error_prone_annotations")
|
||||
exclude("org.checkerframework", "checker-qual")
|
||||
}
|
||||
}
|
||||
|
||||
// patch inner class from Caffeine to avoid ForkJoinTask from being loaded too early in the javaagent
|
||||
val patch by sourceSets.creating {
|
||||
java {}
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
configurations = listOf(shadowInclude)
|
||||
|
||||
relocate("com.github.benmanes.caffeine", "io.opentelemetry.instrumentation.api.internal.shaded.caffeine3")
|
||||
|
||||
minimize()
|
||||
}
|
||||
|
||||
javadoc {
|
||||
enabled = false
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.github.benmanes.caffeine.cache;
|
||||
|
||||
// Caffeine uses reflection to load cache implementations based on parameters specified by a user.
|
||||
// We use gradle-shadow-plugin to minimize the dependency on Caffeine, but it does not allow
|
||||
// specifying classes to keep, only artifacts. It's a relatively simple workaround for us to use
|
||||
// this non-public class to create a static link to the required implementations we use.
|
||||
final class CacheImplementations {
|
||||
|
||||
// Each type of cache has a cache implementation and a node implementation.
|
||||
|
||||
// Strong keys, strong values, maximum size
|
||||
SSMS<?, ?> ssms; // cache
|
||||
PSMS<?, ?> psms; // node
|
||||
|
||||
// Weak keys, strong values, maximum size
|
||||
WSMS<?, ?> wsms; // cache
|
||||
FSMS<?, ?> fsms; // node
|
||||
|
||||
// Weak keys, weak values
|
||||
WI<?, ?> wi; // cache
|
||||
FW<?, ?> fw; // node
|
||||
|
||||
private CacheImplementations() {}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Includes work from:
|
||||
/*
|
||||
* Copyright 2017 Datadog, 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2014 Ben Manes. All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.opentelemetry.instrumentation.api.internal.shaded.caffeine3.cache;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/** skeleton outer class just for compilation purposes, not included in the final patch. */
|
||||
abstract class BoundedLocalCache<K, V> {
|
||||
abstract void performCleanUp(Runnable task);
|
||||
|
||||
/** patched to not extend ForkJoinTask as we don't want that class loaded too early. */
|
||||
static final class PerformCleanupTask implements Runnable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
final WeakReference<BoundedLocalCache<?, ?>> reference;
|
||||
|
||||
PerformCleanupTask(BoundedLocalCache<?, ?> cache) {
|
||||
reference = new WeakReference<>(cache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
BoundedLocalCache<?, ?> cache = reference.get();
|
||||
if (cache != null) {
|
||||
cache.performCleanUp(/* ignored */ null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.caching;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** A builder of {@link Cache}. */
|
||||
public final class CacheBuilder {
|
||||
|
||||
private static final long UNSET = -1;
|
||||
private static final boolean USE_CAFFEINE_3 = Caffeine3Cache.available();
|
||||
|
||||
private boolean weakKeys;
|
||||
private boolean weakValues;
|
||||
private long maximumSize = UNSET;
|
||||
@Nullable private Executor executor = null;
|
||||
|
||||
/** Sets the maximum size of the cache. */
|
||||
public CacheBuilder setMaximumSize(long maximumSize) {
|
||||
this.maximumSize = maximumSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets that keys should be referenced weakly. If used, keys will use identity comparison, not
|
||||
* {@link Object#equals(Object)}.
|
||||
*/
|
||||
public CacheBuilder setWeakKeys() {
|
||||
this.weakKeys = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets that values should be referenced weakly. */
|
||||
public CacheBuilder setWeakValues() {
|
||||
this.weakValues = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
CacheBuilder setExecutor(Executor executor) {
|
||||
this.executor = executor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns a new {@link Cache} with the settings of this {@link CacheBuilder}. */
|
||||
public <K, V> Cache<K, V> build() {
|
||||
if (weakKeys && !weakValues && maximumSize == UNSET) {
|
||||
return new WeakLockFreeCache<>();
|
||||
}
|
||||
CaffeineCache.Builder<K, V> caffeine =
|
||||
USE_CAFFEINE_3 ? new Caffeine3Cache.Builder<>() : new Caffeine2Cache.Builder<>();
|
||||
if (weakKeys) {
|
||||
caffeine.weakKeys();
|
||||
}
|
||||
if (weakValues) {
|
||||
caffeine.weakValues();
|
||||
}
|
||||
if (maximumSize != UNSET) {
|
||||
caffeine.maximumSize(maximumSize);
|
||||
}
|
||||
if (executor != null) {
|
||||
caffeine.executor(executor);
|
||||
} else {
|
||||
caffeine.executor(Runnable::run);
|
||||
}
|
||||
return caffeine.build();
|
||||
}
|
||||
|
||||
CacheBuilder() {}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.caching;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.internal.shaded.caffeine2.cache.Caffeine;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
final class Caffeine2Cache<K, V> implements CaffeineCache<K, V> {
|
||||
|
||||
private final io.opentelemetry.instrumentation.api.internal.shaded.caffeine2.cache.Cache<K, V>
|
||||
delegate;
|
||||
|
||||
Caffeine2Cache(
|
||||
io.opentelemetry.instrumentation.api.internal.shaded.caffeine2.cache.Cache<K, V> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
||||
return delegate.get(key, mappingFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(K key) {
|
||||
return delegate.getIfPresent(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(K key, V value) {
|
||||
delegate.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(K key) {
|
||||
delegate.invalidate(key);
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return delegate.asMap().keySet();
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
@Override
|
||||
public void cleanup() {
|
||||
delegate.cleanUp();
|
||||
}
|
||||
|
||||
static class Builder<K, V> implements CaffeineCache.Builder<K, V> {
|
||||
private final Caffeine<?, ?> caffeine = Caffeine.newBuilder();
|
||||
|
||||
@Override
|
||||
public void weakKeys() {
|
||||
caffeine.weakKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void weakValues() {
|
||||
caffeine.weakValues();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maximumSize(@Nonnegative long maximumSize) {
|
||||
caffeine.maximumSize(maximumSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executor(@Nonnull Executor executor) {
|
||||
caffeine.executor(executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cache<K, V> build() {
|
||||
@SuppressWarnings("unchecked")
|
||||
io.opentelemetry.instrumentation.api.internal.shaded.caffeine2.cache.Cache<K, V> delegate =
|
||||
(io.opentelemetry.instrumentation.api.internal.shaded.caffeine2.cache.Cache<K, V>)
|
||||
caffeine.build();
|
||||
return new Caffeine2Cache<>(delegate);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.caching;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.internal.shaded.caffeine3.cache.Caffeine;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
final class Caffeine3Cache<K, V> implements CaffeineCache<K, V> {
|
||||
|
||||
private final io.opentelemetry.instrumentation.api.internal.shaded.caffeine3.cache.Cache<K, V>
|
||||
delegate;
|
||||
|
||||
Caffeine3Cache(
|
||||
io.opentelemetry.instrumentation.api.internal.shaded.caffeine3.cache.Cache<K, V> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public static boolean available() {
|
||||
try {
|
||||
Caffeine.class.getName();
|
||||
return true;
|
||||
} catch (UnsupportedClassVersionError | NoClassDefFoundError exception) {
|
||||
// caffeine 3 requires jdk 11
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
||||
return delegate.get(key, mappingFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(K key) {
|
||||
return delegate.getIfPresent(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(K key, V value) {
|
||||
delegate.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(K key) {
|
||||
delegate.invalidate(key);
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return delegate.asMap().keySet();
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
@Override
|
||||
public void cleanup() {
|
||||
delegate.cleanUp();
|
||||
}
|
||||
|
||||
static class Builder<K, V> implements CaffeineCache.Builder<K, V> {
|
||||
private final Caffeine<?, ?> caffeine = Caffeine.newBuilder();
|
||||
|
||||
@Override
|
||||
public void weakKeys() {
|
||||
caffeine.weakKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void weakValues() {
|
||||
caffeine.weakValues();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maximumSize(@Nonnegative long maximumSize) {
|
||||
caffeine.maximumSize(maximumSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executor(@Nonnull Executor executor) {
|
||||
caffeine.executor(executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cache<K, V> build() {
|
||||
@SuppressWarnings("unchecked")
|
||||
io.opentelemetry.instrumentation.api.internal.shaded.caffeine3.cache.Cache<K, V> delegate =
|
||||
(io.opentelemetry.instrumentation.api.internal.shaded.caffeine3.cache.Cache<K, V>)
|
||||
caffeine.build();
|
||||
return new Caffeine3Cache<>(delegate);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.caching;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
interface CaffeineCache<K, V> extends Cache<K, V> {
|
||||
|
||||
interface Builder<K, V> {
|
||||
|
||||
void weakKeys();
|
||||
|
||||
void weakValues();
|
||||
|
||||
void maximumSize(@Nonnegative long maximumSize);
|
||||
|
||||
void executor(@Nonnull Executor executor);
|
||||
|
||||
Cache<K, V> build();
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
Set<K> keySet();
|
||||
|
||||
// Visible for testing
|
||||
void cleanup();
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
Tests for this module are in the instrumentation-api project to verify against the shaded artifact.
|
|
@ -14,17 +14,12 @@ sourceSets {
|
|||
// set to generate into. By default it would be the src/main directory itself.
|
||||
srcDir("$buildDir/generated/sources/jflex")
|
||||
}
|
||||
|
||||
val cachingShadedDeps = project(":instrumentation-api-caching")
|
||||
output.dir(cachingShadedDeps.file("build/extracted/shadow"), "builtBy" to ":instrumentation-api-caching:extractShadowJar")
|
||||
}
|
||||
}
|
||||
|
||||
group = "io.opentelemetry.instrumentation"
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
|
||||
api("io.opentelemetry:opentelemetry-api")
|
||||
api("io.opentelemetry:opentelemetry-semconv")
|
||||
|
||||
|
@ -34,7 +29,6 @@ dependencies {
|
|||
compileOnly("com.google.auto.value:auto-value-annotations")
|
||||
annotationProcessor("com.google.auto.value:auto-value")
|
||||
|
||||
testCompileOnly(project(":instrumentation-api-caching"))
|
||||
testImplementation(project(":testing-common"))
|
||||
testImplementation("org.mockito:mockito-core")
|
||||
testImplementation("org.mockito:mockito-junit-jupiter")
|
||||
|
@ -45,6 +39,10 @@ dependencies {
|
|||
}
|
||||
|
||||
tasks {
|
||||
named<Checkstyle>("checkstyleMain") {
|
||||
exclude("**/concurrentlinkedhashmap/**")
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
dependsOn("generateJflex")
|
||||
}
|
||||
|
|
|
@ -3,17 +3,34 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.caching;
|
||||
package io.opentelemetry.instrumentation.api.cache;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** A cache from keys to values. */
|
||||
public interface Cache<K, V> {
|
||||
|
||||
/** Returns a new {@link CacheBuilder} to configure a {@link Cache}. */
|
||||
static CacheBuilder builder() {
|
||||
return new CacheBuilder();
|
||||
/**
|
||||
* Returns new unbounded cache
|
||||
*
|
||||
* <p>Keys are referenced weakly and compared using identity comparison, not {@link
|
||||
* Object#equals(Object)}.
|
||||
*/
|
||||
static <K, V> Cache<K, V> weak() {
|
||||
return new WeakLockFreeCache<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new bounded cache.
|
||||
*
|
||||
* <p>Both keys and values are strongly referenced.
|
||||
*/
|
||||
static <K, V> Cache<K, V> bounded(int capacity) {
|
||||
ConcurrentLinkedHashMap<K, V> map =
|
||||
new ConcurrentLinkedHashMap.Builder<K, V>().maximumWeightedCapacity(capacity).build();
|
||||
return new MapBackedCache<>(map);
|
||||
}
|
||||
|
||||
/**
|
45
instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/cache/MapBackedCache.java
vendored
Normal file
45
instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/cache/MapBackedCache.java
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.cache;
|
||||
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
final class MapBackedCache<K, V> implements Cache<K, V> {
|
||||
|
||||
private final ConcurrentMap<K, V> delegate;
|
||||
|
||||
MapBackedCache(ConcurrentMap<K, V> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
||||
return delegate.computeIfAbsent(key, mappingFunction);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public V get(K key) {
|
||||
return delegate.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(K key, V value) {
|
||||
delegate.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(K key) {
|
||||
delegate.remove(key);
|
||||
}
|
||||
|
||||
// Visible for tests
|
||||
int size() {
|
||||
return delegate.size();
|
||||
}
|
||||
}
|
|
@ -3,9 +3,9 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.caching;
|
||||
package io.opentelemetry.instrumentation.api.cache;
|
||||
|
||||
import com.blogspot.mydailyjava.weaklockfree.WeakConcurrentMap;
|
||||
import io.opentelemetry.instrumentation.api.cache.weaklockfree.WeakConcurrentMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
final class WeakLockFreeCache<K, V> implements Cache<K, V> {
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Includes work from:
|
||||
/*
|
||||
* Copyright 2012 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* A class that can determine the weight of an entry. The total weight threshold is used to
|
||||
* determine when an eviction is required.
|
||||
*
|
||||
* @author ben.manes@gmail.com (Ben Manes)
|
||||
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
|
||||
* http://code.google.com/p/concurrentlinkedhashmap/</a>
|
||||
*/
|
||||
@ThreadSafe
|
||||
public interface EntryWeigher<K, V> {
|
||||
|
||||
/**
|
||||
* Measures an entry's weight to determine how many units of capacity that the key and value
|
||||
* consumes. An entry must consume a minimum of one unit.
|
||||
*
|
||||
* @param key the key to weigh
|
||||
* @param value the value to weigh
|
||||
* @return the entry's weight
|
||||
*/
|
||||
int weightOf(K key, V value);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Includes work from:
|
||||
/*
|
||||
* Copyright 2010 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* A listener registered for notification when an entry is evicted. An instance may be called
|
||||
* concurrently by multiple threads to process entries. An implementation should avoid performing
|
||||
* blocking calls or synchronizing on shared resources.
|
||||
*
|
||||
* <p>The listener is invoked by {@link ConcurrentLinkedHashMap} on a caller's thread and will not
|
||||
* block other threads from operating on the map. An implementation should be aware that the
|
||||
* caller's thread will not expect long execution times or failures as a side effect of the listener
|
||||
* being notified. Execution safety and a fast turn around time can be achieved by performing the
|
||||
* operation asynchronously, such as by submitting a task to an {@link
|
||||
* java.util.concurrent.ExecutorService}.
|
||||
*
|
||||
* @author ben.manes@gmail.com (Ben Manes)
|
||||
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
|
||||
* http://code.google.com/p/concurrentlinkedhashmap/</a>
|
||||
*/
|
||||
@ThreadSafe
|
||||
public interface EvictionListener<K, V> {
|
||||
|
||||
/**
|
||||
* A call-back notification that the entry was evicted.
|
||||
*
|
||||
* @param key the entry's key
|
||||
* @param value the entry's value
|
||||
*/
|
||||
void onEviction(K key, V value);
|
||||
}
|
|
@ -0,0 +1,449 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Includes work from:
|
||||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap;
|
||||
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
/**
|
||||
* Linked list implementation of the {@link Deque} interface where the link pointers are tightly
|
||||
* integrated with the element. Linked deques have no capacity restrictions; they grow as necessary
|
||||
* to support usage. They are not thread-safe; in the absence of external synchronization, they do
|
||||
* not support concurrent access by multiple threads. Null elements are prohibited.
|
||||
*
|
||||
* <p>Most <tt>LinkedDeque</tt> operations run in constant time by assuming that the {@link Linked}
|
||||
* parameter is associated with the deque instance. Any usage that violates this assumption will
|
||||
* result in non-deterministic behavior.
|
||||
*
|
||||
* <p>The iterators returned by this class are <em>not</em> <i>fail-fast</i>: If the deque is
|
||||
* modified at any time after the iterator is created, the iterator will be in an unknown state.
|
||||
* Thus, in the face of concurrent modification, the iterator risks arbitrary, non-deterministic
|
||||
* behavior at an undetermined time in the future.
|
||||
*
|
||||
* @author ben.manes@gmail.com (Ben Manes)
|
||||
* @param <E> the type of elements held in this collection
|
||||
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
|
||||
* http://code.google.com/p/concurrentlinkedhashmap/</a>
|
||||
*/
|
||||
@NotThreadSafe
|
||||
final class LinkedDeque<E extends Linked<E>> extends AbstractCollection<E> implements Deque<E> {
|
||||
|
||||
// This class provides a doubly-linked list that is optimized for the virtual
|
||||
// machine. The first and last elements are manipulated instead of a slightly
|
||||
// more convenient sentinel element to avoid the insertion of null checks with
|
||||
// NullPointerException throws in the byte code. The links to a removed
|
||||
// element are cleared to help a generational garbage collector if the
|
||||
// discarded elements inhabit more than one generation.
|
||||
|
||||
/** Pointer to first node. Invariant: (first == null && last == null) || (first.prev == null) */
|
||||
E first;
|
||||
|
||||
/** Pointer to last node. Invariant: (first == null && last == null) || (last.next == null) */
|
||||
E last;
|
||||
|
||||
/**
|
||||
* Links the element to the front of the deque so that it becomes the first element.
|
||||
*
|
||||
* @param e the unlinked element
|
||||
*/
|
||||
void linkFirst(final E e) {
|
||||
final E f = first;
|
||||
first = e;
|
||||
|
||||
if (f == null) {
|
||||
last = e;
|
||||
} else {
|
||||
f.setPrevious(e);
|
||||
e.setNext(f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Links the element to the back of the deque so that it becomes the last element.
|
||||
*
|
||||
* @param e the unlinked element
|
||||
*/
|
||||
void linkLast(final E e) {
|
||||
final E l = last;
|
||||
last = e;
|
||||
|
||||
if (l == null) {
|
||||
first = e;
|
||||
} else {
|
||||
l.setNext(e);
|
||||
e.setPrevious(l);
|
||||
}
|
||||
}
|
||||
|
||||
/** Unlinks the non-null first element. */
|
||||
E unlinkFirst() {
|
||||
final E f = first;
|
||||
final E next = f.getNext();
|
||||
f.setNext(null);
|
||||
|
||||
first = next;
|
||||
if (next == null) {
|
||||
last = null;
|
||||
} else {
|
||||
next.setPrevious(null);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
/** Unlinks the non-null last element. */
|
||||
E unlinkLast() {
|
||||
final E l = last;
|
||||
final E prev = l.getPrevious();
|
||||
l.setPrevious(null);
|
||||
last = prev;
|
||||
if (prev == null) {
|
||||
first = null;
|
||||
} else {
|
||||
prev.setNext(null);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/** Unlinks the non-null element. */
|
||||
void unlink(E e) {
|
||||
final E prev = e.getPrevious();
|
||||
final E next = e.getNext();
|
||||
|
||||
if (prev == null) {
|
||||
first = next;
|
||||
} else {
|
||||
prev.setNext(next);
|
||||
e.setPrevious(null);
|
||||
}
|
||||
|
||||
if (next == null) {
|
||||
last = prev;
|
||||
} else {
|
||||
next.setPrevious(prev);
|
||||
e.setNext(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return (first == null);
|
||||
}
|
||||
|
||||
void checkNotEmpty() {
|
||||
if (isEmpty()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>Beware that, unlike in most collections, this method is <em>NOT</em> a constant-time
|
||||
* operation.
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
int size = 0;
|
||||
for (E e = first; e != null; e = e.getNext()) {
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
for (E e = first; e != null; ) {
|
||||
E next = e.getNext();
|
||||
e.setPrevious(null);
|
||||
e.setNext(null);
|
||||
e = next;
|
||||
}
|
||||
first = last = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return (o instanceof Linked<?>) && contains((Linked<?>) o);
|
||||
}
|
||||
|
||||
// A fast-path containment check
|
||||
boolean contains(Linked<?> e) {
|
||||
return (e.getPrevious() != null) || (e.getNext() != null) || (e == first);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the element to the front of the deque so that it becomes the first element.
|
||||
*
|
||||
* @param e the linked element
|
||||
*/
|
||||
public void moveToFront(E e) {
|
||||
if (e != first) {
|
||||
unlink(e);
|
||||
linkFirst(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the element to the back of the deque so that it becomes the last element.
|
||||
*
|
||||
* @param e the linked element
|
||||
*/
|
||||
public void moveToBack(E e) {
|
||||
if (e != last) {
|
||||
unlink(e);
|
||||
linkLast(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public E peek() {
|
||||
return peekFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E peekFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E peekLast() {
|
||||
return last;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getFirst() {
|
||||
checkNotEmpty();
|
||||
return peekFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getLast() {
|
||||
checkNotEmpty();
|
||||
return peekLast();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E element() {
|
||||
return getFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(E e) {
|
||||
return offerLast(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offerFirst(E e) {
|
||||
if (contains(e)) {
|
||||
return false;
|
||||
}
|
||||
linkFirst(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offerLast(E e) {
|
||||
if (contains(e)) {
|
||||
return false;
|
||||
}
|
||||
linkLast(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
return offerLast(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFirst(E e) {
|
||||
if (!offerFirst(e)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLast(E e) {
|
||||
if (!offerLast(e)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public E poll() {
|
||||
return pollFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E pollFirst() {
|
||||
return isEmpty() ? null : unlinkFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E pollLast() {
|
||||
return isEmpty() ? null : unlinkLast();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove() {
|
||||
return removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean remove(Object o) {
|
||||
return (o instanceof Linked<?>) && remove((E) o);
|
||||
}
|
||||
|
||||
// A fast-path removal
|
||||
boolean remove(E e) {
|
||||
if (contains(e)) {
|
||||
unlink(e);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E removeFirst() {
|
||||
checkNotEmpty();
|
||||
return pollFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFirstOccurrence(Object o) {
|
||||
return remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E removeLast() {
|
||||
checkNotEmpty();
|
||||
return pollLast();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeLastOccurrence(Object o) {
|
||||
return remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
boolean modified = false;
|
||||
for (Object o : c) {
|
||||
modified |= remove(o);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(E e) {
|
||||
addFirst(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E pop() {
|
||||
return removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new AbstractLinkedIterator(first) {
|
||||
@Override
|
||||
E computeNext() {
|
||||
return cursor.getNext();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> descendingIterator() {
|
||||
return new AbstractLinkedIterator(last) {
|
||||
@Override
|
||||
E computeNext() {
|
||||
return cursor.getPrevious();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
abstract class AbstractLinkedIterator implements Iterator<E> {
|
||||
E cursor;
|
||||
|
||||
/**
|
||||
* Creates an iterator that can can traverse the deque.
|
||||
*
|
||||
* @param start the initial element to begin traversal from
|
||||
*/
|
||||
AbstractLinkedIterator(E start) {
|
||||
cursor = start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return (cursor != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
E e = cursor;
|
||||
cursor = computeNext();
|
||||
return e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** Retrieves the next element to traverse to or <tt>null</tt> if there are no more elements. */
|
||||
abstract E computeNext();
|
||||
}
|
||||
}
|
||||
|
||||
/** An element that is linked on the {@link Deque}. */
|
||||
interface Linked<T extends Linked<T>> {
|
||||
|
||||
/**
|
||||
* Retrieves the previous element or <tt>null</tt> if either the element is unlinked or the first
|
||||
* element on the deque.
|
||||
*/
|
||||
T getPrevious();
|
||||
|
||||
/** Sets the previous element or <tt>null</tt> if there is no link. */
|
||||
void setPrevious(T prev);
|
||||
|
||||
/**
|
||||
* Retrieves the next element or <tt>null</tt> if either the element is unlinked or the last
|
||||
* element on the deque.
|
||||
*/
|
||||
T getNext();
|
||||
|
||||
/** Sets the next element or <tt>null</tt> if there is no link. */
|
||||
void setNext(T next);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Includes work from:
|
||||
/*
|
||||
* Copyright 2010 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* A class that can determine the weight of a value. The total weight threshold is used to determine
|
||||
* when an eviction is required.
|
||||
*
|
||||
* @author ben.manes@gmail.com (Ben Manes)
|
||||
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
|
||||
* http://code.google.com/p/concurrentlinkedhashmap/</a>
|
||||
*/
|
||||
@ThreadSafe
|
||||
public interface Weigher<V> {
|
||||
|
||||
/**
|
||||
* Measures an object's weight to determine how many units of capacity that the value consumes. A
|
||||
* value must consume a minimum of one unit.
|
||||
*
|
||||
* @param value the object to weigh
|
||||
* @return the object's weight
|
||||
*/
|
||||
int weightOf(V value);
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Includes work from:
|
||||
/*
|
||||
* Copyright 2010 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap;
|
||||
|
||||
import static io.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap.ConcurrentLinkedHashMap.checkNotNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A common set of {@link Weigher} and {@link EntryWeigher} implementations.
|
||||
*
|
||||
* @author ben.manes@gmail.com (Ben Manes)
|
||||
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
|
||||
* http://code.google.com/p/concurrentlinkedhashmap/</a>
|
||||
*/
|
||||
public final class Weighers {
|
||||
|
||||
private Weighers() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* A entry weigher backed by the specified weigher. The weight of the value determines the weight
|
||||
* of the entry.
|
||||
*
|
||||
* @param weigher the weigher to be "wrapped" in a entry weigher.
|
||||
* @return A entry weigher view of the specified weigher.
|
||||
*/
|
||||
public static <K, V> EntryWeigher<K, V> asEntryWeigher(final Weigher<? super V> weigher) {
|
||||
return (weigher == singleton())
|
||||
? Weighers.<K, V>entrySingleton()
|
||||
: new EntryWeigherView<>(weigher);
|
||||
}
|
||||
|
||||
/**
|
||||
* A weigher where an entry has a weight of <tt>1</tt>. A map bounded with this weigher will evict
|
||||
* when the number of key-value pairs exceeds the capacity.
|
||||
*
|
||||
* @return A weigher where a value takes one unit of capacity.
|
||||
*/
|
||||
@SuppressWarnings({"cast", "unchecked"})
|
||||
public static <K, V> EntryWeigher<K, V> entrySingleton() {
|
||||
return (EntryWeigher<K, V>) SingletonEntryWeigher.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A weigher where a value has a weight of <tt>1</tt>. A map bounded with this weigher will evict
|
||||
* when the number of key-value pairs exceeds the capacity.
|
||||
*
|
||||
* @return A weigher where a value takes one unit of capacity.
|
||||
*/
|
||||
@SuppressWarnings({"cast", "unchecked"})
|
||||
public static <V> Weigher<V> singleton() {
|
||||
return (Weigher<V>) SingletonWeigher.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A weigher where the value is a byte array and its weight is the number of bytes. A map bounded
|
||||
* with this weigher will evict when the number of bytes exceeds the capacity rather than the
|
||||
* number of key-value pairs in the map. This allows for restricting the capacity based on the
|
||||
* memory-consumption and is primarily for usage by dedicated caching servers that hold the
|
||||
* serialized data.
|
||||
*
|
||||
* <p>A value with a weight of <tt>0</tt> will be rejected by the map. If a value with this weight
|
||||
* can occur then the caller should eagerly evaluate the value and treat it as a removal
|
||||
* operation. Alternatively, a custom weigher may be specified on the map to assign an empty value
|
||||
* a positive weight.
|
||||
*
|
||||
* @return A weigher where each byte takes one unit of capacity.
|
||||
*/
|
||||
public static Weigher<byte[]> byteArray() {
|
||||
return ByteArrayWeigher.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A weigher where the value is a {@link Iterable} and its weight is the number of elements. This
|
||||
* weigher only should be used when the alternative {@link #collection()} weigher cannot be, as
|
||||
* evaluation takes O(n) time. A map bounded with this weigher will evict when the total number of
|
||||
* elements exceeds the capacity rather than the number of key-value pairs in the map.
|
||||
*
|
||||
* <p>A value with a weight of <tt>0</tt> will be rejected by the map. If a value with this weight
|
||||
* can occur then the caller should eagerly evaluate the value and treat it as a removal
|
||||
* operation. Alternatively, a custom weigher may be specified on the map to assign an empty value
|
||||
* a positive weight.
|
||||
*
|
||||
* @return A weigher where each element takes one unit of capacity.
|
||||
*/
|
||||
@SuppressWarnings({"cast", "unchecked"})
|
||||
public static <E> Weigher<? super Iterable<E>> iterable() {
|
||||
return (Weigher<Iterable<E>>) (Weigher<?>) IterableWeigher.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A weigher where the value is a {@link Collection} and its weight is the number of elements. A
|
||||
* map bounded with this weigher will evict when the total number of elements exceeds the capacity
|
||||
* rather than the number of key-value pairs in the map.
|
||||
*
|
||||
* <p>A value with a weight of <tt>0</tt> will be rejected by the map. If a value with this weight
|
||||
* can occur then the caller should eagerly evaluate the value and treat it as a removal
|
||||
* operation. Alternatively, a custom weigher may be specified on the map to assign an empty value
|
||||
* a positive weight.
|
||||
*
|
||||
* @return A weigher where each element takes one unit of capacity.
|
||||
*/
|
||||
@SuppressWarnings({"cast", "unchecked"})
|
||||
public static <E> Weigher<? super Collection<E>> collection() {
|
||||
return (Weigher<Collection<E>>) (Weigher<?>) CollectionWeigher.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A weigher where the value is a {@link List} and its weight is the number of elements. A map
|
||||
* bounded with this weigher will evict when the total number of elements exceeds the capacity
|
||||
* rather than the number of key-value pairs in the map.
|
||||
*
|
||||
* <p>A value with a weight of <tt>0</tt> will be rejected by the map. If a value with this weight
|
||||
* can occur then the caller should eagerly evaluate the value and treat it as a removal
|
||||
* operation. Alternatively, a custom weigher may be specified on the map to assign an empty value
|
||||
* a positive weight.
|
||||
*
|
||||
* @return A weigher where each element takes one unit of capacity.
|
||||
*/
|
||||
@SuppressWarnings({"cast", "unchecked"})
|
||||
public static <E> Weigher<? super List<E>> list() {
|
||||
return (Weigher<List<E>>) (Weigher<?>) ListWeigher.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A weigher where the value is a {@link Set} and its weight is the number of elements. A map
|
||||
* bounded with this weigher will evict when the total number of elements exceeds the capacity
|
||||
* rather than the number of key-value pairs in the map.
|
||||
*
|
||||
* <p>A value with a weight of <tt>0</tt> will be rejected by the map. If a value with this weight
|
||||
* can occur then the caller should eagerly evaluate the value and treat it as a removal
|
||||
* operation. Alternatively, a custom weigher may be specified on the map to assign an empty value
|
||||
* a positive weight.
|
||||
*
|
||||
* @return A weigher where each element takes one unit of capacity.
|
||||
*/
|
||||
@SuppressWarnings({"cast", "unchecked"})
|
||||
public static <E> Weigher<? super Set<E>> set() {
|
||||
return (Weigher<Set<E>>) (Weigher<?>) SetWeigher.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A weigher where the value is a {@link Map} and its weight is the number of entries. A map
|
||||
* bounded with this weigher will evict when the total number of entries across all values exceeds
|
||||
* the capacity rather than the number of key-value pairs in the map.
|
||||
*
|
||||
* <p>A value with a weight of <tt>0</tt> will be rejected by the map. If a value with this weight
|
||||
* can occur then the caller should eagerly evaluate the value and treat it as a removal
|
||||
* operation. Alternatively, a custom weigher may be specified on the map to assign an empty value
|
||||
* a positive weight.
|
||||
*
|
||||
* @return A weigher where each entry takes one unit of capacity.
|
||||
*/
|
||||
@SuppressWarnings({"cast", "unchecked"})
|
||||
public static <A, B> Weigher<? super Map<A, B>> map() {
|
||||
return (Weigher<Map<A, B>>) (Weigher<?>) MapWeigher.INSTANCE;
|
||||
}
|
||||
|
||||
static final class EntryWeigherView<K, V> implements EntryWeigher<K, V>, Serializable {
|
||||
static final long serialVersionUID = 1;
|
||||
final Weigher<? super V> weigher;
|
||||
|
||||
EntryWeigherView(Weigher<? super V> weigher) {
|
||||
checkNotNull(weigher);
|
||||
this.weigher = weigher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int weightOf(K key, V value) {
|
||||
return weigher.weightOf(value);
|
||||
}
|
||||
}
|
||||
|
||||
enum SingletonEntryWeigher implements EntryWeigher<Object, Object> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int weightOf(Object key, Object value) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
enum SingletonWeigher implements Weigher<Object> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int weightOf(Object value) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
enum ByteArrayWeigher implements Weigher<byte[]> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int weightOf(byte[] value) {
|
||||
return value.length;
|
||||
}
|
||||
}
|
||||
|
||||
enum IterableWeigher implements Weigher<Iterable<?>> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int weightOf(Iterable<?> values) {
|
||||
if (values instanceof Collection<?>) {
|
||||
return ((Collection<?>) values).size();
|
||||
}
|
||||
int size = 0;
|
||||
for (Iterator<?> i = values.iterator(); i.hasNext(); ) {
|
||||
i.next();
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
enum CollectionWeigher implements Weigher<Collection<?>> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int weightOf(Collection<?> values) {
|
||||
return values.size();
|
||||
}
|
||||
}
|
||||
|
||||
enum ListWeigher implements Weigher<List<?>> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int weightOf(List<?> values) {
|
||||
return values.size();
|
||||
}
|
||||
}
|
||||
|
||||
enum SetWeigher implements Weigher<Set<?>> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int weightOf(Set<?> values) {
|
||||
return values.size();
|
||||
}
|
||||
}
|
||||
|
||||
enum MapWeigher implements Weigher<Map<?, ?>> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int weightOf(Map<?, ?> values) {
|
||||
return values.size();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTICE file from https://github.com/ben-manes/concurrentlinkedhashmap/blob/master/NOTICE:
|
||||
*
|
||||
* ConcurrentLinkedHashMap
|
||||
* Copyright 2008, Ben Manes
|
||||
* Copyright 2010, Google Inc.
|
||||
*
|
||||
* Some alternate data structures provided by JSR-166e
|
||||
* from http://gee.cs.oswego.edu/dl/concurrency-interest/.
|
||||
* Written by Doug Lea and released as Public Domain.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contains an implementation of a bounded {@link java.util.concurrent.ConcurrentMap}
|
||||
* data structure.
|
||||
*
|
||||
* <p>{@link io.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap.Weigher} is a simple
|
||||
* interface for determining how many units of capacity an entry consumes. Depending on which
|
||||
* concrete Weigher class is used, an entry may consume a different amount of space within the
|
||||
* cache. The {@link io.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap.Weighers}
|
||||
* class provides utility methods for obtaining the most common kinds of implementations.
|
||||
*
|
||||
* <p>{@link io.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap.EvictionListener}
|
||||
* provides the ability to be notified when an entry is evicted from the map. An eviction occurs
|
||||
* when the entry was automatically removed due to the map exceeding a capacity threshold. It is not
|
||||
* called when an entry was explicitly removed.
|
||||
*
|
||||
* <p>The {@link
|
||||
* io.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap.ConcurrentLinkedHashMap} class
|
||||
* supplies an efficient, scalable, thread-safe, bounded map. As with the <tt>Java Collections
|
||||
* Framework</tt> the "Concurrent" prefix is used to indicate that the map is not governed by a
|
||||
* single exclusion lock.
|
||||
*
|
||||
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
|
||||
* http://code.google.com/p/concurrentlinkedhashmap/</a>
|
||||
*/
|
||||
package io.opentelemetry.instrumentation.api.cache.concurrentlinkedhashmap;
|
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Includes work from:
|
||||
/*
|
||||
* Copyright Rafael Winterhalter
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
// Suppress warnings since this is vendored as-is.
|
||||
// CHECKSTYLE:OFF
|
||||
|
||||
package io.opentelemetry.instrumentation.api.cache.weaklockfree;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* A thread-safe map with weak keys. Entries are based on a key's system hash code and keys are
|
||||
* considered equal only by reference equality. This class offers an abstract-base implementation
|
||||
* that allows to override methods. This class does not implement the {@link Map} interface because
|
||||
* this implementation is incompatible with the map contract. While iterating over a map's entries,
|
||||
* any key that has not passed iteration is referenced non-weakly.
|
||||
*
|
||||
* <p>This class has been copied as is from
|
||||
* https://github.com/raphw/weak-lock-free/blob/ad0e5e0c04d4a31f9485bf12b89afbc9d75473b3/src/main/java/com/blogspot/mydailyjava/weaklockfree/WeakConcurrentMap.java
|
||||
*/
|
||||
// Suppress warnings since this is vendored as-is.
|
||||
@SuppressWarnings({"MissingSummary", "EqualsBrokenForNull", "FieldMissingNullable"})
|
||||
abstract class AbstractWeakConcurrentMap<K, V, L> extends ReferenceQueue<K>
|
||||
implements Runnable, Iterable<Map.Entry<K, V>> {
|
||||
|
||||
final ConcurrentMap<WeakKey<K>, V> target;
|
||||
|
||||
protected AbstractWeakConcurrentMap() {
|
||||
this(new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
/** @param target ConcurrentMap implementation that this class wraps. */
|
||||
protected AbstractWeakConcurrentMap(ConcurrentMap<WeakKey<K>, V> target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override with care as it can cause lookup failures if done incorrectly. The result must have
|
||||
* the same {@link Object#hashCode()} as the input and be {@link Object#equals(Object) equal to} a
|
||||
* weak reference of the key. When overriding this, also override {@link #resetLookupKey}.
|
||||
*/
|
||||
protected abstract L getLookupKey(K key);
|
||||
|
||||
/** Resets any reusable state in the {@linkplain #getLookupKey lookup key}. */
|
||||
protected abstract void resetLookupKey(L lookupKey);
|
||||
|
||||
/**
|
||||
* @param key The key of the entry.
|
||||
* @return The value of the entry or the default value if it did not exist.
|
||||
*/
|
||||
public V get(K key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
V value;
|
||||
L lookupKey = getLookupKey(key);
|
||||
try {
|
||||
value = target.get(lookupKey);
|
||||
} finally {
|
||||
resetLookupKey(lookupKey);
|
||||
}
|
||||
if (value == null) {
|
||||
value = defaultValue(key);
|
||||
if (value != null) {
|
||||
V previousValue = target.putIfAbsent(new WeakKey<>(key, this), value);
|
||||
if (previousValue != null) {
|
||||
value = previousValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key The key of the entry.
|
||||
* @return The value of the entry or null if it did not exist.
|
||||
*/
|
||||
public V getIfPresent(K key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
L lookupKey = getLookupKey(key);
|
||||
try {
|
||||
return target.get(lookupKey);
|
||||
} finally {
|
||||
resetLookupKey(lookupKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key The key of the entry.
|
||||
* @return {@code true} if the key already defines a value.
|
||||
*/
|
||||
public boolean containsKey(K key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
L lookupKey = getLookupKey(key);
|
||||
try {
|
||||
return target.containsKey(lookupKey);
|
||||
} finally {
|
||||
resetLookupKey(lookupKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key The key of the entry.
|
||||
* @param value The value of the entry.
|
||||
* @return The previous entry or {@code null} if it does not exist.
|
||||
*/
|
||||
public V put(K key, V value) {
|
||||
if (key == null || value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return target.put(new WeakKey<>(key, this), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key The key of the entry.
|
||||
* @param value The value of the entry.
|
||||
* @return The previous entry or {@code null} if it does not exist.
|
||||
*/
|
||||
public V putIfAbsent(K key, V value) {
|
||||
if (key == null || value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
V previous;
|
||||
L lookupKey = getLookupKey(key);
|
||||
try {
|
||||
previous = target.get(lookupKey);
|
||||
} finally {
|
||||
resetLookupKey(lookupKey);
|
||||
}
|
||||
return previous == null ? target.putIfAbsent(new WeakKey<>(key, this), value) : previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key The key of the entry.
|
||||
* @param value The value of the entry.
|
||||
* @return The previous entry or {@code null} if it does not exist.
|
||||
*/
|
||||
public V putIfProbablyAbsent(K key, V value) {
|
||||
if (key == null || value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return target.putIfAbsent(new WeakKey<>(key, this), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key The key of the entry.
|
||||
* @return The removed entry or {@code null} if it does not exist.
|
||||
*/
|
||||
public V remove(K key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
L lookupKey = getLookupKey(key);
|
||||
try {
|
||||
return target.remove(lookupKey);
|
||||
} finally {
|
||||
resetLookupKey(lookupKey);
|
||||
}
|
||||
}
|
||||
|
||||
/** Clears the entire map. */
|
||||
public void clear() {
|
||||
target.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a default value. There is no guarantee that the requested value will be set as a once
|
||||
* it is created in case that another thread requests a value for a key concurrently.
|
||||
*
|
||||
* @param key The key for which to create a default value.
|
||||
* @return The default value for a key without value or {@code null} for not defining a default
|
||||
* value.
|
||||
*/
|
||||
protected V defaultValue(K key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Cleans all unused references. */
|
||||
public void expungeStaleEntries() {
|
||||
Reference<?> reference;
|
||||
while ((reference = poll()) != null) {
|
||||
target.remove(reference);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the approximate size of this map where the returned number is at least as big as the
|
||||
* actual number of entries.
|
||||
*
|
||||
* @return The minimum size of this map.
|
||||
*/
|
||||
public int approximateSize() {
|
||||
return target.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
target.remove(remove());
|
||||
}
|
||||
} catch (InterruptedException ignored) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Map.Entry<K, V>> iterator() {
|
||||
return new EntryIterator(target.entrySet().iterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return target.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Why this works:
|
||||
* ---------------
|
||||
*
|
||||
* Note that this map only supports reference equality for keys and uses system hash codes. Also, for the
|
||||
* WeakKey instances to function correctly, we are voluntarily breaking the Java API contract for
|
||||
* hashCode/equals of these instances.
|
||||
*
|
||||
* System hash codes are immutable and can therefore be computed prematurely and are stored explicitly
|
||||
* within the WeakKey instances. This way, we always know the correct hash code of a key and always
|
||||
* end up in the correct bucket of our target map. This remains true even after the weakly referenced
|
||||
* key is collected.
|
||||
*
|
||||
* If we are looking up the value of the current key via WeakConcurrentMap::get or any other public
|
||||
* API method, we know that any value associated with this key must still be in the map as the mere
|
||||
* existence of this key makes it ineligible for garbage collection. Therefore, looking up a value
|
||||
* using another WeakKey wrapper guarantees a correct result.
|
||||
*
|
||||
* If we are looking up the map entry of a WeakKey after polling it from the reference queue, we know
|
||||
* that the actual key was already collected and calling WeakKey::get returns null for both the polled
|
||||
* instance and the instance within the map. Since we explicitly stored the identity hash code for the
|
||||
* referenced value, it is however trivial to identify the correct bucket. From this bucket, the first
|
||||
* weak key with a null reference is removed. Due to hash collision, we do not know if this entry
|
||||
* represents the weak key. However, we do know that the reference queue polls at least as many weak
|
||||
* keys as there are stale map entries within the target map. If no key is ever removed from the map
|
||||
* explicitly, the reference queue eventually polls exactly as many weak keys as there are stale entries.
|
||||
*
|
||||
* Therefore, we can guarantee that there is no memory leak.
|
||||
*
|
||||
* It is the responsibility of the actual map implementation to implement a lookup key that is used for
|
||||
* lookups. The lookup key must supply the same semantics as the weak key with regards to hash code.
|
||||
* The weak key invokes the latent key's equality method upon evaluation.
|
||||
*/
|
||||
|
||||
public static final class WeakKey<K> extends WeakReference<K> {
|
||||
|
||||
private final int hashCode;
|
||||
|
||||
WeakKey(K key, ReferenceQueue<? super K> queue) {
|
||||
super(key, queue);
|
||||
hashCode = System.identityHashCode(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof WeakKey<?>) {
|
||||
return ((WeakKey<?>) other).get() == get();
|
||||
} else {
|
||||
return other.equals(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(get());
|
||||
}
|
||||
}
|
||||
|
||||
private class EntryIterator implements Iterator<Map.Entry<K, V>> {
|
||||
|
||||
private final Iterator<Map.Entry<WeakKey<K>, V>> iterator;
|
||||
|
||||
private Map.Entry<WeakKey<K>, V> nextEntry;
|
||||
|
||||
private K nextKey;
|
||||
|
||||
private EntryIterator(Iterator<Map.Entry<WeakKey<K>, V>> iterator) {
|
||||
this.iterator = iterator;
|
||||
findNext();
|
||||
}
|
||||
|
||||
private void findNext() {
|
||||
while (iterator.hasNext()) {
|
||||
nextEntry = iterator.next();
|
||||
nextKey = nextEntry.getKey().get();
|
||||
if (nextKey != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
nextEntry = null;
|
||||
nextKey = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return nextKey != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map.Entry<K, V> next() {
|
||||
if (nextKey == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
try {
|
||||
return new SimpleEntry(nextKey, nextEntry);
|
||||
} finally {
|
||||
findNext();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
private class SimpleEntry implements Map.Entry<K, V> {
|
||||
|
||||
private final K key;
|
||||
|
||||
final Map.Entry<WeakKey<K>, V> entry;
|
||||
|
||||
private SimpleEntry(K key, Map.Entry<WeakKey<K>, V> entry) {
|
||||
this.key = key;
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V getValue() {
|
||||
return entry.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V setValue(V value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return entry.setValue(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Includes work from:
|
||||
/*
|
||||
* Copyright Rafael Winterhalter
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
// Suppress warnings since this is vendored as-is.
|
||||
// CHECKSTYLE:OFF
|
||||
|
||||
package io.opentelemetry.instrumentation.api.cache.weaklockfree;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* A thread-safe map with weak keys. Entries are based on a key's system hash code and keys are
|
||||
* considered equal only by reference equality. This class does not implement the {@link
|
||||
* java.util.Map} interface because this implementation is incompatible with the map contract. While
|
||||
* iterating over a map's entries, any key that has not passed iteration is referenced non-weakly.
|
||||
*
|
||||
* <p>This class has been copied as is from
|
||||
* https://github.com/raphw/weak-lock-free/blob/ad0e5e0c04d4a31f9485bf12b89afbc9d75473b3/src/main/java/com/blogspot/mydailyjava/weaklockfree/WeakConcurrentMap.java
|
||||
*/
|
||||
// Suppress warnings since this is copied as-is.
|
||||
@SuppressWarnings({
|
||||
"HashCodeToString",
|
||||
"MissingSummary",
|
||||
"UngroupedOverloads",
|
||||
"ThreadPriorityCheck",
|
||||
"FieldMissingNullable"
|
||||
})
|
||||
public class WeakConcurrentMap<K, V>
|
||||
extends AbstractWeakConcurrentMap<K, V, WeakConcurrentMap.LookupKey<K>> {
|
||||
|
||||
/**
|
||||
* Lookup keys are cached thread-locally to avoid allocations on lookups. This is beneficial as
|
||||
* the JIT unfortunately can't reliably replace the {@link LookupKey} allocation with stack
|
||||
* allocations, even though the {@link LookupKey} does not escape.
|
||||
*/
|
||||
private static final ThreadLocal<LookupKey<?>> LOOKUP_KEY_CACHE =
|
||||
new ThreadLocal<LookupKey<?>>() {
|
||||
@Override
|
||||
protected LookupKey<?> initialValue() {
|
||||
return new LookupKey<>();
|
||||
}
|
||||
};
|
||||
|
||||
private static final AtomicLong ID = new AtomicLong();
|
||||
|
||||
private final Thread thread;
|
||||
|
||||
private final boolean reuseKeys;
|
||||
|
||||
/** @param cleanerThread {@code true} if a thread should be started that removes stale entries. */
|
||||
public WeakConcurrentMap(boolean cleanerThread) {
|
||||
this(cleanerThread, isPersistentClassLoader(LookupKey.class.getClassLoader()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the provided {@link ClassLoader} may be unloaded like a web application class
|
||||
* loader, for example.
|
||||
*
|
||||
* <p>If the class loader can't be unloaded, it is safe to use {@link ThreadLocal}s and to reuse
|
||||
* the {@link LookupKey}. Otherwise, the use of {@link ThreadLocal}s may lead to class loader
|
||||
* leaks as it prevents the class loader this class is loaded by to unload.
|
||||
*
|
||||
* @param classLoader The class loader to check.
|
||||
* @return {@code true} if the provided class loader can be unloaded.
|
||||
*/
|
||||
private static boolean isPersistentClassLoader(ClassLoader classLoader) {
|
||||
try {
|
||||
return classLoader == null // bootstrap class loader
|
||||
|| classLoader == ClassLoader.getSystemClassLoader()
|
||||
|| classLoader
|
||||
== ClassLoader.getSystemClassLoader().getParent(); // ext/platfrom class loader;
|
||||
} catch (Throwable ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cleanerThread {@code true} if a thread should be started that removes stale entries.
|
||||
* @param reuseKeys {@code true} if the lookup keys should be reused via a {@link ThreadLocal}.
|
||||
* Note that setting this to {@code true} may result in class loader leaks. See {@link
|
||||
* #isPersistentClassLoader(ClassLoader)} for more details.
|
||||
*/
|
||||
public WeakConcurrentMap(boolean cleanerThread, boolean reuseKeys) {
|
||||
this(cleanerThread, reuseKeys, new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cleanerThread {@code true} if a thread should be started that removes stale entries.
|
||||
* @param reuseKeys {@code true} if the lookup keys should be reused via a {@link ThreadLocal}.
|
||||
* Note that setting this to {@code true} may result in class loader leaks. See {@link
|
||||
* #isPersistentClassLoader(ClassLoader)} for more details.
|
||||
* @param target ConcurrentMap implementation that this class wraps.
|
||||
*/
|
||||
public WeakConcurrentMap(
|
||||
boolean cleanerThread, boolean reuseKeys, ConcurrentMap<WeakKey<K>, V> target) {
|
||||
super(target);
|
||||
this.reuseKeys = reuseKeys;
|
||||
if (cleanerThread) {
|
||||
thread = new Thread(this);
|
||||
thread.setName("weak-ref-cleaner-" + ID.getAndIncrement());
|
||||
thread.setPriority(Thread.MIN_PRIORITY);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
} else {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected LookupKey<K> getLookupKey(K key) {
|
||||
LookupKey<K> lookupKey;
|
||||
if (reuseKeys) {
|
||||
lookupKey = (LookupKey<K>) LOOKUP_KEY_CACHE.get();
|
||||
} else {
|
||||
lookupKey = new LookupKey<>();
|
||||
}
|
||||
return lookupKey.withValue(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetLookupKey(LookupKey<K> lookupKey) {
|
||||
lookupKey.reset();
|
||||
}
|
||||
|
||||
/** @return The cleaner thread or {@code null} if no such thread was set. */
|
||||
public Thread getCleanerThread() {
|
||||
return thread;
|
||||
}
|
||||
|
||||
/*
|
||||
* A lookup key must only be used for looking up instances within a map. For this to work, it implements an identical contract for
|
||||
* hash code and equals as the WeakKey implementation. At the same time, the lookup key implementation does not extend WeakReference
|
||||
* and avoids the overhead that a weak reference implies.
|
||||
*/
|
||||
|
||||
// can't use AutoClosable/try-with-resources as this project still supports Java 6
|
||||
static final class LookupKey<K> {
|
||||
|
||||
private K key;
|
||||
private int hashCode;
|
||||
|
||||
LookupKey<K> withValue(K key) {
|
||||
this.key = key;
|
||||
hashCode = System.identityHashCode(key);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Failing to reset a lookup key can lead to memory leaks as the key is strongly referenced. */
|
||||
void reset() {
|
||||
key = null;
|
||||
hashCode = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof WeakConcurrentMap.LookupKey<?>) {
|
||||
return ((LookupKey<?>) other).key == key;
|
||||
} else {
|
||||
return ((WeakKey<?>) other).get() == key;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link WeakConcurrentMap} where stale entries are removed as a side effect of interacting
|
||||
* with this map.
|
||||
*/
|
||||
public static class WithInlinedExpunction<K, V> extends WeakConcurrentMap<K, V> {
|
||||
|
||||
public WithInlinedExpunction() {
|
||||
super(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(K key) {
|
||||
expungeStaleEntries();
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(K key) {
|
||||
expungeStaleEntries();
|
||||
return super.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
expungeStaleEntries();
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(K key) {
|
||||
expungeStaleEntries();
|
||||
return super.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Map.Entry<K, V>> iterator() {
|
||||
expungeStaleEntries();
|
||||
return super.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int approximateSize() {
|
||||
expungeStaleEntries();
|
||||
return super.approximateSize();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ import static io.opentelemetry.instrumentation.api.db.StatementSanitizationConfi
|
|||
import static io.opentelemetry.instrumentation.api.internal.SupportabilityMetrics.CounterNames.SQL_STATEMENT_SANITIZER_CACHE_MISS;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.instrumentation.api.internal.SupportabilityMetrics;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -21,7 +21,7 @@ public final class SqlStatementSanitizer {
|
|||
private static final SupportabilityMetrics supportability = SupportabilityMetrics.instance();
|
||||
|
||||
private static final Cache<CacheKey, SqlStatementInfo> sqlToStatementInfoCache =
|
||||
Cache.builder().setMaximumSize(1000).build();
|
||||
Cache.bounded(1000);
|
||||
|
||||
public static SqlStatementInfo sanitize(@Nullable String statement) {
|
||||
return sanitize(statement, SqlDialect.DEFAULT);
|
||||
|
|
|
@ -6,15 +6,19 @@
|
|||
package io.opentelemetry.instrumentation.api.instrumenter.http;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
final class HttpHeaderAttributes {
|
||||
|
||||
private static final Cache<String, AttributeKey<List<String>>> requestKeysCache =
|
||||
Cache.builder().setMaximumSize(32).build();
|
||||
private static final Cache<String, AttributeKey<List<String>>> responseKeysCache =
|
||||
Cache.builder().setMaximumSize(32).build();
|
||||
// these are naturally bounded because they only store keys listed in
|
||||
// otel.instrumentation.http.capture-headers.server.request and
|
||||
// otel.instrumentation.http.capture-headers.server.response
|
||||
private static final ConcurrentMap<String, AttributeKey<List<String>>> requestKeysCache =
|
||||
new ConcurrentHashMap<>();
|
||||
private static final ConcurrentMap<String, AttributeKey<List<String>>> responseKeysCache =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
static AttributeKey<List<String>> requestAttributeKey(String headerName) {
|
||||
return requestKeysCache.computeIfAbsent(headerName, n -> createKey("request", n));
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package io.opentelemetry.instrumentation.api.internal;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.instrumentation.api.field.VirtualField;
|
||||
import javax.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -40,19 +40,19 @@ public final class RuntimeVirtualFieldSupplier {
|
|||
private static final class CacheBasedVirtualFieldSupplier implements VirtualFieldSupplier {
|
||||
|
||||
private final Cache<Class<?>, Cache<Class<?>, VirtualField<?, ?>>>
|
||||
ownerToFieldToImplementationMap = Cache.builder().setWeakKeys().build();
|
||||
ownerToFieldToImplementationMap = Cache.weak();
|
||||
|
||||
@Override
|
||||
public <U extends T, T, F> VirtualField<U, F> find(Class<T> type, Class<F> fieldType) {
|
||||
return (VirtualField<U, F>)
|
||||
ownerToFieldToImplementationMap
|
||||
.computeIfAbsent(type, c -> Cache.builder().setWeakKeys().build())
|
||||
.computeIfAbsent(type, c -> Cache.weak())
|
||||
.computeIfAbsent(fieldType, c -> new CacheBasedVirtualField<>());
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CacheBasedVirtualField<T, F> extends VirtualField<T, F> {
|
||||
private final Cache<T, F> cache = Cache.builder().setWeakKeys().build();
|
||||
private final Cache<T, F> cache = Cache.weak();
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
|
||||
package io.opentelemetry.instrumentation.api.tracer;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
|
||||
public final class ClassNames {
|
||||
|
||||
private static final Cache<Class<?>, String> simpleNames = Cache.builder().setWeakKeys().build();
|
||||
private static final Cache<Class<?>, String> simpleNames = Cache.weak();
|
||||
|
||||
/**
|
||||
* This method is used to generate a simple name based on a given class reference, e.g. for use in
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package io.opentelemetry.instrumentation.api.tracer;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.instrumentation.api.util.ClassAndMethod;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
@ -14,8 +14,7 @@ import javax.annotation.Nullable;
|
|||
|
||||
public final class SpanNames {
|
||||
|
||||
private static final Cache<Class<?>, Map<String, String>> spanNameCaches =
|
||||
Cache.builder().setWeakKeys().build();
|
||||
private static final Cache<Class<?>, Map<String, String>> spanNameCaches = Cache.weak();
|
||||
|
||||
/**
|
||||
* This method is used to generate a span name based on a method. Anonymous classes are named
|
||||
|
|
78
instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/cache/CacheTest.java
vendored
Normal file
78
instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/cache/CacheTest.java
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.cache;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class CacheTest {
|
||||
|
||||
@Nested
|
||||
@SuppressWarnings("ClassCanBeStatic")
|
||||
class StrongKeys {
|
||||
@Test
|
||||
void bounded() {
|
||||
Cache<String, String> cache = Cache.bounded(1);
|
||||
|
||||
assertThat(cache.computeIfAbsent("bear", unused -> "roar")).isEqualTo("roar");
|
||||
cache.remove("bear");
|
||||
|
||||
MapBackedCache<?, ?> mapBackedCache = ((MapBackedCache<?, ?>) cache);
|
||||
assertThat(cache.computeIfAbsent("cat", unused -> "meow")).isEqualTo("meow");
|
||||
assertThat(mapBackedCache.size()).isEqualTo(1);
|
||||
|
||||
assertThat(cache.computeIfAbsent("cat", unused -> "bark")).isEqualTo("meow");
|
||||
assertThat(mapBackedCache.size()).isEqualTo(1);
|
||||
|
||||
cache.put("dog", "bark");
|
||||
assertThat(cache.get("dog")).isEqualTo("bark");
|
||||
assertThat(mapBackedCache.size()).isEqualTo(1);
|
||||
assertThat(cache.computeIfAbsent("cat", unused -> "purr")).isEqualTo("purr");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@SuppressWarnings("ClassCanBeStatic")
|
||||
class WeakKeys {
|
||||
@SuppressWarnings("StringOperationCanBeSimplified")
|
||||
@Test
|
||||
void unbounded() {
|
||||
Cache<String, String> cache = Cache.weak();
|
||||
|
||||
assertThat(cache.computeIfAbsent("bear", unused -> "roar")).isEqualTo("roar");
|
||||
cache.remove("bear");
|
||||
|
||||
WeakLockFreeCache<?, ?> weakLockFreeCache = ((WeakLockFreeCache<?, ?>) cache);
|
||||
String cat = new String("cat");
|
||||
String dog = new String("dog");
|
||||
assertThat(cache.computeIfAbsent(cat, unused -> "meow")).isEqualTo("meow");
|
||||
assertThat(weakLockFreeCache.size()).isEqualTo(1);
|
||||
|
||||
assertThat(cache.computeIfAbsent(cat, unused -> "bark")).isEqualTo("meow");
|
||||
assertThat(weakLockFreeCache.size()).isEqualTo(1);
|
||||
|
||||
cache.put(dog, "bark");
|
||||
assertThat(cache.get(dog)).isEqualTo("bark");
|
||||
assertThat(cache.get(cat)).isEqualTo("meow");
|
||||
assertThat(cache.get(new String("dog"))).isNull();
|
||||
assertThat(weakLockFreeCache.size()).isEqualTo(2);
|
||||
assertThat(cache.computeIfAbsent(cat, unused -> "meow")).isEqualTo("meow");
|
||||
|
||||
cat = null;
|
||||
System.gc();
|
||||
// Wait for GC to be reflected.
|
||||
await().untilAsserted(() -> assertThat(weakLockFreeCache.size()).isEqualTo(1));
|
||||
assertThat(cache.computeIfAbsent(dog, unused -> "bark")).isEqualTo("bark");
|
||||
dog = null;
|
||||
System.gc();
|
||||
// Wait for GC to be reflected.
|
||||
await().untilAsserted(() -> assertThat(weakLockFreeCache.size()).isEqualTo(0));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.caching;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class CacheTest {
|
||||
|
||||
@Nested
|
||||
@SuppressWarnings("ClassCanBeStatic")
|
||||
class StrongKeys {
|
||||
@Test
|
||||
void unbounded() {
|
||||
Cache<String, String> cache = Cache.builder().build();
|
||||
|
||||
assertThat(cache.computeIfAbsent("bear", unused -> "roar")).isEqualTo("roar");
|
||||
cache.remove("bear");
|
||||
|
||||
CaffeineCache<?, ?> caffeineCache = ((CaffeineCache<?, ?>) cache);
|
||||
assertThat(cache.computeIfAbsent("cat", unused -> "meow")).isEqualTo("meow");
|
||||
assertThat(caffeineCache.keySet()).hasSize(1);
|
||||
|
||||
assertThat(cache.computeIfAbsent("cat", unused -> "bark")).isEqualTo("meow");
|
||||
assertThat(caffeineCache.keySet()).hasSize(1);
|
||||
|
||||
cache.put("dog", "bark");
|
||||
assertThat(cache.get("dog")).isEqualTo("bark");
|
||||
assertThat(cache.get("cat")).isEqualTo("meow");
|
||||
assertThat(cache.get("bear")).isNull();
|
||||
assertThat(caffeineCache.keySet()).hasSize(2);
|
||||
assertThat(cache.computeIfAbsent("cat", unused -> "meow")).isEqualTo("meow");
|
||||
}
|
||||
|
||||
@Test
|
||||
void bounded() {
|
||||
Cache<String, String> cache = Cache.builder().setMaximumSize(1).build();
|
||||
|
||||
assertThat(cache.computeIfAbsent("bear", unused -> "roar")).isEqualTo("roar");
|
||||
cache.remove("bear");
|
||||
|
||||
CaffeineCache<?, ?> caffeineCache = ((CaffeineCache<?, ?>) cache);
|
||||
assertThat(cache.computeIfAbsent("cat", unused -> "meow")).isEqualTo("meow");
|
||||
assertThat(caffeineCache.keySet()).hasSize(1);
|
||||
|
||||
assertThat(cache.computeIfAbsent("cat", unused -> "bark")).isEqualTo("meow");
|
||||
assertThat(caffeineCache.keySet()).hasSize(1);
|
||||
|
||||
cache.put("dog", "bark");
|
||||
assertThat(cache.get("dog")).isEqualTo("bark");
|
||||
caffeineCache.cleanup();
|
||||
assertThat(caffeineCache.keySet()).hasSize(1);
|
||||
assertThat(cache.computeIfAbsent("cat", unused -> "purr")).isEqualTo("purr");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@SuppressWarnings("ClassCanBeStatic")
|
||||
class WeakKeys {
|
||||
@Test
|
||||
void unbounded() {
|
||||
Cache<String, String> cache = Cache.builder().setWeakKeys().build();
|
||||
|
||||
assertThat(cache.computeIfAbsent("bear", unused -> "roar")).isEqualTo("roar");
|
||||
cache.remove("bear");
|
||||
|
||||
WeakLockFreeCache<?, ?> weakLockFreeCache = ((WeakLockFreeCache<?, ?>) cache);
|
||||
String cat = new String("cat");
|
||||
String dog = new String("dog");
|
||||
assertThat(cache.computeIfAbsent(cat, unused -> "meow")).isEqualTo("meow");
|
||||
assertThat(weakLockFreeCache.size()).isEqualTo(1);
|
||||
|
||||
assertThat(cache.computeIfAbsent(cat, unused -> "bark")).isEqualTo("meow");
|
||||
assertThat(weakLockFreeCache.size()).isEqualTo(1);
|
||||
|
||||
cache.put(dog, "bark");
|
||||
assertThat(cache.get(dog)).isEqualTo("bark");
|
||||
assertThat(cache.get(cat)).isEqualTo("meow");
|
||||
assertThat(cache.get(new String("dog"))).isNull();
|
||||
assertThat(weakLockFreeCache.size()).isEqualTo(2);
|
||||
assertThat(cache.computeIfAbsent(cat, unused -> "meow")).isEqualTo("meow");
|
||||
|
||||
cat = null;
|
||||
System.gc();
|
||||
// Wait for GC to be reflected.
|
||||
await().untilAsserted(() -> assertThat(weakLockFreeCache.size()).isEqualTo(1));
|
||||
assertThat(cache.computeIfAbsent(dog, unused -> "bark")).isEqualTo("bark");
|
||||
dog = null;
|
||||
System.gc();
|
||||
// Wait for GC to be reflected.
|
||||
await().untilAsserted(() -> assertThat(weakLockFreeCache.size()).isEqualTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void bounded() {
|
||||
Cache<String, String> cache = Cache.builder().setWeakKeys().setMaximumSize(1).build();
|
||||
|
||||
assertThat(cache.computeIfAbsent("bear", unused -> "roar")).isEqualTo("roar");
|
||||
cache.remove("bear");
|
||||
|
||||
CaffeineCache<?, ?> caffeineCache = ((CaffeineCache<?, ?>) cache);
|
||||
|
||||
String cat = new String("cat");
|
||||
String dog = new String("dog");
|
||||
assertThat(cache.computeIfAbsent(cat, unused -> "meow")).isEqualTo("meow");
|
||||
assertThat(cache.get(cat)).isEqualTo("meow");
|
||||
assertThat(cache.get(new String("cat"))).isNull();
|
||||
assertThat(caffeineCache.keySet()).hasSize(1);
|
||||
|
||||
assertThat(cache.computeIfAbsent(cat, unused -> "bark")).isEqualTo("meow");
|
||||
assertThat(caffeineCache.keySet()).hasSize(1);
|
||||
|
||||
cache.put(dog, "bark");
|
||||
assertThat(cache.get(dog)).isEqualTo("bark");
|
||||
assertThat(cache.get(new String("dog"))).isNull();
|
||||
caffeineCache.cleanup();
|
||||
assertThat(caffeineCache.keySet()).hasSize(1);
|
||||
dog = null;
|
||||
System.gc();
|
||||
// Wait for GC to be reflected.
|
||||
await()
|
||||
.untilAsserted(
|
||||
() -> {
|
||||
caffeineCache.cleanup();
|
||||
assertThat(caffeineCache.keySet()).isEmpty();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.caching;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class PatchCaffeineTest {
|
||||
|
||||
@Test
|
||||
void cleanupNotForkJoinTask() {
|
||||
AtomicReference<AssertionError> errorRef = new AtomicReference<>();
|
||||
Cache<String, String> cache =
|
||||
Cache.builder()
|
||||
.setExecutor(
|
||||
task -> {
|
||||
try {
|
||||
assertThat(task).isNotInstanceOf(ForkJoinTask.class);
|
||||
} catch (AssertionError e) {
|
||||
errorRef.set(e);
|
||||
}
|
||||
})
|
||||
.setMaximumSize(1)
|
||||
.build();
|
||||
assertThat(cache.computeIfAbsent("cat", unused -> "meow")).isEqualTo("meow");
|
||||
assertThat(cache.computeIfAbsent("dog", unused -> "bark")).isEqualTo("bark");
|
||||
AssertionError error = errorRef.get();
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,20 +11,25 @@ import io.netty.util.concurrent.GenericProgressiveFutureListener;
|
|||
import io.netty.util.concurrent.ProgressiveFuture;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public final class FutureListenerWrappers {
|
||||
// Instead of VirtualField use Cache with weak keys and weak values to store link between original
|
||||
// listener and wrapper. VirtualField works fine when wrapper is stored in a field on original
|
||||
// listener, but when listener class is a lambda instead of field it gets stored in a map with
|
||||
// weak keys where original listener is key and wrapper is value. As wrapper has a strong
|
||||
// reference to original listener this causes a memory leak.
|
||||
// Also note that it's ok if the value is collected prior to the key, since this cache is only
|
||||
// used to remove the wrapped listener from the netty future, and if the value is collected prior
|
||||
// to the key, that means it's no longer used (referenced) by the netty future anyways.
|
||||
// note: it's ok if the value is collected prior to the key, since this cache is only used to
|
||||
// remove the wrapped listener from the netty future, and if the value is collected prior to the
|
||||
// key, that means it's no longer used (referenced) by the netty future anyways.
|
||||
//
|
||||
// also note: this is not using VirtualField in case this is ever converted to library
|
||||
// instrumentation, because while the library implementation of VirtualField maintains a weak
|
||||
// reference to its keys, it maintains a strong reference to its values, and in this particular
|
||||
// case the wrapper listener (value) has a strong reference to original listener (key), which will
|
||||
// create a memory leak. which is not a problem in the javaagent's implementation of VirtualField,
|
||||
// since it injects the value directly into the key as a field, and so the value is only retained
|
||||
// strongly by the key, and so they can be collected together.
|
||||
private static final Cache<
|
||||
GenericFutureListener<? extends Future<?>>, GenericFutureListener<? extends Future<?>>>
|
||||
wrappers = Cache.builder().setWeakKeys().setWeakValues().build();
|
||||
GenericFutureListener<? extends Future<?>>,
|
||||
WeakReference<GenericFutureListener<? extends Future<?>>>>
|
||||
wrappers = Cache.weak();
|
||||
|
||||
private static final ClassValue<Boolean> shouldWrap =
|
||||
new ClassValue<Boolean>() {
|
||||
|
@ -44,21 +49,44 @@ public final class FutureListenerWrappers {
|
|||
@SuppressWarnings("unchecked")
|
||||
public static GenericFutureListener<?> wrap(
|
||||
Context context, GenericFutureListener<? extends Future<?>> delegate) {
|
||||
return wrappers.computeIfAbsent(
|
||||
delegate,
|
||||
key -> {
|
||||
if (delegate instanceof GenericProgressiveFutureListener) {
|
||||
return new WrappedProgressiveFutureListener(
|
||||
context, (GenericProgressiveFutureListener<ProgressiveFuture<?>>) delegate);
|
||||
} else {
|
||||
return new WrappedFutureListener(context, (GenericFutureListener<Future<?>>) delegate);
|
||||
}
|
||||
});
|
||||
|
||||
// note: not using computeIfAbsent because that leaves window where WeakReference can be
|
||||
// collected before we have a chance to make (and return) a strong reference to the wrapper
|
||||
|
||||
WeakReference<GenericFutureListener<? extends Future<?>>> resultReference =
|
||||
wrappers.get(delegate);
|
||||
|
||||
if (resultReference != null) {
|
||||
GenericFutureListener<? extends Future<?>> wrapper = resultReference.get();
|
||||
if (wrapper != null) {
|
||||
return wrapper;
|
||||
}
|
||||
// note that it's ok if the value is collected prior to the key, since this cache is only
|
||||
// used to remove the wrapped listener from the netty future, and if the value is collected
|
||||
// prior
|
||||
// to the key, that means it's no longer used (referenced) by the netty future anyways.
|
||||
}
|
||||
|
||||
final GenericFutureListener<? extends Future<?>> wrapper;
|
||||
if (delegate instanceof GenericProgressiveFutureListener) {
|
||||
wrapper =
|
||||
new WrappedProgressiveFutureListener(
|
||||
context, (GenericProgressiveFutureListener<ProgressiveFuture<?>>) delegate);
|
||||
} else {
|
||||
wrapper = new WrappedFutureListener(context, (GenericFutureListener<Future<?>>) delegate);
|
||||
}
|
||||
wrappers.put(delegate, new WeakReference<>(wrapper));
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
public static GenericFutureListener<? extends Future<?>> getWrapper(
|
||||
GenericFutureListener<? extends Future<?>> delegate) {
|
||||
GenericFutureListener<? extends Future<?>> wrapper = wrappers.get(delegate);
|
||||
WeakReference<GenericFutureListener<? extends Future<?>>> wrapperReference =
|
||||
wrappers.get(delegate);
|
||||
if (wrapperReference == null) {
|
||||
return delegate;
|
||||
}
|
||||
GenericFutureListener<? extends Future<?>> wrapper = wrapperReference.get();
|
||||
return wrapper == null ? delegate : wrapper;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,10 +49,6 @@ dependencies {
|
|||
testImplementation("io.opentelemetry:opentelemetry-exporter-otlp")
|
||||
testImplementation("io.opentelemetry:opentelemetry-exporter-zipkin")
|
||||
testImplementation(project(":instrumentation-api-annotation-support"))
|
||||
|
||||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our
|
||||
// inclusion of this artifact inside of :instrumentation-api
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
}
|
||||
|
||||
tasks.compileTestJava {
|
||||
|
|
|
@ -12,8 +12,4 @@ dependencies {
|
|||
testImplementation(project(":testing-common"))
|
||||
testImplementation("org.mockito:mockito-core")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
|
||||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our
|
||||
// inclusion of this artifact inside of :instrumentation-api
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package io.opentelemetry.javaagent.bootstrap;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
@ -17,8 +17,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
*/
|
||||
public final class HelperResources {
|
||||
|
||||
private static final Cache<ClassLoader, Map<String, URL>> RESOURCES =
|
||||
Cache.builder().setWeakKeys().build();
|
||||
private static final Cache<ClassLoader, Map<String, URL>> RESOURCES = Cache.weak();
|
||||
|
||||
/** Registers the {@code payload} to be available to instrumentation at {@code path}. */
|
||||
public static void register(ClassLoader classLoader, String path, URL url) {
|
||||
|
|
|
@ -16,8 +16,4 @@ dependencies {
|
|||
|
||||
// metrics are unstable, do not expose as api
|
||||
implementation("io.opentelemetry:opentelemetry-sdk-metrics")
|
||||
|
||||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our
|
||||
// inclusion of this artifact inside of :instrumentation-api
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package io.opentelemetry.javaagent.extension;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.instrumentation.api.config.Config;
|
||||
import io.opentelemetry.instrumentation.api.field.VirtualField;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
|
|
|
@ -5,15 +5,14 @@
|
|||
|
||||
package io.opentelemetry.javaagent.extension.matcher;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.internal.ClassLoaderMatcherCacheHolder;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.internal.InClassLoaderMatcher;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
class ClassLoaderHasClassesNamedMatcher extends ElementMatcher.Junction.AbstractBase<ClassLoader> {
|
||||
|
||||
private final Cache<ClassLoader, Boolean> cache =
|
||||
Cache.builder().setWeakKeys().setMaximumSize(25).build();
|
||||
private final Cache<ClassLoader, Boolean> cache = Cache.weak();
|
||||
|
||||
private final String[] resources;
|
||||
|
||||
|
|
|
@ -19,8 +19,4 @@ dependencies {
|
|||
testImplementation("org.mockito:mockito-core")
|
||||
testImplementation("org.mockito:mockito-junit-jupiter")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
|
||||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our
|
||||
// inclusion of this artifact inside of :instrumentation-api
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.api.internal;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.instrumentation.api.internal.GuardedBy;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
|
|
@ -40,10 +40,6 @@ dependencies {
|
|||
testImplementation("org.assertj:assertj-core")
|
||||
testImplementation("org.mockito:mockito-core")
|
||||
testImplementation("org.mockito:mockito-junit-jupiter")
|
||||
|
||||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our
|
||||
// inclusion of this artifact inside of :instrumentation-api
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
}
|
||||
|
||||
// Here we only include autoconfigure but don"t include OTLP exporters to ensure they are only in
|
||||
|
|
|
@ -38,8 +38,6 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -86,15 +84,6 @@ public class AgentInstaller {
|
|||
// internal-proxy instrumentation module after the bytebuddy transformer is set up
|
||||
Proxy.class.getName();
|
||||
|
||||
// caffeine can trigger first access of ForkJoinPool under transform(), which leads ForkJoinPool
|
||||
// not to get transformed itself.
|
||||
// loading it early here still allows it to be retransformed as part of agent installation below
|
||||
ForkJoinPool.class.getName();
|
||||
|
||||
// caffeine uses AtomicReferenceArray, ensure it is loaded to avoid ClassCircularityError during
|
||||
// transform.
|
||||
AtomicReferenceArray.class.getName();
|
||||
|
||||
Integer strictContextStressorMillis = Integer.getInteger(STRICT_CONTEXT_STRESSOR_MILLIS);
|
||||
if (strictContextStressorMillis != null) {
|
||||
io.opentelemetry.context.ContextStorage.addWrapper(
|
||||
|
|
|
@ -9,7 +9,7 @@ import static io.opentelemetry.javaagent.tooling.field.GeneratedVirtualFieldName
|
|||
import static io.opentelemetry.javaagent.tooling.field.GeneratedVirtualFieldNames.getRealSetterName;
|
||||
import static io.opentelemetry.javaagent.tooling.field.GeneratedVirtualFieldNames.getVirtualFieldImplementationClassName;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.instrumentation.api.field.VirtualField;
|
||||
import io.opentelemetry.javaagent.tooling.Utils;
|
||||
import io.opentelemetry.javaagent.tooling.muzzle.VirtualFieldMappings;
|
||||
|
@ -264,7 +264,7 @@ final class VirtualFieldImplementationsGenerator {
|
|||
@SuppressWarnings({"UnusedMethod", "UnusedVariable", "MethodCanBeStatic"})
|
||||
static final class VirtualFieldImplementationTemplate extends VirtualField<Object, Object> {
|
||||
private static final VirtualFieldImplementationTemplate INSTANCE =
|
||||
new VirtualFieldImplementationTemplate(Cache.builder().setWeakKeys().build());
|
||||
new VirtualFieldImplementationTemplate(Cache.weak());
|
||||
|
||||
private final Cache<Object, Object> map;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package io.opentelemetry.javaagent.tooling.ignore;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.javaagent.bootstrap.PatchLogger;
|
||||
import io.opentelemetry.javaagent.tooling.util.Trie;
|
||||
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
|
||||
|
@ -17,8 +17,7 @@ public class IgnoredClassLoadersMatcher extends ElementMatcher.Junction.Abstract
|
|||
private static final Logger logger = LoggerFactory.getLogger(IgnoredClassLoadersMatcher.class);
|
||||
|
||||
/* Cache of classloader-instance -> (true|false). True = skip instrumentation. False = safe to instrument. */
|
||||
private static final Cache<ClassLoader, Boolean> skipCache =
|
||||
Cache.builder().setWeakKeys().build();
|
||||
private static final Cache<ClassLoader, Boolean> skipCache = Cache.weak();
|
||||
|
||||
private final Trie<IgnoreAllow> ignoredClassLoaders;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
|
|||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.tooling.HelperInjector;
|
||||
|
@ -125,7 +125,7 @@ public final class InstrumentationModuleInstaller {
|
|||
private static class MuzzleMatcher implements AgentBuilder.RawMatcher {
|
||||
private final InstrumentationModule instrumentationModule;
|
||||
private final AtomicBoolean initialized = new AtomicBoolean(false);
|
||||
private final Cache<ClassLoader, Boolean> matchCache = Cache.builder().setWeakKeys().build();
|
||||
private final Cache<ClassLoader, Boolean> matchCache = Cache.weak();
|
||||
private volatile ReferenceMatcher referenceMatcher;
|
||||
|
||||
private MuzzleMatcher(InstrumentationModule instrumentationModule) {
|
||||
|
|
|
@ -55,12 +55,9 @@ val licenseReportDependencies by configurations.creating {
|
|||
extendsFrom(bootstrapLibs)
|
||||
}
|
||||
|
||||
val caffeine3Version: String by project
|
||||
|
||||
dependencies {
|
||||
bootstrapLibs(project(":instrumentation-api"))
|
||||
bootstrapLibs(project(":instrumentation-api-annotation-support"))
|
||||
bootstrapLibs(project(":instrumentation-api-caching:caffeine3", configuration = "shadow"))
|
||||
bootstrapLibs(project(":javaagent-bootstrap"))
|
||||
bootstrapLibs(project(":javaagent-instrumentation-api"))
|
||||
bootstrapLibs("org.slf4j:slf4j-simple")
|
||||
|
@ -84,11 +81,9 @@ dependencies {
|
|||
exporterSlimLibs("io.opentelemetry:opentelemetry-exporter-otlp")
|
||||
exporterSlimLibs("io.opentelemetry:opentelemetry-exporter-otlp-metrics")
|
||||
|
||||
// We only have compileOnly dependencies on these to make sure they don't leak into POMs.
|
||||
licenseReportDependencies("com.github.ben-manes.caffeine:caffeine:$caffeine3Version") {
|
||||
isTransitive = false
|
||||
}
|
||||
licenseReportDependencies("com.blogspot.mydailyjava:weak-lock-free")
|
||||
// concurrentlinkedhashmap-lru and weak-lock-free are copied in to the instrumentation-api module
|
||||
licenseReportDependencies("com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2")
|
||||
licenseReportDependencies("com.blogspot.mydailyjava:weak-lock-free:0.18")
|
||||
// TODO ideally this would be :instrumentation instead of :javaagent-tooling
|
||||
// in case there are dependencies (accidentally) pulled in by instrumentation modules
|
||||
// but I couldn't get that to work
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Jackson JSON processor
|
||||
|
||||
Jackson is a high-performance, Free/Open Source JSON processing library.
|
||||
It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
|
||||
been in development since 2007.
|
||||
It is currently developed by a community of developers.
|
||||
|
||||
## Licensing
|
||||
|
||||
Jackson 2.x core and extension components are licensed under Apache License 2.0
|
||||
To find the details that apply to this artifact see the accompanying LICENSE file.
|
||||
|
||||
## Credits
|
||||
|
||||
A list of contributors may be found from CREDITS(-2.x) file, which is included
|
||||
in some artifacts (usually source distributions); but is always available
|
||||
from the source code management (SCM) system project uses.
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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
|
||||
|
||||
http://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.
|
|
@ -0,0 +1,17 @@
|
|||
# Jackson JSON processor
|
||||
|
||||
Jackson is a high-performance, Free/Open Source JSON processing library.
|
||||
It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
|
||||
been in development since 2007.
|
||||
It is currently developed by a community of developers.
|
||||
|
||||
## Licensing
|
||||
|
||||
Jackson 2.x core and extension components are licensed under Apache License 2.0
|
||||
To find the details that apply to this artifact see the accompanying LICENSE file.
|
||||
|
||||
## Credits
|
||||
|
||||
A list of contributors may be found from CREDITS(-2.x) file, which is included
|
||||
in some artifacts (usually source distributions); but is always available
|
||||
from the source code management (SCM) system project uses.
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
#javaagent
|
||||
##Dependency License Report
|
||||
_2021-11-09 12:26:05 EET_
|
||||
_2021-11-23 20:07:26 PST_
|
||||
## Apache License, Version 2.0
|
||||
|
||||
**1** **Group:** `com.blogspot.mydailyjava` **Name:** `weak-lock-free` **Version:** `0.18`
|
||||
|
@ -14,133 +14,130 @@ _2021-11-09 12:26:05 EET_
|
|||
> - **POM Project URL**: [https://github.com/raphw/weak-lock-free](https://github.com/raphw/weak-lock-free)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**3** **Group:** `com.github.ben-manes.caffeine` **Name:** `caffeine` **Version:** `3.0.4`
|
||||
**3** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-annotations` **Version:** `2.12.3`
|
||||
> - **Project URL**: [http://github.com/FasterXML/jackson](http://github.com/FasterXML/jackson)
|
||||
> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)
|
||||
> - **POM Project URL**: [https://github.com/ben-manes/caffeine](https://github.com/ben-manes/caffeine)
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **Embedded license files**: [caffeine-3.0.4.jar/META-INF/LICENSE](caffeine-3.0.4.jar/META-INF/LICENSE)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **Embedded license files**: [jackson-annotations-2.12.3.jar/META-INF/LICENSE](jackson-annotations-2.12.3.jar/META-INF/LICENSE)
|
||||
|
||||
**4** **Group:** `com.github.ben-manes.caffeine` **Name:** `caffeine` **Version:** `3.0.4`
|
||||
**4** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-annotations` **Version:** `2.12.3`
|
||||
> - **Project URL**: [http://github.com/FasterXML/jackson](http://github.com/FasterXML/jackson)
|
||||
> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)
|
||||
> - **POM Project URL**: [https://github.com/ben-manes/caffeine](https://github.com/ben-manes/caffeine)
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **Embedded license files**: [caffeine-3.0.4.jar/META-INF/LICENSE](caffeine-3.0.4.jar/META-INF/LICENSE)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **Embedded license files**: [jackson-annotations-2.12.3.jar/META-INF/LICENSE](jackson-annotations-2.12.3.jar/META-INF/LICENSE)
|
||||
|
||||
**5** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api` **Version:** `1.7.1`
|
||||
**5** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-core` **Version:** `2.12.3`
|
||||
> - **Project URL**: [https://github.com/FasterXML/jackson-core](https://github.com/FasterXML/jackson-core)
|
||||
> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **Embedded license files**: [jackson-core-2.12.3.jar/META-INF/LICENSE](jackson-core-2.12.3.jar/META-INF/LICENSE)
|
||||
- [jackson-core-2.12.3.jar/META-INF/NOTICE](jackson-core-2.12.3.jar/META-INF/NOTICE)
|
||||
|
||||
**6** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-core` **Version:** `2.12.3`
|
||||
> - **Project URL**: [https://github.com/FasterXML/jackson-core](https://github.com/FasterXML/jackson-core)
|
||||
> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **Embedded license files**: [jackson-core-2.12.3.jar/META-INF/LICENSE](jackson-core-2.12.3.jar/META-INF/LICENSE)
|
||||
- [jackson-core-2.12.3.jar/META-INF/NOTICE](jackson-core-2.12.3.jar/META-INF/NOTICE)
|
||||
|
||||
**7** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-databind` **Version:** `2.12.3`
|
||||
> - **Project URL**: [http://github.com/FasterXML/jackson](http://github.com/FasterXML/jackson)
|
||||
> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **Embedded license files**: [jackson-databind-2.12.3.jar/META-INF/LICENSE](jackson-databind-2.12.3.jar/META-INF/LICENSE)
|
||||
- [jackson-databind-2.12.3.jar/META-INF/NOTICE](jackson-databind-2.12.3.jar/META-INF/NOTICE)
|
||||
|
||||
**8** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-databind` **Version:** `2.12.3`
|
||||
> - **Project URL**: [http://github.com/FasterXML/jackson](http://github.com/FasterXML/jackson)
|
||||
> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **Embedded license files**: [jackson-databind-2.12.3.jar/META-INF/LICENSE](jackson-databind-2.12.3.jar/META-INF/LICENSE)
|
||||
- [jackson-databind-2.12.3.jar/META-INF/NOTICE](jackson-databind-2.12.3.jar/META-INF/NOTICE)
|
||||
|
||||
**9** **Group:** `com.googlecode.concurrentlinkedhashmap` **Name:** `concurrentlinkedhashmap-lru` **Version:** `1.4.2`
|
||||
> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)
|
||||
> - **POM Project URL**: [http://code.google.com/p/concurrentlinkedhashmap](http://code.google.com/p/concurrentlinkedhashmap)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**10** **Group:** `com.googlecode.concurrentlinkedhashmap` **Name:** `concurrentlinkedhashmap-lru` **Version:** `1.4.2`
|
||||
> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)
|
||||
> - **POM Project URL**: [http://code.google.com/p/concurrentlinkedhashmap](http://code.google.com/p/concurrentlinkedhashmap)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**11** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**6** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api-metrics` **Version:** `1.7.1-alpha`
|
||||
**12** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api-metrics` **Version:** `1.9.0-alpha`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**7** **Group:** `io.opentelemetry` **Name:** `opentelemetry-context` **Version:** `1.7.1`
|
||||
**13** **Group:** `io.opentelemetry` **Name:** `opentelemetry-context` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**8** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-logging` **Version:** `1.7.1`
|
||||
**14** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-logging` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**9** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-aws` **Version:** `1.7.1`
|
||||
**15** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-aws` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**10** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-kotlin` **Version:** `1.7.1`
|
||||
**16** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-kotlin` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**11** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-noop-api` **Version:** `1.7.1-alpha`
|
||||
**17** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-noop-api` **Version:** `1.9.0-alpha`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**12** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-trace-propagators` **Version:** `1.7.1`
|
||||
**18** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-trace-propagators` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**13** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk` **Version:** `1.7.1`
|
||||
**19** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**14** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-common` **Version:** `1.7.1`
|
||||
**20** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-common` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**15** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-autoconfigure` **Version:** `1.7.1-alpha`
|
||||
**21** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-autoconfigure` **Version:** `1.9.0-alpha`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**16** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-autoconfigure-spi` **Version:** `1.7.1`
|
||||
**22** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-autoconfigure-spi` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**17** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-resources` **Version:** `1.7.1`
|
||||
**23** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-resources` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**18** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-metrics` **Version:** `1.7.1-alpha`
|
||||
**24** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-logs` **Version:** `1.9.0-alpha`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**19** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-trace` **Version:** `1.7.1`
|
||||
**25** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-metrics` **Version:** `1.9.0-alpha`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**20** **Group:** `io.opentelemetry` **Name:** `opentelemetry-semconv` **Version:** `1.7.1-alpha`
|
||||
**26** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-trace` **Version:** `1.9.0`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**27** **Group:** `io.opentelemetry` **Name:** `opentelemetry-semconv` **Version:** `1.9.0-alpha`
|
||||
> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
**21** **Group:** `net.bytebuddy` **Name:** `byte-buddy-dep` **Version:** `1.11.22`
|
||||
**28** **Group:** `net.bytebuddy` **Name:** `byte-buddy-dep` **Version:** `1.11.22`
|
||||
> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **Embedded license files**: [byte-buddy-dep-1.11.22.jar/META-INF/LICENSE](byte-buddy-dep-1.11.22.jar/META-INF/LICENSE)
|
||||
- [byte-buddy-dep-1.11.22.jar/META-INF/NOTICE](byte-buddy-dep-1.11.22.jar/META-INF/NOTICE)
|
||||
|
||||
**22** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.2`
|
||||
> - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org)
|
||||
> - **Manifest License**: The 3-Clause BSD License (Not Packaged)
|
||||
> - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
|
||||
|
||||
**23** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.2`
|
||||
> - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org)
|
||||
> - **Manifest License**: The 3-Clause BSD License (Not Packaged)
|
||||
> - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
|
||||
|
||||
## Embedded
|
||||
|
||||
**24** **Group:** `opentelemetry-java-instrumentation.instrumentation-api-caching` **Name:** `caffeine3` **Version:** `1.8.0-alpha-SNAPSHOT`
|
||||
> - **Embedded license files**: [opentelemetry-caffeine3-1.8.0-alpha-SNAPSHOT-all.jar/META-INF/LICENSE](opentelemetry-caffeine3-1.8.0-alpha-SNAPSHOT-all.jar/META-INF/LICENSE)
|
||||
|
||||
## MIT License
|
||||
|
||||
**25** **Group:** `org.slf4j` **Name:** `slf4j-api` **Version:** `1.7.30`
|
||||
> - **POM Project URL**: [http://www.slf4j.org](http://www.slf4j.org)
|
||||
> - **POM License**: MIT License - [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)
|
||||
|
||||
**26** **Group:** `org.slf4j` **Name:** `slf4j-simple` **Version:** `1.7.30`
|
||||
> - **POM Project URL**: [http://www.slf4j.org](http://www.slf4j.org)
|
||||
> - **POM License**: MIT License - [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)
|
||||
|
||||
## The 3-Clause BSD License
|
||||
|
||||
**27** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.2`
|
||||
> - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org)
|
||||
> - **Manifest License**: The 3-Clause BSD License (Not Packaged)
|
||||
> - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
|
||||
|
||||
**28** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.2`
|
||||
> - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org)
|
||||
> - **Manifest License**: The 3-Clause BSD License (Not Packaged)
|
||||
> - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
|
||||
|
||||
**29** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.2`
|
||||
**29** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.2`
|
||||
> - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org)
|
||||
> - **Manifest License**: The 3-Clause BSD License (Not Packaged)
|
||||
> - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/)
|
||||
|
@ -154,30 +151,70 @@ _2021-11-09 12:26:05 EET_
|
|||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
|
||||
|
||||
## MIT License
|
||||
|
||||
**31** **Group:** `org.slf4j` **Name:** `slf4j-api` **Version:** `1.7.30`
|
||||
> - **POM Project URL**: [http://www.slf4j.org](http://www.slf4j.org)
|
||||
> - **POM License**: MIT License - [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)
|
||||
|
||||
**32** **Group:** `org.slf4j` **Name:** `slf4j-simple` **Version:** `1.7.30`
|
||||
> - **POM Project URL**: [http://www.slf4j.org](http://www.slf4j.org)
|
||||
> - **POM License**: MIT License - [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)
|
||||
|
||||
## The 3-Clause BSD License
|
||||
|
||||
**33** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.2`
|
||||
> - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org)
|
||||
> - **Manifest License**: The 3-Clause BSD License (Not Packaged)
|
||||
> - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
|
||||
|
||||
**34** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.2`
|
||||
> - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org)
|
||||
> - **Manifest License**: The 3-Clause BSD License (Not Packaged)
|
||||
> - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
|
||||
|
||||
**35** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.2`
|
||||
> - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org)
|
||||
> - **Manifest License**: The 3-Clause BSD License (Not Packaged)
|
||||
> - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
|
||||
|
||||
**36** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.2`
|
||||
> - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org)
|
||||
> - **Manifest License**: The 3-Clause BSD License (Not Packaged)
|
||||
> - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/)
|
||||
> - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
> - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
|
||||
|
||||
## Unknown
|
||||
|
||||
**31** **Group:** `com.fasterxml.jackson` **Name:** `jackson-bom` **Version:** `2.12.3`
|
||||
**37** **Group:** `com.fasterxml.jackson` **Name:** `jackson-bom` **Version:** `2.12.3`
|
||||
|
||||
**32** **Group:** `com.google.guava` **Name:** `guava-bom` **Version:** `30.1.1-jre`
|
||||
**38** **Group:** `com.google.guava` **Name:** `guava-bom` **Version:** `30.1.1-jre`
|
||||
|
||||
**33** **Group:** `io.opentelemetry` **Name:** `opentelemetry-bom` **Version:** `1.7.1`
|
||||
**39** **Group:** `io.opentelemetry` **Name:** `opentelemetry-bom` **Version:** `1.9.0`
|
||||
|
||||
**34** **Group:** `io.opentelemetry` **Name:** `opentelemetry-bom-alpha` **Version:** `1.7.1-alpha`
|
||||
**40** **Group:** `io.opentelemetry` **Name:** `opentelemetry-bom-alpha` **Version:** `1.9.0-alpha`
|
||||
|
||||
**35** **Group:** `io.opentelemetry.jaxrs-common` **Name:** `bootstrap` **Version:** `1.8.0-alpha-SNAPSHOT`
|
||||
**41** **Group:** `io.opentelemetry.jaxrs-common` **Name:** `bootstrap` **Version:** `1.9.0-alpha-SNAPSHOT`
|
||||
|
||||
**36** **Group:** `io.opentelemetry.kafka-clients-0.11` **Name:** `bootstrap` **Version:** `1.8.0-alpha-SNAPSHOT`
|
||||
**42** **Group:** `io.opentelemetry.kafka-clients-0.11` **Name:** `bootstrap` **Version:** `1.9.0-alpha-SNAPSHOT`
|
||||
|
||||
**37** **Group:** `io.opentelemetry.rmi` **Name:** `bootstrap` **Version:** `1.8.0-alpha-SNAPSHOT`
|
||||
**43** **Group:** `io.opentelemetry.rmi` **Name:** `bootstrap` **Version:** `1.9.0-alpha-SNAPSHOT`
|
||||
|
||||
**38** **Group:** `io.opentelemetry.undertow-1.4` **Name:** `bootstrap` **Version:** `1.8.0-alpha-SNAPSHOT`
|
||||
**44** **Group:** `io.opentelemetry.undertow-1.4` **Name:** `bootstrap` **Version:** `1.9.0-alpha-SNAPSHOT`
|
||||
|
||||
**39** **Group:** `opentelemetry-java-instrumentation` **Name:** `dependencyManagement` **Version:** `1.8.0-alpha-SNAPSHOT`
|
||||
**45** **Group:** `opentelemetry-java-instrumentation` **Name:** `dependencyManagement` **Version:** `1.9.0-alpha-SNAPSHOT`
|
||||
|
||||
**40** **Group:** `org.codehaus.groovy` **Name:** `groovy-bom` **Version:** `2.5.14`
|
||||
**46** **Group:** `org.codehaus.groovy` **Name:** `groovy-bom` **Version:** `2.5.14`
|
||||
|
||||
**41** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-bom` **Version:** `1.4.10`
|
||||
**47** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-bom` **Version:** `1.4.10`
|
||||
|
||||
**42** **Group:** `org.junit` **Name:** `junit-bom` **Version:** `5.7.2`
|
||||
**48** **Group:** `org.junit` **Name:** `junit-bom` **Version:** `5.7.2`
|
||||
|
||||
|
||||
|
|
|
@ -21,10 +21,6 @@ dependencies {
|
|||
implementation(project(":javaagent-extension-api"))
|
||||
implementation("org.slf4j:slf4j-api")
|
||||
|
||||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our
|
||||
// inclusion of this artifact inside of :instrumentation-api
|
||||
compileOnly(project(":instrumentation-api-caching"))
|
||||
|
||||
testImplementation(project(":testing-common"))
|
||||
testImplementation("com.google.guava:guava")
|
||||
testImplementation("org.assertj:assertj-core:3.19.0")
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package io.opentelemetry.javaagent.tooling;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import io.opentelemetry.javaagent.bootstrap.HelperResources;
|
||||
import io.opentelemetry.javaagent.tooling.muzzle.HelperResource;
|
||||
import java.io.File;
|
||||
|
@ -58,8 +58,7 @@ public class HelperInjector implements Transformer {
|
|||
}
|
||||
};
|
||||
|
||||
private static final Cache<Class<?>, Boolean> injectedClasses =
|
||||
Cache.builder().setWeakKeys().build();
|
||||
private static final Cache<Class<?>, Boolean> injectedClasses = Cache.weak();
|
||||
|
||||
private final String requestingName;
|
||||
|
||||
|
@ -69,10 +68,8 @@ public class HelperInjector implements Transformer {
|
|||
@Nullable private final Instrumentation instrumentation;
|
||||
private final Map<String, byte[]> dynamicTypeMap = new LinkedHashMap<>();
|
||||
|
||||
private final Cache<ClassLoader, Boolean> injectedClassLoaders =
|
||||
Cache.builder().setWeakKeys().build();
|
||||
private final Cache<ClassLoader, Boolean> resourcesInjectedClassLoaders =
|
||||
Cache.builder().setWeakKeys().build();
|
||||
private final Cache<ClassLoader, Boolean> injectedClassLoaders = Cache.weak();
|
||||
private final Cache<ClassLoader, Boolean> resourcesInjectedClassLoaders = Cache.weak();
|
||||
|
||||
private final List<WeakReference<Object>> helperModules = new CopyOnWriteArrayList<>();
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package io.opentelemetry.javaagent.tooling.muzzle;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.caching.Cache;
|
||||
import io.opentelemetry.instrumentation.api.cache.Cache;
|
||||
import java.lang.ref.WeakReference;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
import net.bytebuddy.description.annotation.AnnotationList;
|
||||
|
@ -48,14 +48,13 @@ public class AgentCachingPoolStrategy implements AgentBuilder.PoolStrategy {
|
|||
* <li>Allow for quick fast path equivalence check of composite keys
|
||||
* </ul>
|
||||
*/
|
||||
final Cache<ClassLoader, WeakReference<ClassLoader>> loaderRefCache =
|
||||
Cache.builder().setWeakKeys().build();
|
||||
final Cache<ClassLoader, WeakReference<ClassLoader>> loaderRefCache = Cache.weak();
|
||||
|
||||
/**
|
||||
* Single shared Type.Resolution cache -- uses a composite key -- conceptually of loader & name
|
||||
*/
|
||||
final Cache<TypeCacheKey, TypePool.Resolution> sharedResolutionCache =
|
||||
Cache.builder().setMaximumSize(TYPE_CAPACITY).build();
|
||||
Cache.bounded(TYPE_CAPACITY);
|
||||
|
||||
// fast path for bootstrap
|
||||
final SharedResolutionCacheAdapter bootstrapCacheProvider =
|
||||
|
|
|
@ -74,9 +74,6 @@ include(":javaagent")
|
|||
|
||||
include(":bom-alpha")
|
||||
include(":instrumentation-api")
|
||||
include(":instrumentation-api-caching")
|
||||
include(":instrumentation-api-caching:caffeine2")
|
||||
include(":instrumentation-api-caching:caffeine3")
|
||||
include(":javaagent-instrumentation-api")
|
||||
include(":instrumentation-api-annotation-support")
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import io.opentelemetry.javaagent.tooling.Constants
|
|||
import org.slf4j.LoggerFactory
|
||||
|
||||
import java.util.concurrent.TimeoutException
|
||||
import spock.util.environment.Jvm
|
||||
|
||||
// this test is run using
|
||||
// -Dotel.javaagent.exclude-classes=config.exclude.packagename.*,config.exclude.SomeClass,config.exclude.SomeClass$NestedClass
|
||||
|
@ -22,10 +21,6 @@ class AgentInstrumentationSpecificationTest extends AgentInstrumentationSpecific
|
|||
setup:
|
||||
final List<String> bootstrapClassesIncorrectlyLoaded = []
|
||||
for (ClassPath.ClassInfo info : getTestClasspath().getAllClasses()) {
|
||||
if (info.getName().toLowerCase().contains("caffeine3") && !Jvm.getCurrent().isJava11Compatible()) {
|
||||
// caffeine 3 classes are compiled for java 11
|
||||
continue
|
||||
}
|
||||
for (int i = 0; i < Constants.BOOTSTRAP_PACKAGE_PREFIXES.size(); ++i) {
|
||||
if (info.getName().startsWith(Constants.BOOTSTRAP_PACKAGE_PREFIXES[i])) {
|
||||
Class<?> bootstrapClass = Class.forName(info.getName())
|
||||
|
|
Loading…
Reference in New Issue