private static String sanitizeParentId(String parentId) { String result = parentId; if (!isHierarchicalId(parentId)) { result = "|" + result; } char lastChar = parentId.charAt(parentId.length() - 1); if (lastChar != '.' && lastChar != '_') { result = result + '.'; } return result; }
rootId = generateRootId(); currentId = '|' + rootId + '.'; } else { parentId = requestId; rootId = extractRootId(parentId); currentId = generateId(parentId); resolveCorrelationContext(request, requestTelemetry); addTargetAppIdForResponseHeader(response);
/** * Given a request context, it generates a new dependency target, possibly including the appId found in * the given Request-Context. * @param requestContext - the Request-Context header value * @return the dependency target */ public static String generateChildDependencyTarget(String requestContext) { if (requestContext == null || requestContext.isEmpty()) { InternalLogger.INSTANCE.trace("generateChildDependencyTarget: won't continue as requestContext is null or empty."); return ""; } String instrumentationKey = TelemetryConfiguration.getActive().getInstrumentationKey(); if (instrumentationKey == null || instrumentationKey.isEmpty()) { InternalLogger.INSTANCE.error("Failed to generate target correlation. InstrumentationKey is null or empty."); return ""; } String target = generateSourceTargetCorrelation(instrumentationKey, requestContext); if (target == null) { InternalLogger.INSTANCE.warn("Target value is null and hence returning empty string"); return ""; // we want an empty string instead of null so it plays nicer with bytecode injection } return target; }
private static String generateId(String parentId) { String sanitizedParentId = sanitizeParentId(parentId); String suffix = generateSuffix(); //handle overflow if (sanitizedParentId.length() + suffix.length() > REQUESTID_MAXLENGTH) { return shortenId(sanitizedParentId, suffix); } return sanitizedParentId + suffix + "_"; }
TraceContextCorrelation.resolveRequestSource((HttpServletRequest) req, telemetry, instrumentationKey); } else { TelemetryCorrelationUtils.resolveRequestSource((HttpServletRequest) req, telemetry, instrumentationKey);
} else { TelemetryCorrelationUtils.resolveCorrelation(request, response, telemetry);
TelemetryCorrelationUtils.resolveCorrelation(request, response, requestTelemetry); Assert.assertTrue(TelemetryCorrelationUtils.isHierarchicalId(requestTelemetry.getId()));
@Test public void testChildRequestDependencyIdGenerationWithNonHierarchicalRequestId() { //setup Hashtable<String, String> headers = new Hashtable<String, String>(); String incomingId = "guid"; headers.put(TelemetryCorrelationUtils.CORRELATION_HEADER_NAME, incomingId); HttpServletRequest request = ServletUtils.createServletRequestWithHeaders(headers); HttpServletResponse response = (HttpServletResponse)ServletUtils.generateDummyServletResponse(); RequestTelemetryContext context = new RequestTelemetryContext(DateTimeUtils.getDateTimeNow().getTime()); ThreadContext.setRequestTelemetryContext(context); RequestTelemetry requestTelemetry = context.getHttpRequestTelemetry(); //run TelemetryCorrelationUtils.resolveCorrelation(request, response, requestTelemetry); String childId = TelemetryCorrelationUtils.generateChildDependencyId(); //Incoming ID is non-hierarchical, so we must not modidy outgoing (child) id Assert.assertNotNull(childId); Assert.assertEquals(incomingId, childId); }
private static String shortenId(String parentId, String suffix) { // ported from .NET's System.Diagnostics.Activity.cs implementation: // https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs int trimPosition = REQUESTID_MAXLENGTH - 9; // make room for suffix + delimiter while (trimPosition > 1) { if (parentId.charAt(trimPosition - 1) == '.' || parentId.charAt(trimPosition - 1) == '_') break; trimPosition--; } // parentId is not a valid requestId, so generate one. if (trimPosition == 1) { return "|" + generateRootId() + "."; } return parentId.substring(0, trimPosition) + suffix + '#'; }
/** * This method processes the legacy Request-ID header for backward compatibility. * @param request * @return */ private static Traceparent processLegacyCorrelation(HttpServletRequest request) { String requestId = request.getHeader(TelemetryCorrelationUtils.CORRELATION_HEADER_NAME); try { if (requestId != null && !requestId.isEmpty()) { String legacyOperationId = TelemetryCorrelationUtils.extractRootId(requestId); RequestTelemetry requestTelemetry = ThreadContext.getRequestTelemetryContext().getHttpRequestTelemetry(); requestTelemetry.getContext().getProperties().putIfAbsent("ai_legacyRootID", legacyOperationId); requestTelemetry.getContext().getOperation().setParentId(requestId); return new Traceparent(0, legacyOperationId, null, 0); } } catch (Exception e) { InternalLogger.INSTANCE.error(String.format("unable to create traceparent from legacy request-id header" + " %s", ExceptionUtils.getStackTrace(e))); } return null; }
String appId = getKeyValueHeaderValue(requestContext, REQUEST_CONTEXT_HEADER_APPID_KEY); String roleName = getKeyValueHeaderValue(requestContext, REQUEST_CONTEXT_HEADER_ROLENAME_KEY);
TraceContextCorrelation.resolveRequestSource((HttpServletRequest) req, telemetry, instrumentationKey); } else { TelemetryCorrelationUtils.resolveRequestSource((HttpServletRequest) req, telemetry, instrumentationKey);
} else { TelemetryCorrelationUtils.resolveCorrelation(request, response, telemetry);
private static String generateId(String parentId) { String sanitizedParentId = sanitizeParentId(parentId); String suffix = generateSuffix(); //handle overflow if (sanitizedParentId.length() + suffix.length() > REQUESTID_MAXLENGTH) { return shortenId(sanitizedParentId, suffix); } return sanitizedParentId + suffix + "_"; }
TelemetryCorrelationUtils.resolveCorrelation(request, response, requestTelemetry); Assert.assertTrue(TelemetryCorrelationUtils.isHierarchicalId(requestTelemetry.getId()));
@Test public void testChildRequestDependencyIdGenerationWithNoParentId() { //setup - make sure no RequestId is set (i.e. no parent) Hashtable<String, String> headers = new Hashtable<String, String>(); HttpServletRequest request = ServletUtils.createServletRequestWithHeaders(headers); HttpServletResponse response = (HttpServletResponse)ServletUtils.generateDummyServletResponse(); RequestTelemetryContext context = new RequestTelemetryContext(DateTimeUtils.getDateTimeNow().getTime()); ThreadContext.setRequestTelemetryContext(context); RequestTelemetry requestTelemetry = context.getHttpRequestTelemetry(); //run TelemetryCorrelationUtils.resolveCorrelation(request, response, requestTelemetry); String childId = TelemetryCorrelationUtils.generateChildDependencyId(); //validate we have generated proper ID's Assert.assertNotNull(childId); Assert.assertEquals(requestTelemetry.getId() + "1.", childId); }
private static String shortenId(String parentId, String suffix) { // ported from .NET's System.Diagnostics.Activity.cs implementation: // https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs int trimPosition = REQUESTID_MAXLENGTH - 9; // make room for suffix + delimiter while (trimPosition > 1) { if (parentId.charAt(trimPosition - 1) == '.' || parentId.charAt(trimPosition - 1) == '_') break; trimPosition--; } // parentId is not a valid requestId, so generate one. if (trimPosition == 1) { return "|" + generateRootId() + "."; } return parentId.substring(0, trimPosition) + suffix + '#'; }
/** * This method processes the legacy Request-ID header for backward compatibility. * @param request * @return */ private static Traceparent processLegacyCorrelation(HttpServletRequest request) { String requestId = request.getHeader(TelemetryCorrelationUtils.CORRELATION_HEADER_NAME); try { if (requestId != null && !requestId.isEmpty()) { String legacyOperationId = TelemetryCorrelationUtils.extractRootId(requestId); RequestTelemetry requestTelemetry = ThreadContext.getRequestTelemetryContext().getHttpRequestTelemetry(); requestTelemetry.getContext().getProperties().putIfAbsent("ai_legacyRootID", legacyOperationId); requestTelemetry.getContext().getOperation().setParentId(requestId); return new Traceparent(0, legacyOperationId, null, 0); } } catch (Exception e) { InternalLogger.INSTANCE.error(String.format("unable to create traceparent from legacy request-id header" + " %s", ExceptionUtils.getStackTrace(e))); } return null; }
String appId = getKeyValueHeaderValue(requestContext, REQUEST_CONTEXT_HEADER_APPID_KEY); String roleName = getKeyValueHeaderValue(requestContext, REQUEST_CONTEXT_HEADER_ROLENAME_KEY);
rootId = generateRootId(); currentId = '|' + rootId + '.'; } else { parentId = requestId; rootId = extractRootId(parentId); currentId = generateId(parentId); resolveCorrelationContext(request, requestTelemetry); addTargetAppIdForResponseHeader(response);