1 /* 2 * Copyright 2016-17, 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 io.opencensus.trace.internal.BaseMessageEventUtils; 21 import java.util.Collections; 22 import java.util.EnumSet; 23 import java.util.Map; 24 import java.util.Set; 25 import javax.annotation.Nullable; 26 27 /** 28 * An abstract class that represents a span. It has an associated {@link SpanContext} and a set of 29 * {@link Options}. 30 * 31 * <p>Spans are created by the {@link SpanBuilder#startSpan} method. 32 * 33 * <p>{@code Span} <b>must</b> be ended by calling {@link #end()} or {@link #end(EndSpanOptions)} 34 * 35 * @since 0.5 36 */ 37 public abstract class Span { 38 private static final Map<String, AttributeValue> EMPTY_ATTRIBUTES = Collections.emptyMap(); 39 40 // Contains the identifiers associated with this Span. 41 private final SpanContext context; 42 43 // Contains the options associated with this Span. This object is immutable. 44 private final Set<Options> options; 45 46 /** 47 * {@code Span} options. These options are NOT propagated to child spans. These options determine 48 * features such as whether a {@code Span} should record any annotations or events. 49 * 50 * @since 0.5 51 */ 52 public enum Options { 53 /** 54 * This option is set if the Span is part of a sampled distributed trace OR {@link 55 * SpanBuilder#setRecordEvents(boolean)} was called with true. 56 * 57 * @since 0.5 58 */ 59 RECORD_EVENTS; 60 } 61 62 private static final Set<Options> DEFAULT_OPTIONS = 63 Collections.unmodifiableSet(EnumSet.noneOf(Options.class)); 64 65 /** 66 * Creates a new {@code Span}. 67 * 68 * @param context the context associated with this {@code Span}. 69 * @param options the options associated with this {@code Span}. If {@code null} then default 70 * options will be set. 71 * @throws NullPointerException if context is {@code null}. 72 * @throws IllegalArgumentException if the {@code SpanContext} is sampled but no RECORD_EVENTS 73 * options. 74 * @since 0.5 75 */ Span(SpanContext context, @Nullable EnumSet<Options> options)76 protected Span(SpanContext context, @Nullable EnumSet<Options> options) { 77 this.context = Utils.checkNotNull(context, "context"); 78 this.options = 79 options == null 80 ? DEFAULT_OPTIONS 81 : Collections.<Options>unmodifiableSet(EnumSet.copyOf(options)); 82 Utils.checkArgument( 83 !context.getTraceOptions().isSampled() || (this.options.contains(Options.RECORD_EVENTS)), 84 "Span is sampled, but does not have RECORD_EVENTS set."); 85 } 86 87 /** 88 * Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for 89 * the key, the old value is replaced by the specified value. 90 * 91 * @param key the key for this attribute. 92 * @param value the value for this attribute. 93 * @since 0.6 94 */ putAttribute(String key, AttributeValue value)95 public void putAttribute(String key, AttributeValue value) { 96 // Not final because for performance reasons we want to override this in the implementation. 97 // Also a default implementation is needed to not break the compatibility (users may extend this 98 // for testing). 99 Utils.checkNotNull(key, "key"); 100 Utils.checkNotNull(value, "value"); 101 putAttributes(Collections.singletonMap(key, value)); 102 } 103 104 /** 105 * Sets a set of attributes to the {@code Span}. The effect of this call is equivalent to that of 106 * calling {@link #putAttribute(String, AttributeValue)} once for each element in the specified 107 * map. 108 * 109 * @param attributes the attributes that will be added and associated with the {@code Span}. 110 * @since 0.6 111 */ putAttributes(Map<String, AttributeValue> attributes)112 public void putAttributes(Map<String, AttributeValue> attributes) { 113 // Not final because we want to start overriding this method from the beginning, this will 114 // allow us to remove the addAttributes faster. All implementations MUST override this method. 115 Utils.checkNotNull(attributes, "attributes"); 116 addAttributes(attributes); 117 } 118 119 /** 120 * Sets a set of attributes to the {@code Span}. The effect of this call is equivalent to that of 121 * calling {@link #putAttribute(String, AttributeValue)} once for each element in the specified 122 * map. 123 * 124 * @deprecated Use {@link #putAttributes(Map)} 125 * @param attributes the attributes that will be added and associated with the {@code Span}. 126 * @since 0.5 127 */ 128 @Deprecated addAttributes(Map<String, AttributeValue> attributes)129 public void addAttributes(Map<String, AttributeValue> attributes) { 130 putAttributes(attributes); 131 } 132 133 /** 134 * Adds an annotation to the {@code Span}. 135 * 136 * @param description the description of the annotation time event. 137 * @since 0.5 138 */ addAnnotation(String description)139 public final void addAnnotation(String description) { 140 Utils.checkNotNull(description, "description"); 141 addAnnotation(description, EMPTY_ATTRIBUTES); 142 } 143 144 /** 145 * Adds an annotation to the {@code Span}. 146 * 147 * @param description the description of the annotation time event. 148 * @param attributes the attributes that will be added; these are associated with this annotation, 149 * not the {@code Span} as for {@link #putAttributes(Map)}. 150 * @since 0.5 151 */ addAnnotation(String description, Map<String, AttributeValue> attributes)152 public abstract void addAnnotation(String description, Map<String, AttributeValue> attributes); 153 154 /** 155 * Adds an annotation to the {@code Span}. 156 * 157 * @param annotation the annotations to add. 158 * @since 0.5 159 */ addAnnotation(Annotation annotation)160 public abstract void addAnnotation(Annotation annotation); 161 162 /** 163 * Adds a NetworkEvent to the {@code Span}. 164 * 165 * <p>This function is only intended to be used by RPC systems (either client or server), not by 166 * higher level applications. 167 * 168 * @param networkEvent the network event to add. 169 * @deprecated Use {@link #addMessageEvent}. 170 * @since 0.5 171 */ 172 @Deprecated addNetworkEvent(NetworkEvent networkEvent)173 public void addNetworkEvent(NetworkEvent networkEvent) { 174 addMessageEvent(BaseMessageEventUtils.asMessageEvent(networkEvent)); 175 } 176 177 /** 178 * Adds a MessageEvent to the {@code Span}. 179 * 180 * <p>This function can be used by higher level applications to record messaging event. 181 * 182 * <p>This method should always be overridden by users whose API versions are larger or equal to 183 * {@code 0.12}. 184 * 185 * @param messageEvent the message to add. 186 * @since 0.12 187 */ addMessageEvent(MessageEvent messageEvent)188 public void addMessageEvent(MessageEvent messageEvent) { 189 // Default implementation by invoking addNetworkEvent() so that any existing derived classes, 190 // including implementation and the mocked ones, do not need to override this method explicitly. 191 Utils.checkNotNull(messageEvent, "messageEvent"); 192 addNetworkEvent(BaseMessageEventUtils.asNetworkEvent(messageEvent)); 193 } 194 195 /** 196 * Adds a {@link Link} to the {@code Span}. 197 * 198 * <p>Used (for example) in batching operations, where a single batch handler processes multiple 199 * requests from different traces. 200 * 201 * @param link the link to add. 202 * @since 0.5 203 */ addLink(Link link)204 public abstract void addLink(Link link); 205 206 /** 207 * Sets the {@link Status} to the {@code Span}. 208 * 209 * <p>If used, this will override the default {@code Span} status. Default is {@link Status#OK}. 210 * 211 * <p>Only the value of the last call will be recorded, and implementations are free to ignore 212 * previous calls. If the status is set via {@link EndSpanOptions.Builder#setStatus(Status)} that 213 * will always be the last call. 214 * 215 * @param status the {@link Status} to set. 216 * @since 0.9 217 */ setStatus(Status status)218 public void setStatus(Status status) { 219 // Implemented as no-op for backwards compatibility (for example gRPC extends Span in tests). 220 // Implementation must override this method. 221 Utils.checkNotNull(status, "status"); 222 } 223 224 /** 225 * Marks the end of {@code Span} execution with the given options. 226 * 227 * <p>Only the timing of the first end call for a given {@code Span} will be recorded, and 228 * implementations are free to ignore all further calls. 229 * 230 * @param options the options to be used for the end of the {@code Span}. 231 * @since 0.5 232 */ end(EndSpanOptions options)233 public abstract void end(EndSpanOptions options); 234 235 /** 236 * Marks the end of {@code Span} execution with the default options. 237 * 238 * <p>Only the timing of the first end call for a given {@code Span} will be recorded, and 239 * implementations are free to ignore all further calls. 240 * 241 * @since 0.5 242 */ end()243 public final void end() { 244 end(EndSpanOptions.DEFAULT); 245 } 246 247 /** 248 * Returns the {@code SpanContext} associated with this {@code Span}. 249 * 250 * @return the {@code SpanContext} associated with this {@code Span}. 251 * @since 0.5 252 */ getContext()253 public final SpanContext getContext() { 254 return context; 255 } 256 257 /** 258 * Returns the options associated with this {@code Span}. 259 * 260 * @return the options associated with this {@code Span}. 261 * @since 0.5 262 */ getOptions()263 public final Set<Options> getOptions() { 264 return options; 265 } 266 267 /** 268 * Type of span. Can be used to specify additional relationships between spans in addition to a 269 * parent/child relationship. 270 * 271 * @since 0.14 272 */ 273 public enum Kind { 274 /** 275 * Indicates that the span covers server-side handling of an RPC or other remote request. 276 * 277 * @since 0.14 278 */ 279 SERVER, 280 281 /** 282 * Indicates that the span covers the client-side wrapper around an RPC or other remote request. 283 * 284 * @since 0.14 285 */ 286 CLIENT 287 } 288 } 289