Code Monkey home page Code Monkey logo

tracing-laravel's Introduction

Laravel Tracing

Introduction

Distributed tracing is the process of tracking the activity resulting from a request to an application. With this feature, you can:

  • Trace the path of a request as it travels across a complex system
  • Discover the latency of the components (services) along that path
  • Know which component in the path is creating a bottleneck
  • Inspect payloads that are being sent between components
  • Build execution graph for each separate component and more

Simply put, distributed tracing is a knowledge tool. One of the most important perks of having it in your project is that deveopers can learn the system by simply following the traces it makes.

See how Uber is using distributed tracing to make sense of large number of microservices and interactions within their product:

A distributed trace is composed of multiple spans, which represent time spent in services or resources of those services.

Each Span has the following:

  • Operation name
  • Start timestamp
  • Finish timestamp
  • Set of zero or more key:value tags to enable lookup and record additional information
  • Set of zero or more logs paired with a timestamp
  • References to related Spans (e.g. a parent)

Spans are typically displayed for your view as a time axis where each span can be unfolded to inpect additional details:

image

The Tracer interface (available via Trace facade) creates Spans and understands how to Inject (serialize) and Extract (deserialize) them across process boundaries.

See OpenTracing spec for more details on semantics behind distributed tracing.

Requirements

This package requires PHP >= 7.1 and Laravel 5.5 or later. We also offer limited Lumen support (basic tracing and http middleware).

Installation

First, install the package via Composer:

composer require vinelab/tracing-laravel

After installation, you can publish the package configuration using the vendor:publish command. This command will publish the tracing.php configuration file to your config directory:

php artisan vendor:publish --provider="Vinelab\Tracing\TracingServiceProvider"

You may configure the driver and service name in your .env file:

TRACING_DRIVER=zipkin
TRACING_SERVICE_NAME=orders

You should also add credentials for your respective driver as described in the section below.

For Lumen, see dedicated section with installation instructions.

Driver Prerequisites

Zipkin

Use the following environment variables to configure Zipkin:

ZIPKIN_HOST=localhost
ZIPKIN_PORT=9411

If the collector is unreachable via a given hostname, you might see debug messages about that printed with each request. If you want to ignore these in production, simply edit your logging configuration to omit debug level messages.

Jaeger

Jaeger is not "officially" supported because of the lack of stable instrumentation for PHP.

However, you can still post spans to Jaeger collector with Zipkin driver using Zipkin compatible HTTP endpoint. In fact, that's the recommended way to use this library since Jaeger's UI is just that much more convenient than Zipkin's.

There are some downsides, however:

  • you won't be able to avail of some Jaeger specific features like contextualized logging since Zipkin only supports tags and time annotations
  • HTTP is your only choice of transport (no UDP option)

We'll consider improving Jaeger support once its instrumetation matures.

Null

The package also includes null driver that discards created spans.

Usage

You will work with tracing via a Trace facade provided by this package.

Creating Spans

Starting new trace is as simple as calling startSpan method with name for a logical operation the span represents:

$span = Trace::startSpan('Create Order');

Often, you need to continue an existing trace which is why startSpan also accepts additional parameter for span context. SpanContext may be propagated via various channels including HTTP requests, AMQP messages, arrays or even another span:

$spanContext = Trace::extract($request, Formats::ILLUMINATE_HTTP);

$rootSpan = Trace::startSpan('Create Order', $spanContext);

$childSpan = Trace::startSpan('Validate Order', $rootSpan->getContext())

The possibilities are limitless. Refer to Context Propagation section for more details.

Customizing Spans

Override span name:

$span->setName('Create Order');

Add tags, which may be used as lookup keys (to search span on UI) or additional details:

$span->tag('shipping_method', $shipping_method);

Retrieving Spans

You can retrieve the current span, which is also your most recently created span:

$span = Trace::getCurrentSpan()

The first span you create when processing a request in the service is called a root span (not to mix with the global root span of the trace):

After you call flush, the root span is reset.

$span = Trace::getRootSpan()

Controlling Spans

You may finish the span by calling finish on it. Span duration is derived by subtracting the start timestamp from this:

$span->finish()

You can log additional data between span start and finish. For example, annotate creates a time-stamped event to explain latencies:

