Trace Method PHP Agent

Hello,

I have a similar issue with the PHP agent.
I understand that some portion of my code are not traced and appear as “Application code” and that I can make the agent trace it with newrelic_add_custom_tracer () function but I don’t understand how the agent decides to trace or not some part of the code.

I can use newrelic_add_custom_tracer () every time I find “Application code” but:

  • I will have to wait for another trace to get the info
  • I may have to add this a lot and it is quite “polluting”

@Linds @bskarich Any insight on this question ?

Hey @sylvain.fabre I moved this over to the PHP category in order to give you as streamlined an answer as possible. I’ll see if I can get a PHP Agent expert to respond ASAP! Thanks! :blush:

@sylvain.fabre

Actually custom_tracer largely isn’t needed with the PHP Agent anymore. The PHP Agent should detect and report any CUSTOM PHP FUNCTION. This means the agent will not report inline PHP functions nor will we time it.

So what does Application Code mean?

It’s a period of time in your transaction where the inline code wasn’t calling any custom functions that are part of your script or framework, so it’s likely time spent executing core PHP functions, perhaps looping around an array or task like writing to file etc.

In cases like this, we advise a divide and conquer approach to troubleshoot issues.
You can use our API to trace the function which at this point will tell our agent that reporting this function is important and add additional weight to it - Particularly useful if you have over 2000 elements in a trace and your trace is truncated.

Then divide your application into two sub-functions in your function-of-interest, called first_half() and second_half(), for example, splitting your code in the function between them, and put tracers on these new functions first_half and second_half.

You can then find out whether the top or bottom half of your code is causing the issue. Once you know which half has the issue you can then divide that half into two sections. Repeat this until you can identify the bottleneck in your code.

It’s generally viewed as a temporary approach that helps you solve the bottleneck, rather than a long term implementation. So the aim isn’t to pollute but to find out what inline PHP task is taking so long. It’s because it’s basic core PHP functions that don’t have a function name that New Relic has no name to give it, so it’s named Application Code to show you a long period of time was spent by PHP at this point.

1 Like

@Linds @acuffe Thank you for your detailed answer!

If it isn’t needed anymore, you may consider to update the PHP documentation:

How come these basic core PHP functions don’t have a function name? I don’t get this point: as I can invoke them, they must have a name somehow, right?

Best,

@sylvain.fabre

So it’s not “not needed”, it’s just less useful than when initially brought in. However in cases where you have very long traces with over 2000 elements tracked, you might miss out on a function you really want to see, without the tracer API function, you wouldn’t be able to tell our agent that function important_function() needs to be given a higher weighting to always appear in traces.

The core PHP functions have names, for example zend_version, func_num_args, func_get_arg, func_get_args, strlen, strcmp as examples of core PHP functions. These are all part of the PHP core, but we don’t time core functions, because if we did, we would be timing every single line of a PHP script, this would be massively impacting to be timing thousands upon thousands of individual PHP functions that happen.

So instead, New Relic times custom functions. Function that are made in your CMS’s, libraries, the code you write to execute a specific task, all of these are timed. Each of these functions will consist sometimes of core PHP function calls, sometimes custom function calls.

So in Transaction Traces, you may see Application Code both at the top level if there’s inline PHP that’s not part of any function, or you may see Application Code inside a function where a custom sub-function has been called

So to put a picture to that

Transaction 1
—> Function 1
—> Database_call 1
—> Function 2
—> Function 3
—> Application Code (just general PHP for the remainder of the script that isn’t called in functions)

Transaction 2
—> Function 1
—> Database_call 1
—> Function 2
—> Function 3
| —> Sub- Function 1
| —> Sub- Function 2
—> Function 4
| —> Sub- Function 1
| —> Sub- Function 2
| —> Application Code (Time spent in general PHP code as part of Function 4, after the sub-functions ran)

So this lets you know how long a function took, even if it had application code or inline-PHP inside, so you can tell well in Function 4 of Transaction 2, after sub-function 1 and 2 we have inline PHP code that we couldn’t give a specific naming to as no other custom function encapsulated it, so we show that the remainder of the time in Function 4 was spent in inline-PHP code being executed.

Similarly in Transaction 1, while the Application Code isn’t inside an existing function, it means at the highest level, the script which was executed had some inline PHP while also running Function 1,2 and 3 and a database call. Without Application Code grouping the remainder time, it would look like an incomplete trace, so we group together the inline PHP we don’t time (as it would have a massive negative effect on your application timing every single PHP function call) as Application Code and show you that this is where time is being spent.

Does that help explain it a little better in terms of the requirement of custom_tracers and why Application Code groups the inline-PHP together? Let me know if I’ve badly explained anything above I’m happy to clarify anything that’s needed.