use of org.hypertrace.core.datamodel.MetricValue in project hypertrace-ingester by hypertrace.
the class RawServiceViewGenerator method generateView.
@Override
List<RawServiceView> generateView(StructuredTrace structuredTrace, Map<String, Entity> entityMap, Map<ByteBuffer, Event> eventMap, Map<ByteBuffer, List<ByteBuffer>> parentToChildrenEventIds, Map<ByteBuffer, ByteBuffer> childToParentEventIds) {
List<RawServiceView> list = new ArrayList<>();
// Construct ApiTraceGraph and look at all the head spans within each ApiNode
ApiTraceGraph apiTraceGraph = ViewGeneratorState.getApiTraceGraph(structuredTrace);
List<ApiNode<Event>> apiNodes = apiTraceGraph.getApiNodeList();
for (ApiNode<Event> apiNode : apiNodes) {
Event event = apiNode.getHeadEvent();
if (EnrichedSpanUtils.containsServiceId(event)) {
RawServiceView.Builder builder = fastNewBuilder(RawServiceView.Builder.class);
builder.setTenantId(structuredTrace.getCustomerId());
builder.setTraceId(structuredTrace.getTraceId());
builder.setSpanId(event.getEventId());
builder.setParentSpanId(childToParentEventIds.get(event.getEventId()));
builder.setServiceName(EnrichedSpanUtils.getServiceName(event));
builder.setServiceId(EnrichedSpanUtils.getServiceId(event));
builder.setApiName(EnrichedSpanUtils.getApiName(event));
builder.setApiId(EnrichedSpanUtils.getApiId(event));
builder.setApiDiscoveryState(EnrichedSpanUtils.getApiDiscoveryState(event));
builder.setStartTimeMillis(event.getStartTimeMillis());
builder.setEndTimeMillis(event.getEndTimeMillis());
builder.setDurationMillis(event.getEndTimeMillis() - event.getStartTimeMillis());
builder.setTransactionName(getTransactionName(structuredTrace));
String spanType = EnrichedSpanUtils.getSpanType(event);
if (spanType != null) {
builder.setSpanKind(spanType);
}
Protocol protocol = EnrichedSpanUtils.getProtocol(event);
if (protocol == null || protocol == Protocol.PROTOCOL_UNSPECIFIED) {
/* In the view, we want to replace unknown with empty string instead
* for better representation in the UI and easier to filter */
builder.setProtocolName(EMPTY_STRING);
} else {
builder.setProtocolName(protocol.name());
}
builder.setStatusCode(EnrichedSpanUtils.getStatusCode(event));
// If this is an API entry boundary span, copy the error count from the event to the view
// because we want only API or service errors to be present in the view.
MetricValue errorMetric = event.getMetrics().getMetricMap().get(EnrichedSpanConstants.getValue(ErrorMetrics.ERROR_METRICS_ERROR_COUNT));
if (errorMetric != null && errorMetric.getValue() > 0.0d) {
builder.setErrorCount((int) errorMetric.getValue().doubleValue());
}
// Copy the exception count metric to view directly.
MetricValue exceptionMetric = event.getMetrics().getMetricMap().get(EnrichedSpanConstants.getValue(ErrorMetrics.ERROR_METRICS_EXCEPTION_COUNT));
if (exceptionMetric != null && exceptionMetric.getValue() > 0.0d) {
builder.setExceptionCount((int) exceptionMetric.getValue().doubleValue());
}
if (EnrichedSpanUtils.isEntrySpan(event)) {
builder.setNumCalls(1);
}
builder.setSpaceIds(EnrichedSpanUtils.getSpaceIds(event));
list.add(builder.build());
}
}
return list;
}
use of org.hypertrace.core.datamodel.MetricValue in project hypertrace-ingester by hypertrace.
the class SpanEventViewGenerator method generateViewBuilder.
private SpanEventView.Builder generateViewBuilder(Event event, ByteBuffer traceId, Map<ByteBuffer, Event> eventMap, Map<ByteBuffer, ByteBuffer> childToParentEventIds, Map<ByteBuffer, Event> exitSpanToCalleeApiEntrySpanMap) {
SpanEventView.Builder builder = fastNewBuilder(SpanEventView.Builder.class);
builder.setTenantId(event.getCustomerId());
builder.setSpanId(event.getEventId());
builder.setEventName(event.getEventName());
// api_trace_id
ByteBuffer apiEntrySpanId = EnrichedSpanUtils.getApiEntrySpanId(event, eventMap, childToParentEventIds);
builder.setApiTraceId(apiEntrySpanId);
if (event.getEventId().equals(apiEntrySpanId)) {
// set this count to 1 only if this span is the head of the Api Trace
builder.setApiTraceCount(1);
if (SpanAttributeUtils.containsAttributeKey(event, EnrichedSpanConstants.API_CALLEE_NAME_COUNT_ATTRIBUTE)) {
builder.setApiCalleeNameCount(SpanAttributeUtils.getAttributeValue(event, EnrichedSpanConstants.API_CALLEE_NAME_COUNT_ATTRIBUTE).getValueMap());
}
} else {
builder.setApiTraceCount(0);
}
// span_type
String spanType = getStringAttribute(event, EnrichedSpanConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_SPAN_TYPE));
if (spanType != null) {
builder.setSpanKind(spanType);
}
// parent_span_id
ByteBuffer parentEventId = childToParentEventIds.get(event.getEventId());
if (parentEventId != null) {
builder.setParentSpanId(parentEventId);
}
// trace_id
builder.setTraceId(traceId);
// service_id, service_name
builder.setServiceId(EnrichedSpanUtils.getServiceId(event));
builder.setServiceName(EnrichedSpanUtils.getServiceName(event));
// api_id, api_name, api_discovery_state
builder.setApiId(EnrichedSpanUtils.getApiId(event));
builder.setApiName(EnrichedSpanUtils.getApiName(event));
builder.setApiDiscoveryState(EnrichedSpanUtils.getApiDiscoveryState(event));
// entry_api_id
Event entryApiSpan = EnrichedSpanUtils.getApiEntrySpan(event, eventMap, childToParentEventIds);
if (entryApiSpan != null) {
builder.setEntryApiId(EnrichedSpanUtils.getApiId(entryApiSpan));
}
// display entity and span names
builder.setDisplayEntityName(getDisplayEntityName(event, exitSpanToCalleeApiEntrySpanMap));
builder.setDisplaySpanName(getDisplaySpanName(event, exitSpanToCalleeApiEntrySpanMap));
// protocol_name
Protocol protocol = EnrichedSpanUtils.getProtocol(event);
if (protocol == null || protocol == Protocol.PROTOCOL_UNSPECIFIED) {
/* In the view, we want to replace unknown with empty string instead
* for better representation in the UI and easier to filter */
builder.setProtocolName(EMPTY_STRING);
} else {
builder.setProtocolName(EnrichedSpanConstants.getValue(protocol));
}
builder.setTags(getAttributeMap(event.getAttributes()));
// request_url
builder.setRequestUrl(getRequestUrl(event, protocol));
// status_code
builder.setStatusCode(EnrichedSpanUtils.getStatusCode(event));
builder.setStatus(EnrichedSpanUtils.getStatus(event));
builder.setStatusMessage(EnrichedSpanUtils.getStatusMessage(event));
// set boundary type with default value as empty string to avoid null value
builder.setApiBoundaryType(getStringAttribute(event, EnrichedSpanConstants.getValue(Api.API_BOUNDARY_TYPE)));
// start_time_millis, end_time_millis, duration_millis
builder.setStartTimeMillis(event.getStartTimeMillis());
builder.setEndTimeMillis(event.getEndTimeMillis());
builder.setDurationMillis(event.getEndTimeMillis() - event.getStartTimeMillis());
// error count
MetricValue errorMetric = event.getMetrics().getMetricMap().get(ERROR_COUNT_CONSTANT);
if (errorMetric != null && errorMetric.getValue() > 0.0d) {
builder.setErrorCount((int) errorMetric.getValue().doubleValue());
}
builder.setSpans(1);
MetricValue exceptionMetric = event.getMetrics().getMetricMap().get(EXCEPTION_COUNT_CONSTANT);
if (exceptionMetric != null && exceptionMetric.getValue() > 0.0d) {
builder.setExceptionCount((int) exceptionMetric.getValue().doubleValue());
}
builder.setSpaceIds(EnrichedSpanUtils.getSpaceIds(event));
builder.setApiExitCalls(Integer.parseInt(SpanAttributeUtils.getStringAttributeWithDefault(event, EnrichedSpanConstants.API_EXIT_CALLS_ATTRIBUTE, "0")));
builder.setApiTraceErrorSpanCount(Integer.parseInt(SpanAttributeUtils.getStringAttributeWithDefault(event, EnrichedSpanConstants.API_TRACE_ERROR_SPAN_COUNT_ATTRIBUTE, "0")));
return builder;
}
use of org.hypertrace.core.datamodel.MetricValue in project hypertrace-ingester by hypertrace.
the class ErrorsAndExceptionsEnricherTest method createMockTestEvent.
private Event createMockTestEvent() {
Map<String, AttributeValue> map = new HashMap<>();
Map<String, MetricValue> metricMap = new HashMap<>();
map.put("span.kind", AttributeValue.newBuilder().setValue("server").build());
map.put("error", AttributeValue.newBuilder().setValue("true").build());
map.put("SPAN_TYPE", AttributeValue.newBuilder().setValue("ENTRY").build());
metricMap.put("Duration", MetricValue.newBuilder().setValue(4.0).build());
Event event = Event.newBuilder().setCustomerId("customer1").setEventId(ByteBuffer.wrap("bdf03dfabf5c70f9".getBytes())).setEntityIdList(Arrays.asList("4bfca8f7-4974-36a4-9385-dd76bf5c8824")).setEnrichedAttributes(Attributes.newBuilder().setAttributeMap(map).build()).setAttributes(Attributes.newBuilder().setAttributeMap(map).build()).setEventName("test-event").setStartTimeMillis(1566869077746L).setEndTimeMillis(1566869077750L).setMetrics(Metrics.newBuilder().setMetricMap(metricMap).build()).setEventRefList(Collections.emptyList()).build();
return event;
}
use of org.hypertrace.core.datamodel.MetricValue in project hypertrace-ingester by hypertrace.
the class ErrorsAndExceptionsEnricher method enrichTrace.
@Override
public void enrichTrace(StructuredTrace trace) {
// TODO: There could be other cases where the client which is initiating this transaction
// has errored out but the entry span in transaction might be fine (server responded but
// client couldn't process it). Those cases should be handled in future.
ApiTraceGraph apiTraceGraph = ApiTraceGraphBuilder.buildGraph(trace);
for (ApiNode<Event> apiNode : apiTraceGraph.getApiNodeList()) {
Optional<Event> entryEvent = apiNode.getEntryApiBoundaryEvent();
int apiTraceErrorCount = (int) apiNode.getEvents().stream().filter(this::findIfEventHasError).count();
if (entryEvent.isPresent()) {
addEnrichedAttribute(entryEvent.get(), EnrichedSpanConstants.API_TRACE_ERROR_SPAN_COUNT_ATTRIBUTE, AttributeValueCreator.create(apiTraceErrorCount));
}
}
// Find the earliest Event from this trace and check if that's an ENTRY type.
Event earliestEvent = getEarliestEvent(trace);
if (EnrichedSpanUtils.isEntrySpan(earliestEvent)) {
LOG.debug("Found earliest Event in this trace. It is {}", earliestEvent);
Metrics metrics = earliestEvent.getMetrics();
if (metrics != null && metrics.getMetricMap() != null && metrics.getMetricMap().containsKey(EnrichedSpanConstants.getValue(ErrorMetrics.ERROR_METRICS_ERROR_COUNT))) {
trace.getAttributes().getAttributeMap().put(EnrichedSpanConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_TRANSACTION_HAS_ERROR), AttributeValueCreator.create(true));
}
}
// Count the no. of errors and exceptions in this trace overall. These need not have caused
// the trace to error out but it's a good metric to track anyways.
// Trace is considered to have an error if there is an error in the entry span only.
double exceptionCount = 0.0d;
double errorCount = 0.0d;
for (Event event : trace.getEventList()) {
Map<String, MetricValue> metricMap = event.getMetrics().getMetricMap();
if (metricMap != null && metricMap.containsKey(EnrichedSpanConstants.getValue(ErrorMetrics.ERROR_METRICS_ERROR_COUNT))) {
errorCount += metricMap.get(EnrichedSpanConstants.getValue(ErrorMetrics.ERROR_METRICS_ERROR_COUNT)).getValue();
}
if (metricMap != null && metricMap.containsKey(EnrichedSpanConstants.getValue(ErrorMetrics.ERROR_METRICS_EXCEPTION_COUNT))) {
exceptionCount += metricMap.get(EnrichedSpanConstants.getValue(ErrorMetrics.ERROR_METRICS_EXCEPTION_COUNT)).getValue();
}
}
if (exceptionCount > 0.0d) {
trace.getMetrics().getMetricMap().put(EnrichedSpanConstants.getValue(ErrorMetrics.ERROR_METRICS_TOTAL_SPANS_WITH_EXCEPTIONS), MetricValueCreator.create(exceptionCount));
}
if (errorCount > 0.0d) {
trace.getMetrics().getMetricMap().put(EnrichedSpanConstants.getValue(ErrorMetrics.ERROR_METRICS_TOTAL_SPANS_WITH_ERRORS), MetricValueCreator.create(errorCount));
}
}
use of org.hypertrace.core.datamodel.MetricValue in project hypertrace-ingester by hypertrace.
the class EventBuilder method buildEvent.
public static Event buildEvent(String tenantId, JaegerSpanInternalModel.Span jaegerSpan, Optional<String> tenantIdKey) {
Event.Builder eventBuilder = fastNewBuilder(Event.Builder.class);
eventBuilder.setCustomerId(tenantId);
eventBuilder.setEventId(jaegerSpan.getSpanId().asReadOnlyByteBuffer());
eventBuilder.setEventName(jaegerSpan.getOperationName());
// time related stuff
long startTimeMillis = Timestamps.toMillis(jaegerSpan.getStartTime());
eventBuilder.setStartTimeMillis(startTimeMillis);
long endTimeMillis = Timestamps.toMillis(Timestamps.add(jaegerSpan.getStartTime(), jaegerSpan.getDuration()));
eventBuilder.setEndTimeMillis(endTimeMillis);
// SPAN REFS
List<JaegerSpanInternalModel.SpanRef> referencesList = jaegerSpan.getReferencesList();
if (referencesList.size() > 0) {
eventBuilder.setEventRefList(new ArrayList<>());
// Convert the reflist to a set to remove duplicate references. This has been observed in the
// field.
Set<JaegerSpanInternalModel.SpanRef> referencesSet = new HashSet<>(referencesList);
for (JaegerSpanInternalModel.SpanRef spanRef : referencesSet) {
EventRef.Builder builder = fastNewBuilder(EventRef.Builder.class);
builder.setTraceId(spanRef.getTraceId().asReadOnlyByteBuffer());
builder.setEventId(spanRef.getSpanId().asReadOnlyByteBuffer());
builder.setRefType(EventRefType.valueOf(spanRef.getRefType().toString()));
eventBuilder.getEventRefList().add(builder.build());
}
}
// span attributes to event attributes
Map<String, AttributeValue> attributeFieldMap = new HashMap<>();
eventBuilder.setAttributesBuilder(fastNewBuilder(Attributes.Builder.class).setAttributeMap(attributeFieldMap));
List<JaegerSpanInternalModel.KeyValue> tagsList = jaegerSpan.getTagsList();
// https://github.com/hypertrace/hypertrace/issues/245
for (JaegerSpanInternalModel.KeyValue keyValue : tagsList) {
// Convert all attributes to lower case so that we don't have to
// deal with the case sensitivity across different layers in the
// platform.
String key = keyValue.getKey().toLowerCase();
// Do not add the tenant id to the tags.
if ((tenantIdKey.isPresent() && key.equals(tenantIdKey.get()))) {
continue;
}
attributeFieldMap.put(key, JaegerHTTagsConverter.createFromJaegerKeyValue(keyValue));
}
// Jaeger Fields - flags, warnings, logs, jaeger service name in the Process
JaegerFields.Builder jaegerFieldsBuilder = eventBuilder.getJaegerFieldsBuilder();
// FLAGS
jaegerFieldsBuilder.setFlags(jaegerSpan.getFlags());
// WARNINGS
ProtocolStringList warningsList = jaegerSpan.getWarningsList();
if (warningsList.size() > 0) {
jaegerFieldsBuilder.setWarnings(warningsList);
}
// Jaeger service name can come from either first class field in Span or the tag
// `jaeger.servicename`
String serviceName = !StringUtils.isEmpty(jaegerSpan.getProcess().getServiceName()) ? jaegerSpan.getProcess().getServiceName() : attributeFieldMap.containsKey(OLD_JAEGER_SERVICENAME_KEY) ? attributeFieldMap.get(OLD_JAEGER_SERVICENAME_KEY).getValue() : StringUtils.EMPTY;
if (!StringUtils.isEmpty(serviceName)) {
eventBuilder.setServiceName(serviceName);
// in case `jaeger.servicename` is present in the map, remove it
attributeFieldMap.remove(OLD_JAEGER_SERVICENAME_KEY);
attributeFieldMap.put(RawSpanConstants.getValue(JaegerAttribute.JAEGER_ATTRIBUTE_SERVICE_NAME), AttributeValueCreator.create(serviceName));
}
// EVENT METRICS
Map<String, MetricValue> metricMap = new HashMap<>();
MetricValue durationMetric = fastNewBuilder(MetricValue.Builder.class).setValue((double) (endTimeMillis - startTimeMillis)).build();
metricMap.put("Duration", durationMetric);
eventBuilder.setMetrics(fastNewBuilder(Metrics.Builder.class).setMetricMap(metricMap).build());
return eventBuilder.build();
}
Aggregations