$span->annotate('Order Validated')

Flushing Spans

Flush refers to the process of sending all pending spans to the transport. It will also reset the state of the tracer including the active spans and UUID:

Trace::flush()

Most of the time though you don't need to explicitly call flush. Since PHP is designed to die after each request, we already handle finishing the root span and calling flush upon application shutdown for you.

It's only when processing requests continuously in a loop (e.g. AMQP channels) that you must resort to calling flush manually.

Logging

Each root span is associated with a unique identifier that can be used to lookup its trace. It is recommended you include it as part of context when reporting errors to bridge the gap between different parts of your monitoring stack:

// Illuminate\Foundation\Exceptions\Handler

/**
  * Get the default context variables for logging.
  *
  * @return array
  */
protected function context()
{
    return array_filter([
        'userId' => Auth::id(),
        'uuid' => Trace::getUUID(),
    ]);
}

Custom drivers may also support logging structured data (not available in Zipkin) which can be used for integrating tracing with a Log facade:

use Illuminate\Support\Facades\Event;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Event::listen(MessageLogged::class, function (MessageLogged $e) {
        Tracer::getCurrentSpan()->log((array) $e);
    });
}

Middleware

This package includes a \Vinelab\Tracing\Middleware\TraceRequests middleware to take care of continuing the trace from incoming HTTP request.

You should register middleware class in the $middleware property of your app/Http/Kernel.php class.

The middleware adds the following tags on a root span:

  • type (http)
  • request_method
  • request_path
  • request_uri
  • request_headers
  • request_ip
  • request_input
  • response_status
  • response_headers
  • response_content

Request and response body are only included for whitelisted content-types. See logging.content_types option in your config/tracing.php.

You can override the default name of the span (which is VERB /path/for/route) in the controller:

Trace::getRootSpan()->setName('Create Order')

Console Commands

Lumen does not support this feature, but you can still create traces for commands manually using tracer instance.

Let your console commsands be traced by adding Vinelab\Tracing\Contracts\ShouldBeTraced interface to your class.

The container span will include the following tags:

  • type (cli)
  • argv

The span will be named after the console command. You can override the default name of the span in the command itself:

Trace::getRootSpan()->setName('Mark Orders Expired')

Queue Jobs

Lumen does not support this feature, but you can still create traces for jobs manually using tracer instance.

Let your queue jobs be traced by adding Vinelab\Tracing\Contracts\ShouldBeTraced interface to your job class.

The container span will include the following tags:

  • type (queue)
  • connection_name (i.e. sync, redis etc.)
  • queue_name
  • job_input

As the name implies, job_input allows you to view your job's contructor parameters as JSON. Serialization of objects to this JSON string can be controlled by implementing one of the following interfaces: Arrayable, Jsonable, JsonSerializable, or a __toString method. A fallback behavior is to print all your object's public properties.

Constructor arguments must be saved as a class property with the same name (see ProcessPodcast example below).

The span will be named after the queue job class. You can override the default name of the span in the job itself:

app('tracing.queue.span')->setName('Process Podcast')

Note here that the queue span may not necessarily be the root span of the trace. You would usually want the queue to continue the trace from where it left of when the job was dispatched. You can achieve this by simply giving SpanContext to the job's constructor:

class ProcessPodcast implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $podcast;

    protected $spanContext;

    public function __construct(Podcast $podcast, SpanContext $spanContext)
    {
        $this->podcast = $podcast;
        $this->spanContext = $spanContext;
    }

    public function handle(AudioProcessor $processor)
    {
        // Process uploaded podcast...
    }
}

The job above can be dispatched like so:

ProcessPodcast::dispatch($podcast, Trace::getRootSpan()->getContext());

The rest will be handled automatically. Note that SpanContext will be excluded from logged job_input.

This package doesn't automatically handle tracing of queued closures and queued event listeners. You can still trace them manually by opening and closing spans. Improving support for these features might be considered for future versions of the package.

Context Propagation

As we talked about previously, the tracer understands how to inject and extract trace context across different applications (services).

We have already seen the example of extracting trace from HTTP request:

$spanContext = Trace::extract($request, Formats::ILLUMINATE_HTTP);

