forked from openzipkin/zipkin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
StorageComponent.java
192 lines (172 loc) · 8.42 KB
/
StorageComponent.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
* Copyright 2015-2020 The OpenZipkin Authors
*
* 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 zipkin2.storage;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import java.util.logging.Logger;
import zipkin2.Call;
import zipkin2.Callback;
import zipkin2.Component;
import zipkin2.Span;
import zipkin2.internal.TracesAdapter;
/**
* A component that provides storage interfaces used for spans and aggregations. Implementations are
* free to provide other interfaces, but the ones declared here must be supported.
*
* @see InMemoryStorage
*/
public abstract class StorageComponent extends Component {
public Traces traces() {
return new TracesAdapter(spanStore()); // delegates to deprecated methods.
}
public abstract SpanStore spanStore();
public AutocompleteTags autocompleteTags() { // returns default to not break compat
return new AutocompleteTags() {
@Override public Call<List<String>> getKeys() {
return Call.emptyList();
}
@Override public Call<List<String>> getValues(String key) {
return Call.emptyList();
}
@Override public String toString() {
return "EmptyAutocompleteTags{}";
}
};
}
public ServiceAndSpanNames serviceAndSpanNames() { // delegates to deprecated methods.
final SpanStore delegate = spanStore();
return new ServiceAndSpanNames() {
@Override public Call<List<String>> getServiceNames() {
return delegate.getServiceNames();
}
@Override public Call<List<String>> getRemoteServiceNames(String serviceName) {
return Call.emptyList(); // incorrect for not yet ported 3rd party storage components.
}
@Override public Call<List<String>> getSpanNames(String serviceName) {
return delegate.getSpanNames(serviceName);
}
@Override public String toString() {
return "ServiceAndSpanNames{" + delegate + "}";
}
};
}
public abstract SpanConsumer spanConsumer();
/**
* A storage request failed and was dropped due to a limit, resource unavailability, or a timeout.
* Implementations of throttling can use this signal to differentiate between failures, for
* example to reduce traffic.
*
* <p>Callers of this method will submit an exception raised by {@link Call#execute()} or on the
* error callback of {@link Call#enqueue(Callback)}.
*
* <p>By default, this returns true if the input is a {@link RejectedExecutionException}. When
* originating exceptions, use this type to indicate a load related failure.
*
* <p>It is generally preferred to specialize this method to handle relevant exceptions for the
* particular storage rather than wrapping them in {@link RejectedExecutionException} at call
* sites. Extra wrapping can make errors harder to read, for example, by making it harder to
* "google" a solution for a well known error message for the storage client, instead thinking the
* error is in Zipkin code itself.
*
* <h3>See also</h3>
* <p>While implementation is flexible, one known use is <a href="https://github.com/Netflix/concurrency-limits">Netflix
* concurrency limits</a>
*/
public boolean isOverCapacity(Throwable e) {
return e instanceof RejectedExecutionException;
}
public static abstract class Builder {
/**
* Zipkin supports 64 and 128-bit trace identifiers, typically serialized as 16 or 32 character
* hex strings. When false, this setting only considers the low 64-bits (right-most 16
* characters) of a trace ID when grouping or retrieving traces. This should be set to false
* while some applications issue 128-bit trace IDs and while other truncate them to 64-bit. If
* 128-bit trace IDs are not in use, this setting is not required.
*
* <h3>Details</h3>
*
* <p>Zipkin historically had 64-bit {@link Span#traceId() trace IDs}, but it now supports 128-
* bit trace IDs via 32-character hex representation. While instrumentation update to propagate
* 128-bit IDs, it can be ambiguous whether a 64-bit trace ID was sent intentionally, or as an
* accident of truncation. This setting allows Zipkin to be usable until application
* instrumentation are upgraded to support 128-bit trace IDs.
*
* <p>Here are a few trace IDs the help explain this setting.
*
* <pre><ul>
* <li>Trace ID A: 463ac35c9f6413ad48485a3953bb6124</li>
* <li>Trace ID B: 48485a3953bb6124</li>
* <li>Trace ID C: 463ac35c9f6413adf1a48a8cff464e0e</li>
* <li>Trace ID D: 463ac35c9f6413ad</li>
* </ul></pre>
*
* <p>In the above example, Trace ID A and Trace ID B might mean they are in the same trace,
* since the lower-64 bits of the IDs are the same. This could happen if a server A created the
* trace and propagated it to server B which ran an older tracing library. Server B could have
* truncated the trace ID to lower-64 bits. When {@code strictTraceId == false}, spans matching
* either trace ID A or B would be returned in the same trace when searching by ID A or B. Spans
* with trace ID C or D wouldn't be when searching by ID A or B because trace IDs C and D don't
* share lower 64-bits (right-most 16 characters) with trace IDs A or B.
*
* <p>It is also possible that all servers are capable of handling 128-bit trace identifiers,
* but are configured to only send 64-bit ones. In this case, if {@code strictTraceId == false}
* trace ID A and B would clash and be put into the same trace, causing confusion. Moreover,
* there is overhead associated with indexing spans both by 64 and 128-bit trace IDs. When a
* site has finished upgrading to 128-bit trace IDs, they should enable this setting.
*
* <p>See https://github.com/openzipkin/b3-propagation/issues/6 for the status of
* known open source libraries on 128-bit trace identifiers.
*/
public abstract Builder strictTraceId(boolean strictTraceId);
/**
* False is an attempt to disable indexing, leaving only {@link StorageComponent#traces()}
* supported. For example, query requests will be disabled.
*
* The use case is typically to support 100% sampled data, or when traces are searched using
* alternative means such as a logging index.
*
* <p>Refer to implementation docs for the impact of this parameter. Operations that use
* indexes should return empty as opposed to throwing an exception.
*/
public abstract Builder searchEnabled(boolean searchEnabled);
/**
* Autocomplete is used by the UI to suggest getValues for site-specific tags, such as
* environment names. The getKeys here would appear in {@link Span#tags() span tags}. Good
* choices for autocomplete are limited in cardinality for the same reasons as service and span
* names.
*
* For example, "http.url" would be a bad choice for autocomplete, not just because it isn't
* site-specific (such as environment would be), but also as there are unlimited getValues due
* to factors such as unique ids in the path.
*
* @param keys controls the span values stored for auto-complete.
*/
public Builder autocompleteKeys(List<String> keys) { // not abstract as added later
Logger.getLogger(getClass().getName()).info("autocompleteKeys not yet supported");
return this;
}
/** How long in milliseconds to suppress calls to write the same autocomplete key/value pair. */
public Builder autocompleteTtl(int autocompleteTtl) { // not abstract as added later
Logger.getLogger(getClass().getName()).info("autocompleteTtl not yet supported");
return this;
}
/** How many autocomplete key/value pairs to suppress at a time. */
public Builder autocompleteCardinality(
int autocompleteCardinality) { // not abstract as added later
Logger.getLogger(getClass().getName()).info("autocompleteCardinality not yet supported");
return this;
}
public abstract StorageComponent build();
}
}