• 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.Utils;
20 import java.util.Random;
21 import javax.annotation.Nullable;
22 import javax.annotation.concurrent.Immutable;
23 
24 /**
25  * A class that represents a span identifier. A valid span identifier is an 8-byte array with at
26  * least one non-zero byte.
27  *
28  * @since 0.5
29  */
30 @Immutable
31 public final class SpanId implements Comparable<SpanId> {
32   /**
33    * The size in bytes of the {@code SpanId}.
34    *
35    * @since 0.5
36    */
37   public static final int SIZE = 8;
38 
39   /**
40    * The invalid {@code SpanId}. All bytes are 0.
41    *
42    * @since 0.5
43    */
44   public static final SpanId INVALID = new SpanId(0);
45 
46   private static final int BASE16_SIZE = 2 * SIZE;
47   private static final long INVALID_ID = 0;
48 
49   // The internal representation of the SpanId.
50   private final long id;
51 
SpanId(long id)52   private SpanId(long id) {
53     this.id = id;
54   }
55 
56   /**
57    * Returns a {@code SpanId} built from a byte representation.
58    *
59    * @param src the representation of the {@code SpanId}.
60    * @return a {@code SpanId} whose representation is given by the {@code src} parameter.
61    * @throws NullPointerException if {@code src} is null.
62    * @throws IllegalArgumentException if {@code src.length} is not {@link SpanId#SIZE}.
63    * @since 0.5
64    */
fromBytes(byte[] src)65   public static SpanId fromBytes(byte[] src) {
66     Utils.checkNotNull(src, "src");
67     // TODO: Remove this extra condition.
68     Utils.checkArgument(src.length == SIZE, "Invalid size: expected %s, got %s", SIZE, src.length);
69     return fromBytes(src, 0);
70   }
71 
72   /**
73    * Returns a {@code SpanId} whose representation is copied from the {@code src} beginning at the
74    * {@code srcOffset} offset.
75    *
76    * @param src the buffer where the representation of the {@code SpanId} is copied.
77    * @param srcOffset the offset in the buffer where the representation of the {@code SpanId}
78    *     begins.
79    * @return a {@code SpanId} whose representation is copied from the buffer.
80    * @throws NullPointerException if {@code src} is null.
81    * @throws IndexOutOfBoundsException if {@code srcOffset+SpanId.SIZE} is greater than {@code
82    *     src.length}.
83    * @since 0.5
84    */
fromBytes(byte[] src, int srcOffset)85   public static SpanId fromBytes(byte[] src, int srcOffset) {
86     Utils.checkNotNull(src, "src");
87     return new SpanId(BigendianEncoding.longFromByteArray(src, srcOffset));
88   }
89 
90   /**
91    * Returns a {@code SpanId} built from a lowercase base16 representation.
92    *
93    * @param src the lowercase base16 representation.
94    * @return a {@code SpanId} built from a lowercase base16 representation.
95    * @throws NullPointerException if {@code src} is null.
96    * @throws IllegalArgumentException if {@code src.length} is not {@code 2 * SpanId.SIZE} OR if the
97    *     {@code str} has invalid characters.
98    * @since 0.11
99    */
fromLowerBase16(CharSequence src)100   public static SpanId fromLowerBase16(CharSequence src) {
101     Utils.checkNotNull(src, "src");
102     // TODO: Remove this extra condition.
103     Utils.checkArgument(
104         src.length() == BASE16_SIZE,
105         "Invalid size: expected %s, got %s",
106         BASE16_SIZE,
107         src.length());
108     return fromLowerBase16(src, 0);
109   }
110 
111   /**
112    * Returns a {@code SpanId} built from a lowercase base16 representation.
113    *
114    * @param src the lowercase base16 representation.
115    * @param srcOffset the offset in the buffer where the representation of the {@code SpanId}
116    *     begins.
117    * @return a {@code SpanId} built from a lowercase base16 representation.
118    * @throws NullPointerException if {@code src} is null.
119    * @throws IllegalArgumentException if not enough characters in the {@code src} from the {@code
120    *     srcOffset}.
121    * @since 0.11
122    */
fromLowerBase16(CharSequence src, int srcOffset)123   public static SpanId fromLowerBase16(CharSequence src, int srcOffset) {
124     Utils.checkNotNull(src, "src");
125     return new SpanId(BigendianEncoding.longFromBase16String(src, srcOffset));
126   }
127 
128   /**
129    * Generates a new random {@code SpanId}.
130    *
131    * @param random The random number generator.
132    * @return a valid new {@code SpanId}.
133    * @since 0.5
134    */
generateRandomId(Random random)135   public static SpanId generateRandomId(Random random) {
136     long id;
137     do {
138       id = random.nextLong();
139     } while (id == INVALID_ID);
140     return new SpanId(id);
141   }
142 
143   /**
144    * Returns the byte representation of the {@code SpanId}.
145    *
146    * @return the byte representation of the {@code SpanId}.
147    * @since 0.5
148    */
getBytes()149   public byte[] getBytes() {
150     byte[] bytes = new byte[SIZE];
151     BigendianEncoding.longToByteArray(id, bytes, 0);
152     return bytes;
153   }
154 
155   /**
156    * Copies the byte array representations of the {@code SpanId} into the {@code dest} beginning at
157    * the {@code destOffset} offset.
158    *
159    * @param dest the destination buffer.
160    * @param destOffset the starting offset in the destination buffer.
161    * @throws NullPointerException if {@code dest} is null.
162    * @throws IndexOutOfBoundsException if {@code destOffset+SpanId.SIZE} is greater than {@code
163    *     dest.length}.
164    * @since 0.5
165    */
copyBytesTo(byte[] dest, int destOffset)166   public void copyBytesTo(byte[] dest, int destOffset) {
167     BigendianEncoding.longToByteArray(id, dest, destOffset);
168   }
169 
170   /**
171    * Copies the lowercase base16 representations of the {@code SpanId} into the {@code dest}
172    * beginning at the {@code destOffset} offset.
173    *
174    * @param dest the destination buffer.
175    * @param destOffset the starting offset in the destination buffer.
176    * @throws IndexOutOfBoundsException if {@code destOffset + 2 * SpanId.SIZE} is greater than
177    *     {@code dest.length}.
178    * @since 0.18
179    */
copyLowerBase16To(char[] dest, int destOffset)180   public void copyLowerBase16To(char[] dest, int destOffset) {
181     BigendianEncoding.longToBase16String(id, dest, destOffset);
182   }
183 
184   /**
185    * Returns whether the span identifier is valid. A valid span identifier is an 8-byte array with
186    * at least one non-zero byte.
187    *
188    * @return {@code true} if the span identifier is valid.
189    * @since 0.5
190    */
isValid()191   public boolean isValid() {
192     return id != INVALID_ID;
193   }
194 
195   /**
196    * Returns the lowercase base16 encoding of this {@code SpanId}.
197    *
198    * @return the lowercase base16 encoding of this {@code SpanId}.
199    * @since 0.11
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   @Override
equals(@ullable Object obj)208   public boolean equals(@Nullable Object obj) {
209     if (obj == this) {
210       return true;
211     }
212 
213     if (!(obj instanceof SpanId)) {
214       return false;
215     }
216 
217     SpanId that = (SpanId) obj;
218     return id == that.id;
219   }
220 
221   @Override
hashCode()222   public int hashCode() {
223     // Copied from Long.hashCode in java8.
224     return (int) (id ^ (id >>> 32));
225   }
226 
227   @Override
toString()228   public String toString() {
229     return "SpanId{spanId=" + toLowerBase16() + "}";
230   }
231 
232   @Override
compareTo(SpanId that)233   public int compareTo(SpanId that) {
234     // Copied from Long.compare in java8.
235     return (id < that.id) ? -1 : ((id == that.id) ? 0 : 1);
236   }
237 }
238