Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record StackTraceHiddenAttribute when collecting stacks and exceptions #7493

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,18 @@ public void ClassDescription(
ulong ModuleId,
uint Token,
uint Flags,
uint StackTraceHidden,
ulong[] TypeArgs)
{
Span<EventData> data = stackalloc EventData[5];
Span<EventData> data = stackalloc EventData[6];
Span<byte> typeArgsSpan = stackalloc byte[GetArrayDataSize(TypeArgs)];
FillArrayData(typeArgsSpan, TypeArgs);

SetValue(ref data[NameIdentificationEvents.ClassDescPayloads.ClassId], ClassId);
SetValue(ref data[NameIdentificationEvents.ClassDescPayloads.ModuleId], ModuleId);
SetValue(ref data[NameIdentificationEvents.ClassDescPayloads.Token], Token);
SetValue(ref data[NameIdentificationEvents.ClassDescPayloads.Flags], Flags);
SetValue(ref data[NameIdentificationEvents.ClassDescPayloads.StackTraceHidden], StackTraceHidden);
SetValue(ref data[NameIdentificationEvents.ClassDescPayloads.TypeArgs], typeArgsSpan);

WriteEventWithFlushing(ExceptionEvents.EventIds.ClassDescription, data);
Expand All @@ -101,11 +103,12 @@ public void FunctionDescription(
ulong ClassId,
uint ClassToken,
ulong ModuleId,
uint StackTraceHidden,
string Name,
ulong[] TypeArgs,
ulong[] ParameterTypes)
{
Span<EventData> data = stackalloc EventData[8];
Span<EventData> data = stackalloc EventData[9];
using PinnedData namePinned = PinnedData.Create(Name);
Span<byte> typeArgsSpan = stackalloc byte[GetArrayDataSize(TypeArgs)];
FillArrayData(typeArgsSpan, TypeArgs);
Expand All @@ -117,6 +120,7 @@ public void FunctionDescription(
SetValue(ref data[NameIdentificationEvents.FunctionDescPayloads.ClassId], ClassId);
SetValue(ref data[NameIdentificationEvents.FunctionDescPayloads.ClassToken], ClassToken);
SetValue(ref data[NameIdentificationEvents.FunctionDescPayloads.ModuleId], ModuleId);
SetValue(ref data[NameIdentificationEvents.FunctionDescPayloads.StackTraceHidden], StackTraceHidden);
SetValue(ref data[NameIdentificationEvents.FunctionDescPayloads.Name], namePinned);
SetValue(ref data[NameIdentificationEvents.FunctionDescPayloads.TypeArgs], typeArgsSpan);
SetValue(ref data[NameIdentificationEvents.FunctionDescPayloads.ParameterTypes], parameterTypesSpan);
Expand Down Expand Up @@ -160,16 +164,18 @@ public void TokenDescription(
ulong ModuleId,
uint Token,
uint OuterToken,
uint StackTraceHidden,
string Name,
string Namespace)
{
Span<EventData> data = stackalloc EventData[5];
Span<EventData> data = stackalloc EventData[6];
using PinnedData namePinned = PinnedData.Create(Name);
using PinnedData namespacePinned = PinnedData.Create(Namespace);

SetValue(ref data[NameIdentificationEvents.TokenDescPayloads.ModuleId], ModuleId);
SetValue(ref data[NameIdentificationEvents.TokenDescPayloads.Token], Token);
SetValue(ref data[NameIdentificationEvents.TokenDescPayloads.OuterToken], OuterToken);
SetValue(ref data[NameIdentificationEvents.TokenDescPayloads.StackTraceHidden], StackTraceHidden);
SetValue(ref data[NameIdentificationEvents.TokenDescPayloads.Name], namePinned);
SetValue(ref data[NameIdentificationEvents.TokenDescPayloads.Namespace], namespacePinned);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.Diagnostics.Monitoring.StartupHook.Exceptions.Identification;
using System;

namespace Microsoft.Diagnostics.Monitoring.StartupHook.Exceptions.Eventing
{
Expand All @@ -22,6 +23,7 @@ public override void OnClassData(ulong classId, ClassData data)
data.ModuleId,
data.Token,
(uint)data.Flags,
Convert.ToUInt32(data.StackTraceHidden),
data.TypeArgs);
}

Expand All @@ -42,6 +44,7 @@ public override void OnFunctionData(ulong functionId, FunctionData data)
data.ParentClass,
data.ParentClassToken,
data.ModuleId,
Convert.ToUInt32(data.StackTraceHidden),
data.Name,
data.TypeArgs,
data.ParameterTypes);
Expand Down Expand Up @@ -69,6 +72,7 @@ public override void OnTokenData(ulong moduleId, uint typeToken, TokenData data)
moduleId,
typeToken,
data.OuterToken,
Convert.ToUInt32(data.StackTraceHidden),
data.Name,
data.Namespace);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;

Expand Down Expand Up @@ -96,6 +97,13 @@ public ulong GetOrAdd(MethodBase method)
parentClassToken = Convert.ToUInt32(method.DeclaringType.MetadataToken);
}

