open-telemetry / opentelemetry-php

The OpenTelemetry PHP Library

Home Page:https://opentelemetry.io/docs/instrumentation/php/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support Stack Trace attribute against a span

iamacarpet opened this issue · comments

Before opening a feature request against this repo, consider whether the feature should/could be implemented in the other OpenTelemetry client libraries. If so, please open an issue in opentelemetry-specification first.

Is your feature request related to a problem?
If so, provide a concise description of the problem.

On Google Cloud, their Cloud Trace product supports including a stack trace against a span:

image
(labelled as "Call Stack" on this screenshot).

I have implemented an OpenTelemetry compatible exporter for Cloud Trace on GCP, that doesn't require the OTEL Go daemon:
https://github.com/affordablemobiles/opentelemetry-operations-php

I'd like to be able to natively submit a stack trace from PHP to Cloud Trace.

Describe the solution you'd like
What do you want to happen instead? What is the expected behavior?

I'd like to have a method on spanBuilder, as something like setStackTrace(array), where we can access it from the exporter.

Describe alternatives you've considered
Which alternative solutions or features have you considered?

Currently, I'm using an attribute against the span: if the exporter detects an attribute named stackTrace, it'll remove that from the attributes list & instead submit it as a stack trace when creating the span in the Google Cloud PHP library:

The main problem with this is that the open telemetry library won't accept an array from debug_backtrace as an attribute, as it throws this warning:

[warning] attribute with non-primitive or non-homogeneous array of primitives dropped: stackTrace

To make this work, I had to resort to running:

$spanBuilder = $instrumentation
                    ->tracer()
                    ->spanBuilder('GuzzleHttp/request')
                    ...
                    ->setAttribute('stackTrace', serialize(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)))

And in the exporter, using:

        foreach ($span->getAttributes() as $k => $v) {
            if ('stackTrace' === $k) {
                try {
                    $spanOptions['stackTrace'] = unserialize($v, ['allowed_classes' => false]);
                } catch (\Throwable $ex) {
                }
            } else {
                $spanOptions['attributes'][$k] = self::sanitiseAttributeValueString($v);
            }
        }

Using serialize and unserialize obviously adds extra overhead in terms of CPU time to the request, so it would be helpful to be able to pass the array without the need for this.

Additional context
Add any other context about the feature request here.

Hi @iamacarpet
Is the stack trace representing an exception (in which case we have $span->recordException(), or you just want the current call stack? If the latter, did you look at how we add an exception backtrace as a span attribute ?

attribute with non-primitive or non-homogeneous array of primitives dropped

spec says that's how it has to work: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.32.0/specification/common/README.md?plain=1#L39

Thanks @brettmc ,

Yes this isn’t for exceptions, just for including the current call stack within a span: I have looked at what you are currently doing for stack traces logged with an exception and it is formatting as a string - Google Cloud’s library wants an array in the same format as ‘debug_backtrace’:

https://github.com/googleapis/google-cloud-php/blob/a58e5f44d0d942626360dc3ebe65bc40c11a90af/Trace/src/Span.php#L177

https://github.com/googleapis/google-cloud-php/blob/main/Trace/src/StackTrace.php

I understand the spec says “attributes” are required to be homogeneous and that’s the limitation of using them for storing this - so I guess the question is, can it be added as another data storage type against a span?

Has this been implemented in any other languages, and if so how did they make it work? Is it a peculiarity of the google-cloud-php implementation that it wants a PHP-specific format that's not compatible with otel attributes?

I don't see anything in the Span API that could hold the data you're wanting to store (and I believe that is deliberate, to discourage developers from abusing spans for arbitrary storage).

Another avenue would be if google's StackTrace could accept a pre-formatted trace? eg, adding a StackTrace::fromFormatted(). Or perhaps if you did an array_map function call to cast line number from int to string before storing it as an attribute?