Skip to content

Commit 7e8c28b

Browse files
authored
feat: Parse Azure Function HttpTrigger parameters (#2776)
1 parent e545c43 commit 7e8c28b

File tree

16 files changed

+747
-415
lines changed

16 files changed

+747
-415
lines changed

src/Agent/NewRelic/Agent/Core/Transactions/NoOpTransaction.cs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public class NoOpTransaction : ITransaction, ITransactionExperimental
2323
public bool IsValid => false;
2424
public bool IsFinished => false;
2525
public ISegment CurrentSegment => Segment.NoOpSegment;
26+
public bool HasHttpResponseStatusCode => false;
2627

2728
public DateTime StartTime => DateTime.UtcNow;
2829

src/Agent/NewRelic/Agent/Core/Transactions/Transaction.cs

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ public ISegment CurrentSegment
7272
}
7373
}
7474

75+
public bool HasHttpResponseStatusCode => TransactionMetadata.HttpResponseStatusCode.HasValue;
76+
7577
public ITracingState TracingState { get; private set; }
7678

7779
public string TraceId

src/Agent/NewRelic/Agent/Extensions/NewRelic.Agent.Extensions/Api/ITransaction.cs

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public interface ITransaction
3333
/// </summary>
3434
ISegment CurrentSegment { get; }
3535

36+
bool HasHttpResponseStatusCode { get; }
37+
3638
/// <summary>
3739
/// End this transaction.
3840
/// </summary>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2020 New Relic, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using NewRelic.Agent.Api;
5+
using NewRelic.Agent.Extensions.Providers.Wrapper;
6+
7+
namespace NewRelic.Providers.Wrapper.AzureFunction;
8+
9+
public class FunctionsHttpProxyingMiddlewareWrapper : IWrapper
10+
{
11+
private const string WrapperName = "FunctionsHttpProxyingMiddlewareWrapper";
12+
13+
public bool IsTransactionRequired => false;
14+
15+
public CanWrapResponse CanWrap(InstrumentedMethodInfo methodInfo)
16+
{
17+
return new CanWrapResponse(WrapperName.Equals(methodInfo.RequestedWrapperName));
18+
}
19+
20+
/// <summary>
21+
/// Gets request method / path for Azure function HttpTrigger invocations
22+
/// in apps that use the Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore package
23+
/// </summary>
24+
public AfterWrappedMethodDelegate BeforeWrappedMethod(InstrumentedMethodCall instrumentedMethodCall, IAgent agent, ITransaction transaction)
25+
{
26+
if (agent.Configuration.AzureFunctionModeEnabled)
27+
{
28+
dynamic httpContext;
29+
switch (instrumentedMethodCall.MethodCall.Method.MethodName)
30+
{
31+
case "AddHttpContextToFunctionContext":
32+
httpContext = instrumentedMethodCall.MethodCall.MethodArguments[1];
33+
34+
agent.CurrentTransaction.SetRequestMethod(httpContext.Request.Method);
35+
agent.CurrentTransaction.SetUri(httpContext.Request.Path);
36+
break;
37+
case "TryHandleHttpResult":
38+
if (!agent.CurrentTransaction.HasHttpResponseStatusCode) // these handlers seem to get called more than once; only set the status code one time
39+
{
40+
httpContext = instrumentedMethodCall.MethodCall.MethodArguments[2];
41+
agent.CurrentTransaction.SetHttpResponseStatusCode(httpContext.Response.StatusCode);
42+
}
43+
break;
44+
case "TryHandleOutputBindingsHttpResult":
45+
if (!agent.CurrentTransaction.HasHttpResponseStatusCode) // these handlers seem to get called more than once; only set the status code one time
46+
{
47+
httpContext = instrumentedMethodCall.MethodCall.MethodArguments[1];
48+
agent.CurrentTransaction.SetHttpResponseStatusCode(httpContext.Response.StatusCode);
49+
}
50+
break;
51+
}
52+
}
53+
54+
return Delegates.NoOp;
55+
}
56+
}

src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AzureFunction/Instrumentation.xml

+13
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,18 @@ SPDX-License-Identifier: Apache-2.0
1919
<exactMethodMatcher methodName="Build" />
2020
</match>
2121
</tracerFactory>
22+
23+
<tracerFactory name="FunctionsHttpProxyingMiddlewareWrapper">
24+
<match assemblyName="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" className="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware">
25+
<exactMethodMatcher methodName="AddHttpContextToFunctionContext" />
26+
</match>
27+
<match assemblyName="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" className="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware">
28+
<exactMethodMatcher methodName="TryHandleHttpResult" />
29+
</match>
30+
<match assemblyName="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" className="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware">
31+
<exactMethodMatcher methodName="TryHandleOutputBindingsHttpResult" />
32+
</match>
33+
34+
</tracerFactory>
2235
</instrumentation>
2336
</extension>

0 commit comments

Comments
 (0)