bool stackTraceHidden = false;
try
{
stackTraceHidden = method.GetCustomAttributes<StackTraceHiddenAttribute>(inherit: false).Any();
}
catch (Exception) { }

// RTDynamicMethod does not implement GetGenericArguments.
Type[] genericArguments = Array.Empty<Type>();
try
Expand All @@ -111,8 +119,8 @@ public ulong GetOrAdd(MethodBase method)
parentClassToken,
GetOrAdd(method.Module),
GetOrAdd(genericArguments),
GetOrAdd(method.GetParameters())
);
GetOrAdd(method.GetParameters()),
stackTraceHidden);

if (_nameCache.FunctionData.TryAdd(methodId, data))
{
Expand Down Expand Up @@ -205,11 +213,20 @@ public ulong GetOrAdd(Type type)
{
ulong moduleId = GetOrAdd(type.Module);
uint typeToken = Convert.ToUInt32(type.MetadataToken);

bool stackTraceHidden = false;
try
{
stackTraceHidden = type.GetCustomAttributes<StackTraceHiddenAttribute>(inherit: false).Any();
}
catch (Exception) { }

ClassData classData = new(
typeToken,
moduleId,
ClassFlags.None,
GetOrAdd(type.GetGenericArguments()));
GetOrAdd(type.GetGenericArguments()),
stackTraceHidden);

if (!_nameCache.ClassData.TryAdd(classId, classData))
break;
Expand All @@ -228,7 +245,8 @@ public ulong GetOrAdd(Type type)
TokenData tokenData = new(
type.Name,
null == type.DeclaringType ? type.Namespace ?? string.Empty : string.Empty,
parentClassToken);
parentClassToken,
stackTraceHidden);

if (!_nameCache.TokenData.TryAdd(key, tokenData))
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ private void Callback(TraceEvent action)
action.GetPayload<uint>(NameIdentificationEvents.FunctionDescPayloads.ClassToken),
action.GetPayload<ulong>(NameIdentificationEvents.FunctionDescPayloads.ModuleId),
action.GetPayload<ulong[]>(NameIdentificationEvents.FunctionDescPayloads.TypeArgs) ?? Array.Empty<ulong>(),
action.GetPayload<ulong[]>(NameIdentificationEvents.FunctionDescPayloads.ParameterTypes) ?? Array.Empty<ulong>()
action.GetPayload<ulong[]>(NameIdentificationEvents.FunctionDescPayloads.ParameterTypes) ?? Array.Empty<ulong>(),
action.GetBoolPayload(NameIdentificationEvents.FunctionDescPayloads.StackTraceHidden)
);

