Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit

Permalink
Always on better format for generic methods (#439)
Browse files Browse the repository at this point in the history
* update tests

* better formating

* fix taking parameter name

* write all generic parameters for methods

* Test case for method with 21 parameters

* Test case for class with more than 20 parameters

* remove double at from tests

* code review ffixes
  • Loading branch information
Kielek authored Mar 23, 2022
1 parent da551c9 commit f861066
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 16 deletions.
49 changes: 41 additions & 8 deletions tracer/src/Datadog.Trace.ClrProfiler.Native/always_on_profiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ constexpr auto max_function_name_cache_size = 7000;
constexpr auto param_name_max_len = 260;
constexpr auto generic_params_max_len = 20;
constexpr auto unknown = WStr("Unknown");
constexpr auto params_separator = WStr(", ");
constexpr auto generic_params_opening_brace = WStr("[");
constexpr auto generic_params_closing_brace = WStr("]");
constexpr auto function_params_opening_brace = WStr("(");
constexpr auto function_params_closing_brace = WStr(")");

// If you squint you can make out that the original bones of this came from sample code provided by the dotnet project:
// https://github.com/dotnet/samples/blob/2cf486af936261b04a438ea44779cdc26c613f98/core/profiling/stacksampling/src/sampler.cpp
Expand Down Expand Up @@ -363,18 +368,46 @@ class SamplingHelper
result.append(unknown_list_of_arguments);
return;
}

hr = pIMDImport->EnumGenericParams(&functionGenParamsIter, functionToken, functionGenericParams,
generic_params_max_len,
&functionGenParamsCount);
pIMDImport->CloseEnum(functionGenParamsIter);

if (FAILED(hr))
{
Logger::Debug("Method generic parameters enumeration failed. HRESULT=0x", std::setfill('0'), std::setw(8),
std::hex, hr);
result.append(unknown_list_of_arguments);
return;
}

if (functionGenParamsCount > 0)
{
result.append(generic_params_opening_brace);
for (ULONG i = 0; i < functionGenParamsCount; ++i)
{
if (i != 0)
{
result.append(params_separator);
}

WCHAR param_type_name[param_name_max_len]{};
ULONG pch_name = 0;
const auto hr =
pIMDImport->GetGenericParamProps(functionGenericParams[i], nullptr, nullptr, nullptr, nullptr,
param_type_name, param_name_max_len, &pch_name);
if (FAILED(hr))
{
Logger::Debug("GetGenericParamProps failed. HRESULT=0x", std::setfill('0'), std::setw(8), std::hex, hr);
result.append(unknown);
}
else
{
result.append(param_type_name);
}
}
result.append(generic_params_closing_brace);
}

// try to list arguments type
FunctionMethodSignature functionMethodSignature = function_info.method_signature;
Expand All @@ -387,19 +420,19 @@ class SamplingHelper
else
{
const auto& arguments = functionMethodSignature.GetMethodArguments();
result.append(WStr("("));
result.append(function_params_opening_brace);
for (ULONG i = 0; i < arguments.size(); i++)
{
if (i != 0)
{
result.append(WStr(", "));
result.append(params_separator);
}

auto& currentArg = arguments[i];
PCCOR_SIGNATURE pbCur = &currentArg.pbBase[currentArg.offset];
result.append(GetSigTypeTokName(pbCur, pIMDImport, classGenericParams, functionGenericParams));
}
result.append(WStr(")"));
result.append(function_params_closing_brace);
}
}