Of course, you don't need to do this manually because this package already includes a middleware to handle this for you, but the trace may not necessarily come from HTTP request.

The second parameter is a format descriptor that tells us how to deserialize tracing headers from given carrier. By default, the following formats are supported:

use Vinelab\Tracing\Propagation\Formats;

$spanContext = Trace::extract($carrier, Formats::TEXT_MAP);
$spanContext = Trace::extract($carrier, Formats::PSR_REQUEST);
$spanContext = Trace::extract($carrier, Formats::ILLUMINATE_HTTP);
$spanContext = Trace::extract($carrier, Formats::AMQP);
$spanContext = Trace::extract($carrier, Formats::GOOGLE_PUBSUB);

You may also add your own format using registerExtractionFormat method.

Trace::registerExtractionFormat("pubsub", new PubSubExtractor());

The injection format must implement Vinelab\Tracing\Contracts\Extractor. Refer to default Zipkin implementation for example.

interface Extractor
{
    public function extract($carrier): ?SpanContext;
}

Naturally, you can also inject existing trace context from the current span into a given carrier so that another service can continue the trace:

$message = Trace::inject($message, Formats::AMQP);

$channel->basic_publish($message, $this->exchangeName, $routingKey);

By default, the following formats are supported:

use Vinelab\Tracing\Propagation\Formats;

$carrier = Trace::inject($carrier, Formats::TEXT_MAP);
$carrier = Trace::inject($carrier, Formats::PSR_REQUEST);
$carrier = Trace::inject($carrier, Formats::ILLUMINATE_HTTP);
$carrier = Trace::inject($carrier, Formats::AMQP);
$carrier = Trace::inject($carrier, Formats::GOOGLE_PUBSUB);
$carrier = Trace::inject($carrier, Formats::VINELAB_HTTP);

You may also add your own format using registerInjectionFormat method.

The injection format must implement Vinelab\Tracing\Contracts\Injector. Refer to default Zipkin implementation for example.

interface Injector
{
    public function inject(SpanContext $spanContext, &$carrier): void;
}

You can also use injectContext method if you need to pass span context explicitly:

$carrier = Trace::injectContext($carrier, Formats::TEXT_MAP, $span->getContext());

IMPORTANT: You don't need to create a custom propagation format if you need to get something done quickly. You can always avail of the default TEXT_MAP format to inject or extract tracing headers from an associative array.

Custom Drivers

Writing New Driver

New drivers must adhere to Vinelab\Tracing\Contracts\Tracer contract. Refer to the default ZipkinTracer imlementation for example.

use Vinelab\Tracing\Contracts\Extractor;
use Vinelab\Tracing\Contracts\Injector;
use Vinelab\Tracing\Contracts\Span;
use Vinelab\Tracing\Contracts\SpanContext;

public function startSpan(string $name, SpanContext $spanContext = null, ?int $timestamp = null): Span;
public function getRootSpan(): ?Span;
public function getCurrentSpan(): ?Span;
public function getUUID(): ?string;
public function extract($carrier, string $format): ?SpanContext;
public function inject($carrier, string $format);
public function injectContext($carrier, string $format, SpanContext $spanContext);
public function registerExtractionFormat(string $format, Extractor $extractor): array;
public function registerInjectionFormat(string $format, Injector $injector): array;
public function flush(): void;

Registering New Driver

Once you have written your custom driver, you may register it using the extend method of the TracingDriverManager. You should call the extend method from the boot method of your AppServiceProvider or any other service provider used by your application. For example, if you have written a JaegerTracer, you may register it like so:

use Vinelab\Tracing\TracingDriverManager;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    resolve(TracingDriverManager::class)->extend('jaeger', function () {
        return new JaegerTracer;
    });
}

Once your driver has been registered, you may specify it as your tracing driver in your environment variables:

TRACING_DRIVER=jaeger

Usage With Lumen

You need to register service provider manually in bootstrap/app.php file:

$app->register(Vinelab\Tracing\TracingServiceProvider::class);

You should also register middleware in the same file:

$app->middleware([
    Vinelab\Tracing\Middleware\TraceRequests::class,
]);

Add the following lines to the end of public/index.php file:

$tracer = app(Vinelab\Tracing\Contracts\Tracer::class);

