Home | History | Annotate | Download | only in trace
      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.
     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
     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
    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    */
    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    */
    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
    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    */
    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    */
    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    */
    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    */
    191   public boolean isSampled() {
    192     return hasOption(IS_SAMPLED);
    193   }
    194 
    195   @Override
    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
    210   public int hashCode() {
    211     return Arrays.hashCode(new byte[] {options});
    212   }
    213 
    214   @Override
    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 
    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
    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      */
    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      */
    266     public TraceOptions build() {
    267       return fromByte(options);
    268     }
    269   }
    270 
    271   // Returns the current set of options bitmask.
    272   @DefaultVisibilityForTesting
    273   byte getOptions() {
    274     return options;
    275   }
    276 
    277   private boolean hasOption(int mask) {
    278     return (this.options & mask) != 0;
    279   }
    280 }
    281