Expand All @@ -415,7 +448,7 @@ class SamplingHelper
WCHAR param_type_name[param_name_max_len]{};
ULONG pch_name = 0;
const auto hr = pImport->GetGenericParamProps(genericParameters[num], nullptr, nullptr, nullptr, nullptr,
param_type_name, param_name_max_len - 1, &pch_name);
param_type_name, param_name_max_len, &pch_name);
if (FAILED(hr))
{
Logger::Debug("GetGenericParamProps failed. HRESULT=0x", std::setfill('0'), std::setw(8),
Expand Down Expand Up @@ -521,18 +554,18 @@ class SamplingHelper
{
pbCur++;
tokenName = GetSigTypeTokName(pbCur, pImport, classParams, methodParams);
tokenName += WStr("[");
tokenName += generic_params_opening_brace;
ULONG num = 0;
pbCur += CorSigUncompressData(pbCur, &num);
for (ULONG i = 0; i < num; i++)
{
tokenName += GetSigTypeTokName(pbCur, pImport, classParams, methodParams);
if (i != num - 1)
{
tokenName += WStr(",");
tokenName += params_separator;
}
}
tokenName += WStr("]");
tokenName += generic_params_closing_brace;
break;
}
case ELEMENT_TYPE_MVAR:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,13 @@ private static bool ContainStackTraceForClassHierarchy(LogRecord logRecord)
{
return logRecord.Body.StringValue.Contains(
"\tat System.Threading.Thread.Sleep(System.TimeSpan)\n" +
"\tat My.Custom.Test.Namespace.ClassD`1.GenericMethodDFromGenericClass(TClass, TMethod, TMethod2)\n" +
"\tat My.Custom.Test.Namespace.ClassE`1.GenericMethodDFromGenericClass[TMethod, TMethod2](TClass, TMethod, TMethod2)\n" +
"\tat My.Custom.Test.Namespace.ClassD`21.MethodD(T01, T02, T03, T04, T05, T06, T07, T08, T09, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Unknown)\n" +
"\tat My.Custom.Test.Namespace.GenericClassC`1.GenericMethodCFromGenericClass[T01, T02, T03, T04, T05, T06, T07, T08, T09, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20](T01, T02, T03, T04, T05, T06, T07, T08, T09, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Unknown)\n" +
"\tat My.Custom.Test.Namespace.GenericClassC`1.GenericMethodCFromGenericClass(T)\n" +
"\tat My.Custom.Test.Namespace.ClassA.InternalClassB`2.DoubleInternalClassB.TripleInternalClassB`1.MethodB(System.String, TC[], TB, TD, System.Collections.Generic.IList`1[TA])\n" +
"\tat My.Custom.Test.Namespace.ClassA.<MethodAOthers>g__Action|4_0(System.String)\n" +
"\tat My.Custom.Test.Namespace.ClassA.MethodAOthers(System.String, System.Object, My.Custom.Test.Namespace.CustomClass, My.Custom.Test.Namespace.CustomStruct, My.Custom.Test.Namespace.CustomClass[], My.Custom.Test.Namespace.CustomStruct[], System.Collections.Generic.List`1[T])\n" +
"\tat My.Custom.Test.Namespace.ClassA.InternalClassB`2.DoubleInternalClassB.TripleInternalClassB`1.MethodB[TB](System.String, TC[], TB, TD, System.Collections.Generic.IList`1[TA], System.Collections.Generic.IList`1[System.String])\n" +
"\tat My.Custom.Test.Namespace.ClassA.<MethodAOthers>g__Action|4_0[T](System.String)\n" +
"\tat My.Custom.Test.Namespace.ClassA.MethodAOthers[T](System.String, System.Object, My.Custom.Test.Namespace.CustomClass, My.Custom.Test.Namespace.CustomStruct, My.Custom.Test.Namespace.CustomClass[], My.Custom.Test.Namespace.CustomStruct[], System.Collections.Generic.List`1[T])\n" +
"\tat My.Custom.Test.Namespace.ClassA.MethodAFloats(System.Single, System.Double)\n" +
"\tat My.Custom.Test.Namespace.ClassA.MethodAInts(System.UInt16, System.Int16, System.UInt32, System.Int32, System.UInt64, System.Int64, System.IntPtr, System.UIntPtr)\n" +
"\tat My.Custom.Test.Namespace.ClassA.MethodABytes(System.Boolean, System.Char, System.SByte, System.Byte)\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public static void MethodAOthers<T>(
CustomStruct[] structArray,
List<T> genericList)
{
void Action(string s) => InternalClassB<string, int>.DoubleInternalClassB.TripleInternalClassB<int>.MethodB(s, new int[] { 3 }, TimeSpan.Zero, 0, new List<string>{"a"});
void Action(string s) => InternalClassB<string, int>.DoubleInternalClassB.TripleInternalClassB<int>.MethodB(s, new int[] { 3 }, TimeSpan.Zero, 0, new List<string>{"a"}, new List<string>(0));
Action("test arg");
}

Expand All @@ -88,7 +88,7 @@ internal static class DoubleInternalClassB
{
internal static class TripleInternalClassB<TC>
{
public static void MethodB<TB>(string testArg, TC[] a, TB b, TD t, IList<TA> c)
public static void MethodB<TB>(string testArg, TC[] a, TB b, TD t, IList<TA> c, IList<string> d)
{
GenericClassC<string>.GenericMethodCFromGenericClass(testArg);
}
Expand All @@ -101,11 +101,28 @@ internal static class GenericClassC<T>
{
public static void GenericMethodCFromGenericClass(T arg)
{
ClassD<TimeSpan>.GenericMethodDFromGenericClass(TimeSpan.MaxValue, arg, 1);
GenericMethodCFromGenericClass(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21);
}

public static void GenericMethodCFromGenericClass<T01, T02, T03, T04, T05, T06, T07, T08, T09, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(T01 p01, T02 p02, T03 p03, T04 p04, T05 p05, T06 p06, T07 p07, T08 p08, T09 p09, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16, T17 p17, T18 p18, T19 p19, T20 p20, T21 p21)
{
// Always on profiler supports fetching at most 20 generic arguments. This method covers scenario where there are more than 20 parameters.
ClassD<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>.MethodD(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21);
}

}

internal static class ClassD<T01, T02, T03, T04, T05, T06, T07, T08, T09, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>
{
// Always on profiler supports fetching at most 20 generic arguments. This class covers scenario where there are more than 20 parameters.
public static void MethodD(T01 p01, T02 p02, T03 p03, T04 p04, T05 p05, T06 p06, T07 p07, T08 p08, T09 p09, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16, T17 p17, T18 p18, T19 p19, T20 p20, T21 p21)
{
ClassE<TimeSpan>.GenericMethodDFromGenericClass(TimeSpan.MaxValue, p01, 1);

}
}

internal static class ClassD<TClass>
internal static class ClassE<TClass>
{
public static void GenericMethodDFromGenericClass<TMethod, TMethod2>(TClass classArg, TMethod methodArg, TMethod2 additionalArg)
{
Expand Down

0 comments on commit f861066

Please sign in to comment.