optional($tracer->getRootSpan())->finish();
$tracer->flush();

Finally, you may also want to copy over config/tracing.php from this repo if you need to customize default settings.

If you don't use facades in your Lumen project, you can resolve tracer instance from container like this:

use Vinelab\Tracing\Contracts\Tracer;

app(Tracer::class)->startSpan('Create Order')

Note that Lumen currently doesn't support automatic tracing for console commands and jobs because it doesn't dispatch some events and terminating callbacks. However, you can still create traces manually where you need them.

Integrations

Lucid Architecture

This package includes optional Vinelab\Tracing\Integration\Concerns\TracesLucidArchitecture trait to enable tracing for Lucid projects:

class TracingServiceProvider extends ServiceProvider
{
    use TracesLucidArchitecture;

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->traceLucidArchitecture();
    }
}

tracing-laravel's People

Contributors

adiachenko avatar deonvdv avatar devinnorgarb avatar iyhunko avatar jeroenvanoort avatar kinaned avatar mulkave avatar rikj000 avatar steveoliver avatar summerkk avatar wlzch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tracing-laravel's Issues

Has anyone considered adding more events to Laravel?

I would be great if Laravel had more events that we could use to start and finish spans. Like QueryStarted in addition to QueryExecuted, CacheQueryStarted in addition to CacheHit and CacheMissed, etc. Maybe even some new events for the HTTP client.

Do you know if anyone has tried this already? I'm willing to work on it, but if someone has already tried and got their PR rejected, I may want to save myself the effort.

Why does `sampler` not support `PercentageSampler`

Can we consider making a configuration option to support PercentageSampler?
Sampling may be employed to reduce the data collected and reported out of process.
https://github.com/openzipkin/zipkin-php#sampling

    public function createZipkinDriver()
    {
        $tracer = new ZipkinTracer(
            $this->config->get('tracing.service_name'),
            $this->config->get('tracing.zipkin.host'),
            $this->config->get('tracing.zipkin.port'),
            $this->config->get('tracing.zipkin.options.128bit'),
            $this->config->get('tracing.zipkin.options.request_timeout', 5)
        );

        ZipkinTracer::setMaxTagLen(
            $this->config->get('tracing.zipkin.options.max_tag_len', ZipkinTracer::getMaxTagLen())
        );

        return $tracer->init();
    }
    public function init(): Tracer
    {
        $this->tracing = TracingBuilder::create()
            ->havingLocalEndpoint($this->createEndpoint())
            ->havingTraceId128bits($this->usesTraceId128bits)
            ->havingSampler($this->createSampler())
            ->havingReporter($this->createReporter())
            ->build();

        $this->registerDefaultExtractionFormats();
        $this->registerDefaultInjectionFormats();

        return $this;
    }
    protected function createSampler(): Sampler
    {
        return BinarySampler::createAsAlwaysSample();
    }

Too few arguments to function 'Illuminate\Support\Manager::createDriver()'

Running on:

  • Laravel 8.15
  • PHP v7.4
  • Phpunit v9.4.3

In previous Laravel installations 5.8.*, to silence tracing while running phpunit tests we adapt our phpunit.xml as such:

    <php>
       ...
        <env name="TRACING_DRIVER" value="null"/>
    </php>

Doing this same in this installation result with the following error:

ArgumentCountError: Too few arguments to function Illuminate\Support\Manager::createDriver(), 0 passed in /code/vendor/laravel/framework/src/Illuminate/Support/Manager.php on line 105 and exactly 1 expected
/code/vendor/laravel/framework/src/Illuminate/Support/Manager.php:94
/code/vendor/laravel/framework/src/Illuminate/Support/Manager.php:105
/code/vendor/laravel/framework/src/Illuminate/Support/Manager.php:80
/code/vendor/vinelab/tracing-laravel/src/TracingServiceProvider.php:75
/code/vendor/laravel/framework/src/Illuminate/Container/Container.php:805
/code/vendor/laravel/framework/src/Illuminate/Container/Container.php:691
/code/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:796
/code/vendor/laravel/framework/src/Illuminate/Container/Container.php:637
/code/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:781
/code/vendor/laravel/framework/src/Illuminate/Container/Container.php:1280
/code/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:198
/code/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:166
/code/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:255
/code/vendor/vinelab/tracing-laravel/src/Integration/Concerns/TracesLucidArchitecture.php:67
/code/vendor/vinelab/tracing-laravel/src/Integration/Concerns/TracesLucidArchitecture.php:55
/code/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:391
/code/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:236
/code/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:432