_result.NameCache.FunctionData.TryAdd(id, functionData);
Expand All @@ -126,7 +127,8 @@ private void Callback(TraceEvent action)
action.GetPayload<uint>(NameIdentificationEvents.ClassDescPayloads.Token),
action.GetPayload<ulong>(NameIdentificationEvents.ClassDescPayloads.ModuleId),
(ClassFlags)action.GetPayload<uint>(NameIdentificationEvents.ClassDescPayloads.Flags),
action.GetPayload<ulong[]>(NameIdentificationEvents.ClassDescPayloads.TypeArgs) ?? Array.Empty<ulong>()
action.GetPayload<ulong[]>(NameIdentificationEvents.ClassDescPayloads.TypeArgs) ?? Array.Empty<ulong>(),
action.GetBoolPayload(NameIdentificationEvents.ClassDescPayloads.StackTraceHidden)
);

_result.NameCache.ClassData.TryAdd(id, classData);
Expand All @@ -148,7 +150,8 @@ private void Callback(TraceEvent action)
var tokenData = new TokenData(
action.GetPayload<string>(NameIdentificationEvents.TokenDescPayloads.Name),
action.GetPayload<string>(NameIdentificationEvents.TokenDescPayloads.Namespace),
action.GetPayload<uint>(NameIdentificationEvents.TokenDescPayloads.OuterToken)
action.GetPayload<uint>(NameIdentificationEvents.TokenDescPayloads.OuterToken),
action.GetBoolPayload(NameIdentificationEvents.TokenDescPayloads.StackTraceHidden)
);

_result.NameCache.TokenData.TryAdd(new ModuleScopedToken(modId, token), tokenData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,18 @@ internal enum ClassFlags : uint
/// <param name="ModuleId">The identifier of the module that contains the class.</param>
/// <param name="Flags">The flags for the class.</param>
/// <param name="TypeArgs">The class identifiers of the generic type arguments of the class.</param>
/// <param name="StackTraceHidden">If the class has <see cref="StackTraceHiddenAttribute"/>.</param>
/// <remarks>
/// The name of the class can be retrieved from the corresponding <see cref="TokenData"/>.
/// </remarks>
internal sealed record class ClassData(uint Token, ulong ModuleId, ClassFlags Flags, ulong[] TypeArgs);
internal sealed record class ClassData(uint Token, ulong ModuleId, ClassFlags Flags, ulong[] TypeArgs, bool StackTraceHidden);

/// <param name="Name">The name of the token.</param>
/// <param name="Namespace">The namespace of the Name.</param>
/// <param name="OuterToken">The metadata token of the parent container.</param>
/// <param name="StackTraceHidden">If the token has <see cref="StackTraceHiddenAttribute"/>.</param>
[DebuggerDisplay("{Name}")]
internal sealed record class TokenData(string Name, string Namespace, uint OuterToken);
internal sealed record class TokenData(string Name, string Namespace, uint OuterToken, bool StackTraceHidden);

/// <param name="Name">The name of the function.</param>
/// <param name="MethodToken">The method token of the function (methodDef token).</param>
Expand All @@ -50,11 +52,12 @@ internal sealed record class TokenData(string Name, string Namespace, uint Outer
/// <param name="ModuleId">The identifier of the module that contains the function.</param>
/// <param name="TypeArgs">The class identifiers of the generic type arguments of the function.</param>
/// <param name="ParameterTypes">The class identifiers of the parameter types of the function.</param>
/// <param name="StackTraceHidden">If the function has <see cref="StackTraceHiddenAttribute"/>.</param>
/// <remarks>
/// If <paramref name="ParentClass"/> is 0, then use <paramref name="ParentClassToken"/>.
/// </remarks>
[DebuggerDisplay("{Name}")]
internal sealed record class FunctionData(string Name, uint MethodToken, ulong ParentClass, uint ParentClassToken, ulong ModuleId, ulong[] TypeArgs, ulong[] ParameterTypes);
internal sealed record class FunctionData(string Name, uint MethodToken, ulong ParentClass, uint ParentClassToken, ulong ModuleId, ulong[] TypeArgs, ulong[] ParameterTypes, bool StackTraceHidden);

/// <param name="Name">The name of the module.</param>
/// <param name="ModuleVersionId">The version identifier of the module.</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ public static class FunctionDescPayloads
public const int ClassId = 2;
public const int ClassToken = 3;
public const int ModuleId = 4;
public const int Name = 5;
public const int TypeArgs = 6;
public const int ParameterTypes = 7;
public const int StackTraceHidden = 5;
public const int Name = 6;
public const int TypeArgs = 7;
public const int ParameterTypes = 8;
}

public static class ClassDescPayloads
Expand All @@ -27,7 +28,8 @@ public static class ClassDescPayloads
public const int ModuleId = 1;
public const int Token = 2;
public const int Flags = 3;
public const int TypeArgs = 4;
public const int StackTraceHidden = 4;
public const int TypeArgs = 5;
}

