forked from open-telemetry/opentelemetry-java
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ComponentRegistry.java
124 lines (114 loc) · 4.84 KB
/
ComponentRegistry.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.internal;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import javax.annotation.Nullable;
/**
* Component (tracer, meter, etc) registry class for all the provider classes (TracerProvider,
* MeterProvider, etc.).
*
* <p>Components are identified by name, version, and schema. Name is required, but version and
* schema are optional. Therefore, we have 4 possible scenarios for component keys:
*
* <ol>
* <li>Only name is provided, represented by {@link #componentByName}
* <li>Name and version are provided, represented by {@link #componentByNameAndVersion}
* <li>Name and schema are provided, represented by {@link #componentByNameAndSchema}
* <li>Name, version and schema are provided, represented by {@link
* #componentByNameVersionAndSchema}
* </ol>
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*
* @param <V> the type of the registered value.
*/
public final class ComponentRegistry<V> {
private final Map<String, V> componentByName = new ConcurrentHashMap<>();
private final Map<String, Map<String, V>> componentByNameAndVersion = new ConcurrentHashMap<>();
private final Map<String, Map<String, V>> componentByNameAndSchema = new ConcurrentHashMap<>();
private final Map<String, Map<String, Map<String, V>>> componentByNameVersionAndSchema =
new ConcurrentHashMap<>();
private final Set<V> allComponents = Collections.newSetFromMap(new IdentityHashMap<>());
private final Function<InstrumentationScopeInfo, V> factory;
public ComponentRegistry(Function<InstrumentationScopeInfo, V> factory) {
this.factory = factory;
}
/**
* Returns the component associated with the {@code name}, {@code version}, and {@code schemaUrl}.
* {@link Attributes} are not part of component identity. Behavior is undefined when different
* {@link Attributes} are provided where {@code name}, {@code version}, and {@code schemaUrl} are
* identical.
*/
public V get(
String name, @Nullable String version, @Nullable String schemaUrl, Attributes attributes) {
if (version != null && schemaUrl != null) {
Map<String, Map<String, V>> componentByVersionAndSchema =
componentByNameVersionAndSchema.computeIfAbsent(
name, unused -> new ConcurrentHashMap<>());
Map<String, V> componentBySchema =
componentByVersionAndSchema.computeIfAbsent(version, unused -> new ConcurrentHashMap<>());
return componentBySchema.computeIfAbsent(
schemaUrl,
schemaUrl1 ->
buildComponent(
InstrumentationScopeInfo.builder(name)
.setVersion(version)
.setSchemaUrl(schemaUrl1)
.setAttributes(attributes)
.build()));
} else if (version != null) { // schemaUrl == null
Map<String, V> componentByVersion =
componentByNameAndVersion.computeIfAbsent(name, unused -> new ConcurrentHashMap<>());
return componentByVersion.computeIfAbsent(
version,
version1 ->
buildComponent(
InstrumentationScopeInfo.builder(name)
.setVersion(version1)
.setAttributes(attributes)
.build()));
}
if (schemaUrl != null) { // version == null
Map<String, V> componentBySchema =
componentByNameAndSchema.computeIfAbsent(name, unused -> new ConcurrentHashMap<>());
return componentBySchema.computeIfAbsent(
schemaUrl,
schemaUrl1 ->
buildComponent(
InstrumentationScopeInfo.builder(name)
.setSchemaUrl(schemaUrl1)
.setAttributes(attributes)
.build()));
} else { // schemaUrl == null && version == null
return componentByName.computeIfAbsent(
name,
name1 ->
buildComponent(
InstrumentationScopeInfo.builder(name1).setAttributes(attributes).build()));
}
}
private V buildComponent(InstrumentationScopeInfo instrumentationScopeInfo) {
V component = factory.apply(instrumentationScopeInfo);
allComponents.add(component);
return component;
}
/**
* Returns a {@code Collection} view of the registered components.
*
* @return a {@code Collection} view of the registered components.
*/
public Collection<V> getComponents() {
return Collections.unmodifiableCollection(allComponents);
}
}