blob: e63d4148eace17407b5c66cb1296dc4ccf71d5ec [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.htrace.core;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
/**
* Base interface for gathering and reporting statistics about a block of
* execution.
* <p/>
* Spans should form a directed acyclic graph structure. It should be possible
* to keep following the parents of a span until you arrive at a span with no
* parents.<p/>
*/
@JsonSerialize(using = Span.SpanSerializer.class)
public interface Span {
/**
* The block has completed, stop the clock
*/
void stop();
/**
* Get the start time, in milliseconds
*/
long getStartTimeMillis();
/**
* Get the stop time, in milliseconds
*/
long getStopTimeMillis();
/**
* Return the total amount of time elapsed since start was called, if running,
* or difference between stop and start
*/
long getAccumulatedMillis();
/**
* Has the span been started and not yet stopped?
*/
boolean isRunning();
/**
* Return a textual description of this span.<p/>
*
* Will never be null.
*/
String getDescription();
/**
* A pseudo-unique (random) number assigned to this span instance.<p/>
*
* The spanId is immutable and cannot be changed. It is safe to access this
* from multiple threads.
*/
SpanId getSpanId();
/**
* Create a child span of this span with the given description
* @deprecated Since 4.0.0. Use {@link MilliSpan.Builder}
*/
@Deprecated
Span child(String description);
@Override
String toString();
/**
* Returns the parent IDs of the span.<p/>
*
* The array will be empty if there are no parents.
*/
SpanId[] getParents();
/**
* Set the parents of this span.<p/>
*
* Any existing parents will be cleared by this call.
*/
void setParents(SpanId[] parents);
/**
* Add a data annotation associated with this span
*/
void addKVAnnotation(String key, String value);
/**
* Add a timeline annotation associated with this span
*/
void addTimelineAnnotation(String msg);
/**
* Get data associated with this span (read only)<p/>
*
* Will never be null.
*/
Map<String, String> getKVAnnotations();
/**
* Get any timeline annotations (read only)<p/>
*
* Will never be null.
*/
List<TimelineAnnotation> getTimelineAnnotations();
/**
* Return a unique id for the process from which this Span originated.<p/>
*
* Will never be null.
*/
String getTracerId();
/**
* Set the process id of a span.
*/
void setTracerId(String s);
/**
* Serialize to Json
*/
String toJson();
public static class SpanSerializer extends JsonSerializer<Span> {
@Override
public void serialize(Span span, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStartObject();
if (span.getSpanId().isValid()) {
jgen.writeStringField("a", span.getSpanId().toString());
}
if (span.getStartTimeMillis() != 0) {
jgen.writeNumberField("b", span.getStartTimeMillis());
}
if (span.getStopTimeMillis() != 0) {
jgen.writeNumberField("e", span.getStopTimeMillis());
}
if (!span.getDescription().isEmpty()) {
jgen.writeStringField("d", span.getDescription());
}
String tracerId = span.getTracerId();
if (!tracerId.isEmpty()) {
jgen.writeStringField("r", tracerId);
}
jgen.writeArrayFieldStart("p");
for (SpanId parent : span.getParents()) {
jgen.writeString(parent.toString());
}
jgen.writeEndArray();
Map<String, String> traceInfoMap = span.getKVAnnotations();
if (!traceInfoMap.isEmpty()) {
jgen.writeObjectFieldStart("n");
for (Map.Entry<String, String> e : traceInfoMap.entrySet()) {
jgen.writeStringField(e.getKey(), e.getValue());
}
jgen.writeEndObject();
}
List<TimelineAnnotation> timelineAnnotations =
span.getTimelineAnnotations();
if (!timelineAnnotations.isEmpty()) {
jgen.writeArrayFieldStart("t");
for (TimelineAnnotation tl : timelineAnnotations) {
jgen.writeStartObject();
jgen.writeNumberField("t", tl.getTime());
jgen.writeStringField("m", tl.getMessage());
jgen.writeEndObject();
}
jgen.writeEndArray();
}
jgen.writeEndObject();
}
}
}