public static class ModuleDescPayloads
Expand All @@ -42,8 +44,9 @@ public static class TokenDescPayloads
public const int ModuleId = 0;
public const int Token = 1;
public const int OuterToken = 2;
public const int Name = 3;
public const int Namespace = 4;
public const int StackTraceHidden = 3;
public const int Name = 4;
public const int Namespace = 5;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.Diagnostics.Tracing;
using System;

namespace Microsoft.Diagnostics.Monitoring.WebApi
{
internal static class TraceEventExtensions
{
public static bool GetBoolPayload(this TraceEvent traceEvent, int index)
{
return Convert.ToBoolean(GetPayload<uint>(traceEvent, index));
}

public static T GetPayload<T>(this TraceEvent traceEvent, int index)
{
return (T)traceEvent.PayloadValue(index);
Copy link
Member Author

@schmittjoseph schmittjoseph Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: I plan on updating this with a DEBUG check to prevent us accidentally calling it with <bool>. This will happen in a separate PR since we have an instance of using GetPayload<bool> elsewhere in dotnet-monitor that needs to get fixed first.

Expand Down
17 changes: 12 additions & 5 deletions src/Profilers/CommonMonitorProfiler/CommonUtilities/ClrData.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,45 +36,50 @@ enum class ClassFlags : UINT32
class ClassData
{
public:
ClassData(ModuleID moduleId, mdTypeDef token, ClassFlags flags) :
_moduleId(moduleId), _token(token), _flags(flags)
ClassData(ModuleID moduleId, mdTypeDef token, ClassFlags flags, bool stackTraceHidden) :
_moduleId(moduleId), _token(token), _flags(flags), _stackTraceHidden(stackTraceHidden)
{
}

const ModuleID GetModuleId() const { return _moduleId; }
const mdTypeDef GetToken() const { return _token; }
const ClassFlags GetFlags() const { return _flags; }
const bool GetStackTraceHidden() const { return _stackTraceHidden; }
const std::vector<UINT64>& GetTypeArgs() const { return _typeArgs; }
void AddTypeArg(ClassID id) { _typeArgs.push_back(static_cast<UINT64>(id)); }

private:
ModuleID _moduleId;
mdTypeDef _token;
ClassFlags _flags;
bool _stackTraceHidden;
std::vector<UINT64> _typeArgs;
};

class TokenData
{
public:
TokenData(tstring&& name, tstring&& Namespace, mdTypeDef outerClass) : _name(name), _namespace(Namespace), _outerClass(outerClass)
TokenData(tstring&& name, tstring&& Namespace, mdTypeDef outerClass, bool stackTraceHidden) :
_name(name), _namespace(Namespace), _outerClass(outerClass), _stackTraceHidden(stackTraceHidden)
{
}

const tstring& GetName() const { return _name; }
const tstring& GetNamespace() const { return _namespace; }
const mdTypeDef& GetOuterToken() const { return _outerClass; }
const bool GetStackTraceHidden() const { return _stackTraceHidden; }
private:
tstring _name;
tstring _namespace;
mdTypeDef _outerClass;
bool _stackTraceHidden;
};

class FunctionData
{
public:
FunctionData(ModuleID moduleId, ClassID containingClass, tstring&& name, mdToken methodToken, mdTypeDef classToken) :
_moduleId(moduleId), _class(containingClass), _functionName(name), _methodToken(methodToken), _classToken(classToken)
FunctionData(ModuleID moduleId, ClassID containingClass, tstring&& name, mdToken methodToken, mdTypeDef classToken, bool stackTraceHidden) :
_moduleId(moduleId), _class(containingClass), _functionName(name), _methodToken(methodToken), _classToken(classToken), _stackTraceHidden(stackTraceHidden)
{
}

Expand All @@ -83,6 +88,7 @@ class FunctionData
const ClassID GetClass() const { return _class; }
const mdToken GetMethodToken() const { return _methodToken; }
const mdTypeDef GetClassToken() const { return _classToken; }
const bool GetStackTraceHidden() const { return _stackTraceHidden; }
const std::vector<UINT64>& GetTypeArgs() const { return _typeArgs; }
const std::vector<UINT64>& GetParameterTypes() const { return _parameterTypes; }
void AddTypeArg(ClassID classID) { _typeArgs.push_back(static_cast<UINT64>(classID)); }
Expand All @@ -93,6 +99,7 @@ class FunctionData
tstring _functionName;
mdToken _methodToken;
mdTypeDef _classToken;
bool _stackTraceHidden;
std::vector<UINT64> _typeArgs;
std::vector<UINT64> _parameterTypes;
};
Original file line number Diff line number Diff line change
Expand Up @@ -193,29 +193,29 @@ const std::unordered_map<std::pair<ModuleID, mdTypeDef>, std::shared_ptr<TokenDa
return _names;
}

void NameCache::AddFunctionData(ModuleID moduleId, FunctionID id, tstring&& name, ClassID parent, mdToken methodToken, mdTypeDef parentToken, ClassID* typeArgs, int typeArgsCount)
void NameCache::AddFunctionData(ModuleID moduleId, FunctionID id, tstring&& name, ClassID parent, mdToken methodToken, mdTypeDef parentToken, ClassID* typeArgs, int typeArgsCount, bool stackTraceHidden)
{
std::shared_ptr<FunctionData> functionData = std::make_shared<FunctionData>(moduleId, parent, std::move(name), methodToken, parentToken);
std::shared_ptr<FunctionData> functionData = std::make_shared<FunctionData>(moduleId, parent, std::move(name), methodToken, parentToken, stackTraceHidden);
for (int i = 0; i < typeArgsCount; i++)
{
functionData->AddTypeArg(typeArgs[i]);
}
_functionNames.emplace(id, functionData);
}

void NameCache::AddClassData(ModuleID moduleId, ClassID id, mdTypeDef typeDef, ClassFlags flags, ClassID* typeArgs, int typeArgsCount)
void NameCache::AddClassData(ModuleID moduleId, ClassID id, mdTypeDef typeDef, ClassFlags flags, ClassID* typeArgs, int typeArgsCount, bool stackTraceHidden)
{
std::shared_ptr<ClassData> classData = std::make_shared<ClassData>(moduleId, typeDef, flags);
std::shared_ptr<ClassData> classData = std::make_shared<ClassData>(moduleId, typeDef, flags, stackTraceHidden);
for (int i = 0; i < typeArgsCount; i++)
{
classData->AddTypeArg(typeArgs[i]);
}
_classNames.emplace(id, classData);
}

void NameCache::AddTokenData(ModuleID moduleId, mdTypeDef typeDef, mdTypeDef outerToken, tstring&& name, tstring&& Namespace)
void NameCache::AddTokenData(ModuleID moduleId, mdTypeDef typeDef, mdTypeDef outerToken, tstring&& name, tstring&& Namespace, bool stackTraceHidden)
{
std::shared_ptr<TokenData> tokenData = std::make_shared<TokenData>(std::move(name), std::move(Namespace), outerToken);
std::shared_ptr<TokenData> tokenData = std::make_shared<TokenData>(std::move(name), std::move(Namespace), outerToken, stackTraceHidden);

_names.emplace(std::make_pair(moduleId, typeDef), tokenData);
}
Loading
Loading