Search in sources :

Example 1 with MetricValue

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;
}
Also used : MetricValue(org.hypertrace.core.datamodel.MetricValue) ArrayList(java.util.ArrayList) Event(org.hypertrace.core.datamodel.Event) ApiTraceGraph(org.hypertrace.traceenricher.trace.util.ApiTraceGraph) ApiNode(org.hypertrace.core.datamodel.shared.ApiNode) Protocol(org.hypertrace.traceenricher.enrichedspan.constants.v1.Protocol) RawServiceView(org.hypertrace.viewgenerator.api.RawServiceView)

Example 2 with MetricValue

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;
}
Also used : MetricValue(org.hypertrace.core.datamodel.MetricValue) SpanEventView(org.hypertrace.viewgenerator.api.SpanEventView) Event(org.hypertrace.core.datamodel.Event) Protocol(org.hypertrace.traceenricher.enrichedspan.constants.v1.Protocol) ByteBuffer(java.nio.ByteBuffer)

Example 3 with MetricValue

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;
}
Also used : AttributeValue(org.hypertrace.core.datamodel.AttributeValue) MetricValue(org.hypertrace.core.datamodel.MetricValue) HashMap(java.util.HashMap) Event(org.hypertrace.core.datamodel.Event)

Example 4 with MetricValue

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));
    }
}
Also used : Metrics(org.hypertrace.core.datamodel.Metrics) ErrorMetrics(org.hypertrace.traceenricher.enrichedspan.constants.v1.ErrorMetrics) MetricValue(org.hypertrace.core.datamodel.MetricValue) Event(org.hypertrace.core.datamodel.Event) ApiTraceGraph(org.hypertrace.traceenricher.trace.util.ApiTraceGraph)

Example 5 with MetricValue

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();
}
Also used : AttributeValue(org.hypertrace.core.datamodel.AttributeValue) HashMap(java.util.HashMap) JaegerSpanInternalModel(io.jaegertracing.api_v2.JaegerSpanInternalModel) AvroBuilderCache.fastNewBuilder(org.hypertrace.core.datamodel.shared.AvroBuilderCache.fastNewBuilder) Attributes(org.hypertrace.core.datamodel.Attributes) MetricValue(org.hypertrace.core.datamodel.MetricValue) EventRef(org.hypertrace.core.datamodel.EventRef) HashSet(java.util.HashSet) ProtocolStringList(com.google.protobuf.ProtocolStringList) JaegerFields(org.hypertrace.core.datamodel.eventfields.jaeger.JaegerFields) Event(org.hypertrace.core.datamodel.Event)

Aggregations

Event (org.hypertrace.core.datamodel.Event)5 MetricValue (org.hypertrace.core.datamodel.MetricValue)5 HashMap (java.util.HashMap)2 AttributeValue (org.hypertrace.core.datamodel.AttributeValue)2 Protocol (org.hypertrace.traceenricher.enrichedspan.constants.v1.Protocol)2 ApiTraceGraph (org.hypertrace.traceenricher.trace.util.ApiTraceGraph)2 ProtocolStringList (com.google.protobuf.ProtocolStringList)1 JaegerSpanInternalModel (io.jaegertracing.api_v2.JaegerSpanInternalModel)1 ByteBuffer (java.nio.ByteBuffer)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 Attributes (org.hypertrace.core.datamodel.Attributes)1 EventRef (org.hypertrace.core.datamodel.EventRef)1 Metrics (org.hypertrace.core.datamodel.Metrics)1 JaegerFields (org.hypertrace.core.datamodel.eventfields.jaeger.JaegerFields)1 ApiNode (org.hypertrace.core.datamodel.shared.ApiNode)1 AvroBuilderCache.fastNewBuilder (org.hypertrace.core.datamodel.shared.AvroBuilderCache.fastNewBuilder)1 ErrorMetrics (org.hypertrace.traceenricher.enrichedspan.constants.v1.ErrorMetrics)1 RawServiceView (org.hypertrace.viewgenerator.api.RawServiceView)1 SpanEventView (org.hypertrace.viewgenerator.api.SpanEventView)1