We were able to work around this by adding a single quote for the null driver:
<server name="TRACING_DRIVER" value="'null'"/>

Is this an exepcted behaviour?

Drop support for some older versions of PHP and Laravel in the next major release

At the moment our versions constraints are brittle and its getting harder to anticipate where things might break due to wide range of supported software.

I suggest to limit support to the following versions to ease maintenance burden:

  • PHP >= 7.4 (support for PHP 7.3 will end on December 6)
  • Laravel >= 6.0 (this is the last version that still receives security fixes)

This also allows us to clean up some other dependencies a bit:

  • "openzipkin/zipkin": "~2.0.2|~3.0" => "~3.0"
  • "phpunit/phpunit": "~7.0|~8.0" => "~9.0"

Users of older PHP/Laravel can still avail of older versions of the package.

Opinions? @Mulkave @KinaneD

🐞 Bug - v2.3.2 - Invalid sampler class. Expected `BinarySampler` or `PercentageSampler`, got 0.000000

Issue Description

Since updating to the new v2.3.2 release,
following error log gets spammed in the laravel.log file:

[2023-11-09 10:32:47] testing.ERROR: Invalid sampler class. Expected `BinarySampler` or `PercentageSampler`, got 0.000000 {

    "exception":"[object] (InvalidArgumentException(code: 0): Invalid sampler class. Expected `BinarySampler` or `PercentageSampler`, got 0.000000 at /vendor/vinelab/tracing-laravel/src/TracingDriverManager.php:83)

    [stacktrace]
    #0  /vendor/vinelab/tracing-laravel/src/TracingDriverManager.php(60): Vinelab\\Tracing\\TracingDriverManager->getZipkinSampler()
    #1  /vendor/laravel/framework/src/Illuminate/Support/Manager.php(106): Vinelab\\Tracing\\TracingDriverManager->createZipkinDriver()
    #2  /vendor/laravel/framework/src/Illuminate/Support/Manager.php(80): Illuminate\\Support\\Manager->createDriver()
    #3  /vendor/vinelab/tracing-laravel/src/TracingServiceProvider.php(77): Illuminate\\Support\\Manager->driver()
    #4  /vendor/laravel/framework/src/Illuminate/Container/Container.php(908): Vinelab\\Tracing\\TracingServiceProvider->Vinelab\\Tracing\\{closure}()
    #5  /vendor/laravel/framework/src/Illuminate/Container/Container.php(795): Illuminate\\Container\\Container->build()
    #6  /vendor/laravel/framework/src/Illuminate/Foundation/Application.php(955): Illuminate\\Container\\Container->resolve()
    #7  /vendor/laravel/framework/src/Illuminate/Container/Container.php(731): Illuminate\\Foundation\\Application->resolve()
    #8  /vendor/laravel/framework/src/Illuminate/Foundation/Application.php(940): Illuminate\\Container\\Container->make()
    #9  /vendor/laravel/framework/src/Illuminate/Container/Container.php(1454): Illuminate\\Foundation\\Application->make()
    #10 /vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(236): Illuminate\\Container\\Container->offsetGet()
    #11 /vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(207): Illuminate\\Support\\Facades\\Facade::resolveFacadeInstance()
    #12 /vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(347): Illuminate\\Support\\Facades\\Facade::getFacadeRoot()
    #13 /vendor/vinelab/tracing-laravel/src/TracingServiceProvider.php(57): Illuminate\\Support\\Facades\\Facade::__callStatic()
    #14 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Vinelab\\Tracing\\TracingServiceProvider->Vinelab\\Tracing\\{closure}()
    #15 /vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
    #16 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(81): Illuminate\\Container\\Util::unwrapIfClosure()
    #17 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\\Container\\BoundMethod::callBoundMethod()
    #18 /vendor/laravel/framework/src/Illuminate/Container/Container.php(662): Illuminate\\Container\\BoundMethod::call()
    #19 /vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1272): Illuminate\\Container\\Container->call()
    #20 /vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(220): Illuminate\\Foundation\\Application->terminate()
    #21 /artisan(49): Illuminate\\Foundation\\Console\\Kernel->terminate()
    #22 {main}"
}

