newrelic-dotnet-agent
newrelic-dotnet-agent copied to clipboard
Instrumenting PowerShell 7 Scripts, Modules, and Functions
I have a script that runs as a Windows Service that has two functions. One function is called in a loop that runs every five minutes, and that function calls the second function (in mine it's multiple times with lots of logic, but for brevity, I've only put it in once). Shown below.
I assumed that since PowerShell is based on .NetCore/.Net 6 that it would just be picked up automatically. But sadly this is not the case. I would love to see metrics (or anything really) about my script and what it's doing in APM, and potentially alert off of it.
My script has no problem importing the NewRelic.Api.Agent.dll and doesn't throw any errors when I add the [NewRelic.Api.Agent.Transaction()] and the [NewRelic.Api.Agent.Trace()] attributes (it even throws errors when I change the names slightly, so I have the names right at least), but NR APM doesn't pick up any data.
$AgentDLL = ".\lib\netstandard2.0\NewRelic.Api.Agent.dll"
Add-Type -Path $AgentDLL
function Invoke-MyTracedFunction {
[NewRelic.Api.Agent.Trace()]
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$Parameter1
)
# do some stuff
}
function Invoke-MyMainFunction {
[NewRelic.Api.Agent.Transaction()]
[CmdletBinding()]
param ()
Invoke-MyTracedFunction -Parameter1 "some data"
}
while ($true) {
Invoke-MyMainFunction
Start-Sleep 300
}
I'm curious, why doesn't it get any data? Also, is there a way to add PowerShell to the .NetCore/.Net 6 Agent compatibility?
As a DevOps Engineer, it would be very useful to see metrics and such about my scripts and modules that I run, especially ones that are run automatically in one way or another.
Hey @Vacant0mens, thanks for the feature request! This idea intrigued me so I tried it out with our profiler attached. Unfortunately even though powershell appears to let you add our attributes, actual .NET functions with the names Invoke-MyMainFunction or Invoke-MyTracedFunction are never encountered by the profiler.
I tried invoking a web request via powershell and our existing instrumentation did rejit the appropriate .net function, so I have hope there may be some way to accomplish this.
My guess is that if you loaded a proper .NET assembly that contained functions with the Transaction attribute, and called them, the .NET agent would report that while attached to your powershell script. I realize this defeats your use case though.
I've assigned this to our product owner, and we will let you know what is decided.
Hi @JcolemanNR Just so I'm clear, in your tests, did you use the .Net libraries to make your web request? or did you use a cmdlet?
Also, thanks for submitting the feature request! It'd be pretty great to be able to monitor long-running or always-running/scheduled scripts. 👍
Hey @Vacant0mens,
I was using Invoke-WebRequest and this was calling a lower level C# api that we do instrument (but only in a transaction).
Here is my test script that did not work. I think it's basically your script with an additional line or two:
$AgentDLL = "C:\src\newrelic-dotnet-agent\src\Agent\newrelichome_x64_coreclr\NewRelic.Api.Agent.dll"
Add-Type -Path $AgentDLL
function Invoke-MyTracedFunction {
[CmdletBinding()]
[NewRelic.Api.Agent.TraceAttribute()]
param (
[Parameter(Mandatory = $true)]
[string]$Parameter1
)
# do some stuff
Invoke-WebRequest -URI https://www.bing.com/search?q=how+many+feet+in+a+mile
}
function Invoke-MyMainFunction {
[CmdletBinding()]
[NewRelic.Api.Agent.TransactionAttribute()]
param ()
Invoke-MyTracedFunction -Parameter1 "some data"
}
while ($true) {
Write-Output "Invoking function"
Invoke-MyMainFunction
Start-Sleep 5
}
The core issue with the above example is that the Cmdlet functions are never encountered by the Microsoft Profiler API for JIT/Rejit, so the .NET Agent is unable to inject the required code to observe the lifecycle of these functions. The [Trace] and [Transaction] attributes are observed during this Jit/Rejit process, but since this doesn't happen, no transaction is ever started.
Based on my experimentation, I don't think instrumenting cmdlets as a [Transaction] will work with the current .NET agent. The only thing I could see working would be calling out to a custom assembly that contains business logic, and wraps the entry point with a [Transaction] attribute. This would likely defeat the benefit of scripting in PowerShell though.
Could that (in theory) be a new/different NewRelic.Api.Agent.DLL made for PowerShell specifically? If not, what is the feature request is for? (Just making sure I understand)
Hey @Vacant0mens, good question! The feature request label was added to this ticket since the agent was not designed with this use case in mind, and it's not a trivial change to make it work as foundational things are not working (like JIT/ReJIT notifications for powershell cmdlets). There are a few ideas out there for alternative APIs that the agent API dll could support to enable the powershell use case, and they all fall in to the new development (feature request! 😄) bucket versus resolving a bug/issue.
The best approach, so far, to implement support for powershell would be to extend the Agent API to allow transactions/segments to be manually started/ended within your script by decorating your functions/segments of interest. There is also some potential crossover with the concept of transaction-less data (similar to open telemetry) that could be useful for the scripting use case.
Those are the answers from a technical perspective. I'd have to defer to product management for any questions about priority/timeframe for implementing such a feature though.
https://issues.newrelic.com/browse/NEWRELIC-3651
This issue won't be actioned.
@angelatan2 does that last comment by workato-integration bot mean that it's done or that it won't get worked on ever?
@Vacant0mens, please pardon the automated message. Typically, this means that Product Management has reviewed the feature request and also reviewed the demand for the feature. At this time, he has decided that it is not part of our annual roadmap. But, of course, he continues to monitor requests from the community and our customers and frequently revisits the feature requests as interests changes.