• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017, OpenCensus Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.opencensus.trace;
18 
19 import io.opencensus.internal.DefaultVisibilityForTesting;
20 import io.opencensus.internal.Utils;
21 import java.util.Arrays;
22 import javax.annotation.Nullable;
23 import javax.annotation.concurrent.Immutable;
24 
25 /**
26  * A class that represents global trace options. These options are propagated to all child {@link
27  * io.opencensus.trace.Span spans}. These determine features such as whether a {@code Span} should
28  * be traced. It is implemented as a bitmask.
29  *
30  * @since 0.5
31  */
32 @Immutable
33 public final class TraceOptions {
34   // Default options. Nothing set.
35   private static final byte DEFAULT_OPTIONS = 0;
36   // Bit to represent whether trace is sampled or not.
37   private static final byte IS_SAMPLED = 0x1;
38 
39   /**
40    * The size in bytes of the {@code TraceOptions}.
41    *
42    * @since 0.5
43    */
44   public static final int SIZE = 1;
45 
46   private static final int BASE16_SIZE = 2 * SIZE;
47 
48   /**
49    * The default {@code TraceOptions}.
50    *
51    * @since 0.5
52    */
53   public static final TraceOptions DEFAULT = fromByte(DEFAULT_OPTIONS);
54 
55   // The set of enabled features is determined by all the enabled bits.
56   private final byte options;
57 
58   // Creates a new {@code TraceOptions} with the given options.
TraceOptions(byte options)59   private TraceOptions(byte options) {
60     this.options = options;
61   }
62 
63   /**
64    * Returns a {@code TraceOptions} built from a byte representation.
65    *
66    * <p>Equivalent with:
67    *
68    * <pre>{@code
69    * TraceOptions.fromBytes(buffer, 0);
70    * }</pre>
71    *
72    * @param buffer the representation of the {@code TraceOptions}.
73    * @return a {@code TraceOptions} whose representation is given by the {@code buffer} parameter.
74    * @throws NullPointerException if {@code buffer} is null.
75    * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceOptions#SIZE}.
76    * @since 0.5
77    * @deprecated use {@link #fromByte(byte)}.
78    */
79   @Deprecated
fromBytes(byte[] buffer)80   public static TraceOptions fromBytes(byte[] buffer) {
81     Utils.checkNotNull(buffer, "buffer");
82     Utils.checkArgument(
83         buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length);
84     return fromByte(buffer[0]);
85   }
86 
87   /**
88    * Returns a {@code TraceOptions} whose representation is copied from the {@code src} beginning at
89    * the {@code srcOffset} offset.
90    *
91    * @param src the buffer where the representation of the {@code TraceOptions} is copied.
92    * @param srcOffset the offset in the buffer where the representation of the {@code TraceOptions}
93    *     begins.
94    * @return a {@code TraceOptions} whose representation is copied from the buffer.
95    * @throws NullPointerException if {@code src} is null.
96    * @throws IndexOutOfBoundsException if {@code srcOffset+TraceOptions.SIZE} is greater than {@code
97    *     src.length}.
98    * @since 0.5
99    * @deprecated use {@link #fromByte(byte)}.
100    */
101   @Deprecated
fromBytes(byte[] src, int srcOffset)102   public static TraceOptions fromBytes(byte[] src, int srcOffset) {
103     Utils.checkIndex(srcOffset, src.length);
104     return fromByte(src[srcOffset]);
105   }
106 
107   /**
108    * Returns a {@code TraceOptions} whose representation is {@code src}.
109    *
110    * @param src the byte representation of the {@code TraceOptions}.
111    * @return a {@code TraceOptions} whose representation is {@code src}.
112    * @since 0.16
113    */
fromByte(byte src)114   public static TraceOptions fromByte(byte src) {
115     // TODO(bdrutu): OPTIMIZATION: Cache all the 256 possible objects and return from the cache.
116     return new TraceOptions(src);
117   }
118 
119   /**
120    * Returns a {@code TraceOption} built from a lowercase base16 representation.
121    *
122    * @param src the lowercase base16 representation.
123    * @param srcOffset the offset in the buffer where the representation of the {@code TraceOptions}
124    *     begins.
125    * @return a {@code TraceOption} built from a lowercase base16 representation.
126    * @throws NullPointerException if {@code src} is null.
127    * @throws IllegalArgumentException if {@code src.length} is not {@code 2 * TraceOption.SIZE} OR
128    *     if the {@code str} has invalid characters.
129    * @since 0.18
130    */
fromLowerBase16(CharSequence src, int srcOffset)131   public static TraceOptions fromLowerBase16(CharSequence src, int srcOffset) {
132     return new TraceOptions(BigendianEncoding.byteFromBase16String(src, srcOffset));
133   }
134 
135   /**
136    * Returns the one byte representation of the {@code TraceOptions}.
137    *
138    * @return the one byte representation of the {@code TraceOptions}.
139    * @since 0.16
140    */
getByte()141   public byte getByte() {
142     return options;
143   }
144 
145   /**
146    * Returns the 1-byte array representation of the {@code TraceOptions}.
147    *
148    * @return the 1-byte array representation of the {@code TraceOptions}.
149    * @since 0.5
150    * @deprecated use {@link #getByte()}.
151    */
152   @Deprecated
getBytes()153   public byte[] getBytes() {
154     byte[] bytes = new byte[SIZE];
155     bytes[0] = options;
156     return bytes;
157   }
158 
159   /**
160    * Copies the byte representations of the {@code TraceOptions} into the {@code dest} beginning at
161    * the {@code destOffset} offset.
162    *
163    * <p>Equivalent with (but faster because it avoids any new allocations):
164    *
165    * <pre>{@code
166    * System.arraycopy(getBytes(), 0, dest, destOffset, TraceOptions.SIZE);
167    * }</pre>
168    *
169    * @param dest the destination buffer.
170    * @param destOffset the starting offset in the destination buffer.
171    * @throws NullPointerException if {@code dest} is null.
172    * @throws IndexOutOfBoundsException if {@code destOffset+TraceOptions.SIZE} is greater than
173    *     {@code dest.length}.
174    * @since 0.5
175    */
copyBytesTo(byte[] dest, int destOffset)176   public void copyBytesTo(byte[] dest, int destOffset) {
177     Utils.checkIndex(destOffset, dest.length);
178     dest[destOffset] = options;
179   }
180 
181   /**
182    * Copies the lowercase base16 representations of the {@code TraceId} into the {@code dest}
183    * beginning at the {@code destOffset} offset.
184    *
185    * @param dest the destination buffer.
186    * @param destOffset the starting offset in the destination buffer.
187    * @throws IndexOutOfBoundsException if {@code destOffset + 2} is greater than {@code
188    *     dest.length}.
189    * @since 0.18
190    */
copyLowerBase16To(char[] dest, int destOffset)191   public void copyLowerBase16To(char[] dest, int destOffset) {
192     BigendianEncoding.byteToBase16String(options, dest, destOffset);
193   }
194 
195   /**
196    * Returns the lowercase base16 encoding of this {@code TraceOptions}.
197    *
198    * @return the lowercase base16 encoding of this {@code TraceOptions}.
199    * @since 0.18
200    */
toLowerBase16()201   public String toLowerBase16() {
202     char[] chars = new char[BASE16_SIZE];
203     copyLowerBase16To(chars, 0);
204     return new String(chars);
205   }
206 
207   /**
208    * Returns a new {@link Builder} with default options.
209    *
210    * @return a new {@code Builder} with default options.
211    * @since 0.5
212    */
builder()213   public static Builder builder() {
214     return new Builder(DEFAULT_OPTIONS);
215   }
216 
217   /**
218    * Returns a new {@link Builder} with all given options set.
219    *
220    * @param traceOptions the given options set.
221    * @return a new {@code Builder} with all given options set.
222    * @since 0.5
223    */
builder(TraceOptions traceOptions)224   public static Builder builder(TraceOptions traceOptions) {
225     return new Builder(traceOptions.options);
226   }
227 
228   /**
229    * Returns a boolean indicating whether this {@code Span} is part of a sampled trace and data
230    * should be exported to a persistent store.
231    *
232    * @return a boolean indicating whether the trace is sampled.
233    * @since 0.5
234    */
isSampled()235   public boolean isSampled() {
236     return hasOption(IS_SAMPLED);
237   }
238 
239   @Override
equals(@ullable Object obj)240   public boolean equals(@Nullable Object obj) {
241     if (obj == this) {
242       return true;
243     }
244 
245     if (!(obj instanceof TraceOptions)) {
246       return false;
247     }
248 
249     TraceOptions that = (TraceOptions) obj;
250     return options == that.options;
251   }
252 
253   @Override
hashCode()254   public int hashCode() {
255     return Arrays.hashCode(new byte[] {options});
256   }
257 
258   @Override
toString()259   public String toString() {
260     return "TraceOptions{sampled=" + isSampled() + "}";
261   }
262 
263   /**
264    * Builder class for {@link TraceOptions}.
265    *
266    * @since 0.5
267    */
268   public static final class Builder {
269     private byte options;
270 
Builder(byte options)271     private Builder(byte options) {
272       this.options = options;
273     }
274 
275     /**
276      * Sets the sampling bit in the options to true.
277      *
278      * @deprecated Use {@code Builder.setIsSampled(true)}.
279      * @return this.
280      * @since 0.5
281      */
282     @Deprecated
setIsSampled()283     public Builder setIsSampled() {
284       return setIsSampled(true);
285     }
286 
287     /**
288      * Sets the sampling bit in the options.
289      *
290      * @param isSampled the sampling bit.
291      * @return this.
292      * @since 0.7
293      */
setIsSampled(boolean isSampled)294     public Builder setIsSampled(boolean isSampled) {
295       if (isSampled) {
296         options = (byte) (options | IS_SAMPLED);
297       } else {
298         options = (byte) (options & ~IS_SAMPLED);
299         ;
300       }
301       return this;
302     }
303 
304     /**
305      * Builds and returns a {@code TraceOptions} with the desired options.
306      *
307      * @return a {@code TraceOptions} with the desired options.
308      * @since 0.5
309      */
build()310     public TraceOptions build() {
311       return fromByte(options);
312     }
313   }
314 
315   // Returns the current set of options bitmask.
316   @DefaultVisibilityForTesting
getOptions()317   byte getOptions() {
318     return options;
319   }
320 
hasOption(int mask)321   private boolean hasOption(int mask) {
322     return (this.options & mask) != 0;
323   }
324 }
325