in src/ServiceProfiler.EventPipe.Otel/Microsoft.ApplicationInsights.Profiler.Shared/Services/ActivityIdUtilities.cs [33:123]
private static unsafe string CreateActivityPathString(Guid guid)
{
var processID = ActivityPathProcessID(guid);
StringBuilder sb = new StringBuilder();
if (processID != 0)
{
sb.Append("/#"); // Use /# to mark the fact that the first number is a process ID.
sb.Append(processID);
}
else
{
sb.Append('/'); // Use // to start to make it easy to anchor
}
byte* bytePtr = (byte*)&guid;
byte* endPtr = bytePtr + 12;
char separator = '/';
while (bytePtr < endPtr)
{
uint nibble = (uint)(*bytePtr >> 4);
bool secondNibble = false; // are we reading the second nibble (low order bits) of the byte.
NextNibble:
if (nibble == (uint)NumberListCodes.End)
break;
if (nibble <= (uint)NumberListCodes.LastImmediateValue)
{
sb.Append('/').Append(nibble);
if (!secondNibble)
{
nibble = (uint)(*bytePtr & 0xF);
secondNibble = true;
goto NextNibble;
}
// We read the second nibble so we move on to the next byte.
bytePtr++;
continue;
}
else if (nibble == (uint)NumberListCodes.PrefixCode)
{
// This are the prefix codes. If the next nibble is MultiByte, then this is an overflow ID.
// we we denote with a $ instead of a / separator.
// Read the next nibble.
if (!secondNibble)
nibble = (uint)(*bytePtr & 0xF);
else
{
bytePtr++;
if (endPtr <= bytePtr)
break;
nibble = (uint)(*bytePtr >> 4);
}
if (nibble < (uint)NumberListCodes.MultiByte1)
{
// If the nibble is less than MultiByte we have not defined what that means
// For now we simply give up, and stop parsing. We could add more cases here...
return guid.ToString();
}
// If we get here we have a overflow ID, which is just like a normal ID but the separator is $
separator = '$';
// Fall into the Multi-byte decode case.
}
Debug.Assert((uint)NumberListCodes.MultiByte1 <= nibble);
// At this point we are decoding a multi-byte number, either a normal number or a
// At this point we are byte oriented, we are fetching the number as a stream of bytes.
uint numBytes = nibble - (uint)NumberListCodes.MultiByte1;
uint value = 0;
if (!secondNibble)
value = (uint)(*bytePtr & 0xF);
bytePtr++; // Advance to the value bytes
numBytes++; // Now numBytes is 1-4 and represents the number of bytes to read.
if (endPtr < bytePtr + numBytes)
break;
// Compute the number (little endian) (thus backwards).
for (int i = (int)numBytes - 1; 0 <= i; --i)
value = (value << 8) + bytePtr[i];
// Print the value
sb.Append(separator).Append(value);
bytePtr += numBytes; // Advance past the bytes.
}
sb.Append('/');
return sb.ToString();
}