Workaround

Manually add the new tracing.zipkin.sampler_class settings to config/tracing:

'sampler_class' => \Zipkin\Samplers\BinarySampler::class,
'percentage_sampler_rate' => env('ZIPKIN_PERCENTAGE_SAMPLER_RATE', 0.2),

PR #49 - Diff of config/tracing

Fix Suggestion

  • Populate the new tracing.zipkin.sampler_class settings in config/tracing with default values if not set.
  • Document config/tracing changes in the ChangeLog of new releases

PR #49 - Review

Linked Issues/PRs

Lumen Support

I'm trying to use this package on Lumen 8.0 but I'm getting a lot of missing function or method errors. Is it possible to add support for Lumen? Thank you.

Migrate to Zipkin 2.0

Zipkin PHP 2.0 is out and brought support for PHP 7.1+ avoiding type checks with almost no breaking changes. Consider upgrading.

Lumen with Vinelab/tracing-laravel plugin raised error

Trying to add logger tool
https://github.com/Vinelab/tracing-laravel#usage-with-lumen

to lumen app and I followed all steps under “Usage With Lumen” section.
Running request I got error :

 "message": "Call to undefined method Laravel\\Lumen\\Application::terminating()",
    "exception": "Error",
    "file": "/mnt/_work_sdb8/wwwroot/LumenProjects/PublishPagesAPI/vendor/vinelab/tracing-laravel/src/TracingServiceProvider.php",
    "line": 55,
    "trace": [
        {
            "file": "/mnt/_work_sdb8/wwwroot/LumenProjects/PublishPagesAPI/vendor/illuminate/container/BoundMethod.php",
            "line": 36,
            "function": "boot",
            "class": "Vinelab\\Tracing\\TracingServiceProvider",
            "type": "->"
        },
        {
            "file": "/mnt/_work_sdb8/wwwroot/LumenProjects/PublishPagesAPI/vendor/illuminate/container/Util.php",
            "line": 40,
            "function": "Illuminate\\Container\\{closure}",
            "class": "Illuminate\\Container\\BoundMethod",
            "type": "::"
        },
        {
            "file": "/mnt/_work_sdb8/wwwroot/LumenProjects/PublishPagesAPI/vendor/illuminate/container/BoundMethod.php",
            "line": 93,
            "function": "unwrapIfClosure",
            "class": "Illuminate\\Container\\Util",
            "type": "::"
        },
        {
            "file": "/mnt/_work_sdb8/wwwroot/LumenProjects/PublishPagesAPI/vendor/illuminate/container/BoundMethod.php",
            "line": 37,
            "function": "callBoundMethod",
            "class": "Illuminate\\Container\\BoundMethod",
            "type": "::"
        },
        {
            "file": "/mnt/_work_sdb8/wwwroot/LumenProjects/PublishPagesAPI/vendor/illuminate/container/Container.php",
            "line": 653,
            "function": "call",
            "class": "Illuminate\\Container\\BoundMethod",
            "type": "::"
        },
        {
            "file": "/mnt/_work_sdb8/wwwroot/LumenProjects/PublishPagesAPI/vendor/laravel/lumen-framework/src/Application.php",
            "line": 277,
            "function": "call",
            "class": "Illuminate\\Container\\Container",
            "type": "->"
        },
        {
            "file": "/mnt/_work_sdb8/wwwroot/LumenProjects/PublishPagesAPI/vendor/laravel/lumen-framework/src/Application.php",
            "line": 262,
            "function": "bootProvider",
            "class": "Laravel\\Lumen\\Application",
            "type": "->"
        },
        {
        
I upgrated all packages in my composer.json :
{
    "name": "laravel/lumen",
    "description": "The Laravel Lumen Framework.",
    "keywords": ["framework", "laravel", "lumen"],
    "license": "MIT",
    "type": "project",
    "require": {
        "php": "^7.3|^8.0",
        "anik/form-request": "^4.3",
        "cviebrock/eloquent-sluggable": "^8.0.8",
        "dusterio/lumen-passport": "^0.3.4",
        "flipbox/lumen-generator": "^8.2.2",
        "illuminate/mail": "^8.70.2",
        "illuminate/notifications": "^8.70.2",
        "intervention/image": "^2.7.0",
        "laravel/lumen-framework": "^8.3.1",
        "league/flysystem": " ~1.1.5",
        "openzipkin/zipkin": "^2.0.2",
        "vinelab/tracing-laravel": "^2.0.2"
    },
    "require-dev": {
        "barryvdh/laravel-debugbar": "^3.6.4",
        "fakerphp/faker": "^1.16.0",
        "mockery/mockery": "^1.4.4",
        "phpunit/phpunit": "^9.5.10"
    },
    "autoload": {
        "files": [
            "app/library/helper.php"
        ],
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        }
    },
    "autoload-dev": {
        "classmap": [
            "tests/"
        ]
    },
    "config": {
        "preferred-install": "dist",
        "sort-packages": true,
        "optimize-autoloader": true
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "scripts": {
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ]
    }
}

How this error can be fixed?

Thanks!

'Vinelab\Tracing\Contracts\Tracer' is not Instantiable

Running on:

  • Laravel 8.15
  • PHP v7.4
  • Phpunit v9.4.3

We are adding a Phpunit functionality to provide some test coverage html page running the following command:
./vendor/bin/phpunit --coverage-html html

We get the following error:
Screenshot 2020-11-24 at 17 51 46

It is worth mentioning that we have in the same project a number of RabbitMq consumers running with Tracing enabled with no issues. And running the phpunit test suit goes as expected.

Once thing to mention is that to suppress Tracing while runing phpunit test we add the following to the phpunit.xml file:
<server name="TRACING_DRIVER" value="'null'"/>

Could this issue be pointing to a particular caveat within the service provider?

Update
Removing the null Tracing driver from phpunit.xml apparently circumvent the above issue.

Consider using idiomatic zipkin tags

Currently there are a couple of things that don't follow idiomatic naming in zipkin.

First, we usually use VERB /path/for/route as span names instead of a fixed name as it is less useful when it comes to search for an specific operation. E.g. GET /images/{image_id}. Notice the usage of {image_id} instead of the actual ID as high cardinality on this can make your span search struggle.

Second, there are a bunch of idiomatic zipkin tags that I would recommend to use instead of custom ones in https://github.com/Vinelab/tracing-laravel/blob/master/src/Middleware/TraceRequests.php#L75. See:
https://github.com/openzipkin/zipkin-php/blob/master/src/Zipkin/Tags.php

FInally I am concerned about the automatic adding request_headers into the tags, sensitive information like JWT can be carried here and at most you want ti to be optional and a concious decision because it implies some privacy issues. Also not sure https://github.com/Vinelab/tracing-laravel/blob/master/src/Middleware/TraceRequests.php#L80 includes query parameters, they also can carry sensitive information like api_key.

Tracing db queries

How can i set span duration?
Method "finish" in interface Vinelab\Tracing\Contracts\Span don't have parameters, but same method in Interface Zipkin\Span has parameter $timestamp.

Are we considering supporting `QueueReport`?

Using a queue can speed up the response time of your site and reduce a lot of risks. For example, if zipkin crashes, it won't affect the site.

It can be supported with very few code changes, I can provide a PR.

The reporter can be obtained through dependency injection.

tracing-laravel/src/Drivers/Zipkin/ZipkinTracer.php

protected function createReporter(): Reporter
{
    if (!$this->reporter) {
        return new HttpReporter([
            'endpoint_url' => sprintf('http://%s:%s/api/v2/spans', $this->host, $this->port),
            'timeout' => $this->requestTimeout,
        ]);
    }

    return $this->reporter;
}
class QueueReporter implements Reporter
{
    public function report(array $spans): void
    {
        if (count($spans) === 0) {
            return;
        }

        $reporterJob = new ReporterJob(
            config('tracing.zipkin.host'),
            config('tracing.zipkin.port'),
            config('tracing.zipkin.options.request_timeout', 1),
            $spans
        );
        dispatch($reporterJob)->onQueue();
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.