aboutsummaryrefslogtreecommitdiff
path: root/api/src/main/java/io/opencensus/trace/TraceOptions.java
blob: 218f4dabe1471c11e1e7992f535c1542889d5755 (plain)
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/*
 * Copyright 2017, OpenCensus 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 io.opencensus.trace;

import io.opencensus.internal.DefaultVisibilityForTesting;
import io.opencensus.internal.Utils;
import java.util.Arrays;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

/**
 * A class that represents global trace options. These options are propagated to all child {@link
 * io.opencensus.trace.Span spans}. These determine features such as whether a {@code Span} should
 * be traced. It is implemented as a bitmask.
 *
 * @since 0.5
 */
@Immutable
public final class TraceOptions {
  // Default options. Nothing set.
  private static final byte DEFAULT_OPTIONS = 0;
  // Bit to represent whether trace is sampled or not.
  private static final byte IS_SAMPLED = 0x1;

  /**
   * The size in bytes of the {@code TraceOptions}.
   *
   * @since 0.5
   */
  public static final int SIZE = 1;

  /**
   * The default {@code TraceOptions}.
   *
   * @since 0.5
   */
  public static final TraceOptions DEFAULT = fromByte(DEFAULT_OPTIONS);

  // The set of enabled features is determined by all the enabled bits.
  private final byte options;

  // Creates a new {@code TraceOptions} with the given options.
  private TraceOptions(byte options) {
    this.options = options;
  }

  /**
   * Returns a {@code TraceOptions} built from a byte representation.
   *
   * <p>Equivalent with:
   *
   * <pre>{@code
   * TraceOptions.fromBytes(buffer, 0);
   * }</pre>
   *
   * @param buffer the representation of the {@code TraceOptions}.
   * @return a {@code TraceOptions} whose representation is given by the {@code buffer} parameter.
   * @throws NullPointerException if {@code buffer} is null.
   * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceOptions#SIZE}.
   * @since 0.5
   * @deprecated use {@link #fromByte(byte)}.
   */
  @Deprecated
  public static TraceOptions fromBytes(byte[] buffer) {
    Utils.checkNotNull(buffer, "buffer");
    Utils.checkArgument(
        buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length);
    return fromByte(buffer[0]);
  }

  /**
   * Returns a {@code TraceOptions} whose representation is copied from the {@code src} beginning at
   * the {@code srcOffset} offset.
   *
   * @param src the buffer where the representation of the {@code TraceOptions} is copied.
   * @param srcOffset the offset in the buffer where the representation of the {@code TraceOptions}
   *     begins.
   * @return a {@code TraceOptions} whose representation is copied from the buffer.
   * @throws NullPointerException if {@code src} is null.
   * @throws IndexOutOfBoundsException if {@code srcOffset+TraceOptions.SIZE} is greater than {@code
   *     src.length}.
   * @since 0.5
   * @deprecated use {@link #fromByte(byte)}.
   */
  @Deprecated
  public static TraceOptions fromBytes(byte[] src, int srcOffset) {
    Utils.checkIndex(srcOffset, src.length);
    return fromByte(src[srcOffset]);
  }

  /**
   * Returns a {@code TraceOptions} whose representation is {@code src}.
   *
   * @param src the byte representation of the {@code TraceOptions}.
   * @return a {@code TraceOptions} whose representation is {@code src}.
   * @since 0.16
   */
  public static TraceOptions fromByte(byte src) {
    // TODO(bdrutu): OPTIMIZATION: Cache all the 256 possible objects and return from the cache.
    return new TraceOptions(src);
  }

  /**
   * Returns the one byte representation of the {@code TraceOptions}.
   *
   * @return the one byte representation of the {@code TraceOptions}.
   * @since 0.16
   */
  public byte getByte() {
    return options;
  }

  /**
   * Returns the 1-byte array representation of the {@code TraceOptions}.
   *
   * @return the 1-byte array representation of the {@code TraceOptions}.
   * @since 0.5
   * @deprecated use {@link #getByte()}.
   */
  @Deprecated
  public byte[] getBytes() {
    byte[] bytes = new byte[SIZE];
    bytes[0] = options;
    return bytes;
  }

  /**
   * Copies the byte representations of the {@code TraceOptions} into the {@code dest} beginning at
   * the {@code destOffset} offset.
   *
   * <p>Equivalent with (but faster because it avoids any new allocations):
   *
   * <pre>{@code
   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceOptions.SIZE);
   * }</pre>
   *
   * @param dest the destination buffer.
   * @param destOffset the starting offset in the destination buffer.
   * @throws NullPointerException if {@code dest} is null.
   * @throws IndexOutOfBoundsException if {@code destOffset+TraceOptions.SIZE} is greater than
   *     {@code dest.length}.
   * @since 0.5
   */
  public void copyBytesTo(byte[] dest, int destOffset) {
    Utils.checkIndex(destOffset, dest.length);
    dest[destOffset] = options;
  }

  /**
   * Returns a new {@link Builder} with default options.
   *
   * @return a new {@code Builder} with default options.
   * @since 0.5
   */
  public static Builder builder() {
    return new Builder(DEFAULT_OPTIONS);
  }

  /**
   * Returns a new {@link Builder} with all given options set.
   *
   * @param traceOptions the given options set.
   * @return a new {@code Builder} with all given options set.
   * @since 0.5
   */
  public static Builder builder(TraceOptions traceOptions) {
    return new Builder(traceOptions.options);
  }

  /**
   * Returns a boolean indicating whether this {@code Span} is part of a sampled trace and data
   * should be exported to a persistent store.
   *
   * @return a boolean indicating whether the trace is sampled.
   * @since 0.5
   */
  public boolean isSampled() {
    return hasOption(IS_SAMPLED);
  }

  @Override
  public boolean equals(@Nullable Object obj) {
    if (obj == this) {
      return true;
    }

    if (!(obj instanceof TraceOptions)) {
      return false;
    }

    TraceOptions that = (TraceOptions) obj;
    return options == that.options;
  }

  @Override
  public int hashCode() {
    return Arrays.hashCode(new byte[] {options});
  }

  @Override
  public String toString() {
    return "TraceOptions{sampled=" + isSampled() + "}";
  }

  /**
   * Builder class for {@link TraceOptions}.
   *
   * @since 0.5
   */
  public static final class Builder {
    private byte options;

    private Builder(byte options) {
      this.options = options;
    }

    /**
     * Sets the sampling bit in the options to true.
     *
     * @deprecated Use {@code Builder.setIsSampled(true)}.
     * @return this.
     * @since 0.5
     */
    @Deprecated
    public Builder setIsSampled() {
      return setIsSampled(true);
    }

    /**
     * Sets the sampling bit in the options.
     *
     * @param isSampled the sampling bit.
     * @return this.
     * @since 0.7
     */
    public Builder setIsSampled(boolean isSampled) {
      if (isSampled) {
        options = (byte) (options | IS_SAMPLED);
      } else {
        options = (byte) (options & ~IS_SAMPLED);
        ;
      }
      return this;
    }

    /**
     * Builds and returns a {@code TraceOptions} with the desired options.
     *
     * @return a {@code TraceOptions} with the desired options.
     * @since 0.5
     */
    public TraceOptions build() {
      return fromByte(options);
    }
  }

  // Returns the current set of options bitmask.
  @DefaultVisibilityForTesting
  byte getOptions() {
    return options;
  }

  private boolean hasOption(int mask) {
    return (this.options & mask) != 0;
  }
}