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 /** 47 * The default {@code TraceOptions}. 48 * 49 * @since 0.5 50 */ 51 public static final TraceOptions DEFAULT = fromByte(DEFAULT_OPTIONS); 52 53 // The set of enabled features is determined by all the enabled bits. 54 private final byte options; 55 56 // Creates a new {@code TraceOptions} with the given options. TraceOptions(byte options)57 private TraceOptions(byte options) { 58 this.options = options; 59 } 60 61 /** 62 * Returns a {@code TraceOptions} built from a byte representation. 63 * 64 * <p>Equivalent with: 65 * 66 * <pre>{@code 67 * TraceOptions.fromBytes(buffer, 0); 68 * }</pre> 69 * 70 * @param buffer the representation of the {@code TraceOptions}. 71 * @return a {@code TraceOptions} whose representation is given by the {@code buffer} parameter. 72 * @throws NullPointerException if {@code buffer} is null. 73 * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceOptions#SIZE}. 74 * @since 0.5 75 * @deprecated use {@link #fromByte(byte)}. 76 */ 77 @Deprecated fromBytes(byte[] buffer)78 public static TraceOptions fromBytes(byte[] buffer) { 79 Utils.checkNotNull(buffer, "buffer"); 80 Utils.checkArgument( 81 buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); 82 return fromByte(buffer[0]); 83 } 84 85 /** 86 * Returns a {@code TraceOptions} whose representation is copied from the {@code src} beginning at 87 * the {@code srcOffset} offset. 88 * 89 * @param src the buffer where the representation of the {@code TraceOptions} is copied. 90 * @param srcOffset the offset in the buffer where the representation of the {@code TraceOptions} 91 * begins. 92 * @return a {@code TraceOptions} whose representation is copied from the buffer. 93 * @throws NullPointerException if {@code src} is null. 94 * @throws IndexOutOfBoundsException if {@code srcOffset+TraceOptions.SIZE} is greater than {@code 95 * src.length}. 96 * @since 0.5 97 * @deprecated use {@link #fromByte(byte)}. 98 */ 99 @Deprecated fromBytes(byte[] src, int srcOffset)100 public static TraceOptions fromBytes(byte[] src, int srcOffset) { 101 Utils.checkIndex(srcOffset, src.length); 102 return fromByte(src[srcOffset]); 103 } 104 105 /** 106 * Returns a {@code TraceOptions} whose representation is {@code src}. 107 * 108 * @param src the byte representation of the {@code TraceOptions}. 109 * @return a {@code TraceOptions} whose representation is {@code src}. 110 * @since 0.16 111 */ fromByte(byte src)112 public static TraceOptions fromByte(byte src) { 113 // TODO(bdrutu): OPTIMIZATION: Cache all the 256 possible objects and return from the cache. 114 return new TraceOptions(src); 115 } 116 117 /** 118 * Returns the one byte representation of the {@code TraceOptions}. 119 * 120 * @return the one byte representation of the {@code TraceOptions}. 121 * @since 0.16 122 */ getByte()123 public byte getByte() { 124 return options; 125 } 126 127 /** 128 * Returns the 1-byte array representation of the {@code TraceOptions}. 129 * 130 * @return the 1-byte array representation of the {@code TraceOptions}. 131 * @since 0.5 132 * @deprecated use {@link #getByte()}. 133 */ 134 @Deprecated getBytes()135 public byte[] getBytes() { 136 byte[] bytes = new byte[SIZE]; 137 bytes[0] = options; 138 return bytes; 139 } 140 141 /** 142 * Copies the byte representations of the {@code TraceOptions} into the {@code dest} beginning at 143 * the {@code destOffset} offset. 144 * 145 * <p>Equivalent with (but faster because it avoids any new allocations): 146 * 147 * <pre>{@code 148 * System.arraycopy(getBytes(), 0, dest, destOffset, TraceOptions.SIZE); 149 * }</pre> 150 * 151 * @param dest the destination buffer. 152 * @param destOffset the starting offset in the destination buffer. 153 * @throws NullPointerException if {@code dest} is null. 154 * @throws IndexOutOfBoundsException if {@code destOffset+TraceOptions.SIZE} is greater than 155 * {@code dest.length}. 156 * @since 0.5 157 */ copyBytesTo(byte[] dest, int destOffset)158 public void copyBytesTo(byte[] dest, int destOffset) { 159 Utils.checkIndex(destOffset, dest.length); 160 dest[destOffset] = options; 161 } 162 163 /** 164 * Returns a new {@link Builder} with default options. 165 * 166 * @return a new {@code Builder} with default options. 167 * @since 0.5 168 */ builder()169 public static Builder builder() { 170 return new Builder(DEFAULT_OPTIONS); 171 } 172 173 /** 174 * Returns a new {@link Builder} with all given options set. 175 * 176 * @param traceOptions the given options set. 177 * @return a new {@code Builder} with all given options set. 178 * @since 0.5 179 */ builder(TraceOptions traceOptions)180 public static Builder builder(TraceOptions traceOptions) { 181 return new Builder(traceOptions.options); 182 } 183 184 /** 185 * Returns a boolean indicating whether this {@code Span} is part of a sampled trace and data 186 * should be exported to a persistent store. 187 * 188 * @return a boolean indicating whether the trace is sampled. 189 * @since 0.5 190 */ isSampled()191 public boolean isSampled() { 192 return hasOption(IS_SAMPLED); 193 } 194 195 @Override equals(@ullable Object obj)196 public boolean equals(@Nullable Object obj) { 197 if (obj == this) { 198 return true; 199 } 200 201 if (!(obj instanceof TraceOptions)) { 202 return false; 203 } 204 205 TraceOptions that = (TraceOptions) obj; 206 return options == that.options; 207 } 208 209 @Override hashCode()210 public int hashCode() { 211 return Arrays.hashCode(new byte[] {options}); 212 } 213 214 @Override toString()215 public String toString() { 216 return "TraceOptions{sampled=" + isSampled() + "}"; 217 } 218 219 /** 220 * Builder class for {@link TraceOptions}. 221 * 222 * @since 0.5 223 */ 224 public static final class Builder { 225 private byte options; 226 Builder(byte options)227 private Builder(byte options) { 228 this.options = options; 229 } 230 231 /** 232 * Sets the sampling bit in the options to true. 233 * 234 * @deprecated Use {@code Builder.setIsSampled(true)}. 235 * @return this. 236 * @since 0.5 237 */ 238 @Deprecated setIsSampled()239 public Builder setIsSampled() { 240 return setIsSampled(true); 241 } 242 243 /** 244 * Sets the sampling bit in the options. 245 * 246 * @param isSampled the sampling bit. 247 * @return this. 248 * @since 0.7 249 */ setIsSampled(boolean isSampled)250 public Builder setIsSampled(boolean isSampled) { 251 if (isSampled) { 252 options = (byte) (options | IS_SAMPLED); 253 } else { 254 options = (byte) (options & ~IS_SAMPLED); 255 ; 256 } 257 return this; 258 } 259 260 /** 261 * Builds and returns a {@code TraceOptions} with the desired options. 262 * 263 * @return a {@code TraceOptions} with the desired options. 264 * @since 0.5 265 */ build()266 public TraceOptions build() { 267 return fromByte(options); 268 } 269 } 270 271 // Returns the current set of options bitmask. 272 @DefaultVisibilityForTesting getOptions()273 byte getOptions() { 274 return options; 275 } 276 hasOption(int mask)277 private boolean hasOption(int mask) { 278 return (this.options & mask) != 0; 279 } 280 } 281