Zipkin PHP is the official PHP Tracer implementation for Zipkin

Overview

Zipkin PHP

CI Latest Stable Version Coverage Status Minimum PHP Version Total Downloads License

Zipkin PHP is the official PHP Tracer implementation for Zipkin, supported by the OpenZipkin community.

Installation

composer require openzipkin/zipkin

Setup

use Zipkin\Annotation;
use Zipkin\Endpoint;
use Zipkin\Samplers\BinarySampler;
use Zipkin\TracingBuilder;
use Zipkin\Reporters\Http;

// First we create the endpoint that describes our service
$endpoint = Endpoint::create('my_service');

$reporter = new Http(['endpoint_url' => 'http://myzipkin:9411/api/v2/spans']);
$sampler = BinarySampler::createAsAlwaysSample();
$tracing = TracingBuilder::create()
    ->havingLocalEndpoint($endpoint)
    ->havingSampler($sampler)
    ->havingReporter($reporter)
    ->build();

$tracer = $tracing->getTracer();

...

$tracer->flush();

Obs. for a more complete frontend/backend example, check this repository.

Tracing

The tracer creates and joins spans that model the latency of potentially distributed work. It can employ sampling to reduce overhead in process or to reduce the amount of data sent to Zipkin.

Spans returned by a tracer report data to Zipkin when finished, or do nothing if unsampled. After starting a span, you can annotate events of interest or add tags containing details or lookup keys.

Spans have a context which includes trace identifiers that place it at the correct spot in the tree representing the distributed operation.

Local Tracing

When tracing local code, just run it inside a span

$span = $tracer->newTrace();
$span->setName('encode');
$span->start();

try {
  doSomethingExpensive();
} finally {
  $span->finish();
}

In the above example, the span is the root of the trace. In many cases, you will be a part of an existing trace. When this is the case, call newChild instead of newTrace

$span = $tracer->newChild($root->getContext());
$span->setName('encode');
$span->start();
try {
  doSomethingExpensive();
} finally {
  $span->finish();
}

Customizing spans

Once you have a span, you can add tags to it, which can be used as lookup keys or details. For example, you might add a tag with your runtime version.

$span->tag('http.status_code', '200');

RPC tracing

RPC tracing is often done automatically by interceptors. Under the scenes, they add tags and events that relate to their role in an RPC operation.

Here's an example of a client span:

// before you send a request, add metadata that describes the operation
$span = $tracer->newTrace();
$span->setName('get');
$span->setKind(Kind\CLIENT);
$span->tag('http.status_code', '200');
$span->tag(Tags\HTTP_PATH, '/api');
$span->setRemoteEndpoint(Endpoint::create('backend', 127 << 24 | 1, null, 8080));

// when the request is scheduled, start the span
$span->start();

// if you have callbacks for when data is on the wire, note those events
$span->annotate(Annotation\WIRE_SEND);
$span->annotate(Annotation\WIRE_RECV);

// when the response is complete, finish the span
$span->finish();

Sampling

Sampling may be employed to reduce the data collected and reported out of process. When a span isn't sampled, it adds no overhead (noop).

Sampling is an up-front decision, meaning that the decision to report data is made at the first operation in a trace, and that decision is propagated downstream.

By default, there's a global sampler that applies a single rate to all traced operations. Sampler is how you indicate this, and it defaults to trace every request.

Custom sampling

You may want to apply different policies depending on what the operation is. For example, you might not want to trace requests to static resources such as images, or you might want to trace all requests to a new api.

Most users will use a framework interceptor which automates this sort of policy. Here's how they might work internally.

private function newTrace(Request $request) {
  $flags = SamplingFlags::createAsEmpty();
  if (strpos($request->getUri(), '/experimental') === 0) {
    $flags = DefaultSamplingFlags::createAsSampled();
  } else if (strpos($request->getUri(), '/static') === 0) {
    $flags = DefaultSamplingFlags::createAsSampled();
  }
  return $tracer->newTrace($flags);
}

Propagation

Propagation is needed to ensure activity originating from the same root are collected together in the same trace. The most common propagation approach is to copy a trace context from a client sending an RPC request to a server receiving it.

For example, when an downstream Http call is made, its trace context is sent along with it, encoded as request headers:

   Client Span                                                Server Span
┌──────────────────┐                                       ┌──────────────────┐
│                  │                                       │                  │
│   TraceContext   │           Http Request Headers        │   TraceContext   │
│ ┌──────────────┐ │          ┌───────────────────┐        │ ┌──────────────┐ │
│ │ TraceId      │ │          │ X-B3-TraceId      │        │ │ TraceId      │ │
│ │              │ │          │                   │        │ │              │ │
│ │ ParentSpanId │ │ Extract  │ X-B3-ParentSpanId │ Inject │ │ ParentSpanId │ │
│ │              ├─┼─────────>│                   ├────────┼>│              │ │
│ │ SpanId       │ │          │ X-B3-SpanId       │        │ │ SpanId       │ │
│ │              │ │          │                   │        │ │              │ │
│ │ Sampled      │ │          │ X-B3-Sampled      │        │ │ Sampled      │ │
│ └──────────────┘ │          └───────────────────┘        │ └──────────────┘ │
│                  │                                       │                  │
└──────────────────┘                                       └──────────────────┘

The names above are from B3 Propagation, which is built-in to Brave and has implementations in many languages and frameworks.

Most users will use a framework interceptor which automates propagation. Here's how they might work internally.

Here's what client-side propagation might look like

// configure a function that injects a trace context into a request
$injector = $tracing->getPropagation()->getInjector(new RequestHeaders);

// before a request is sent, add the current span's context to it
$injector($span->getContext(), $request);

Here's what server-side propagation might look like

// configure a function that extracts the trace context from a request
$extractor = $tracing->getPropagation()->getExtractor(new RequestHeaders);
$extracted = $extractor($request);

$span = $tracer->newChild($extracted);
$span->setKind(Kind\SERVER);

If you aren't using a framework or don't have access to the Request object, you can extract the context from the $_SERVER variable

$extractor = $tracing->getPropagation()->getExtractor(new ServerHeaders);
$extracted = $extractor($_SERVER);

Extracting a propagated context

The Extractor reads trace identifiers and sampling status from an incoming request or message. The carrier is usually a request object or headers.

SamplingFlags|TraceContext is usually only used with $tracer->newChild(extracted), unless you are sharing span IDs between a client and a server.

Implementing Propagation

Extractor will output a SamplingFlags|TraceContext with one of the following:

  • TraceContext if trace and span IDs were present.
  • SamplingFlags if no identifiers were present

Current Span

Zipkin supports a "current span" concept which represents the in-flight operation. Tracer::currentSpan() can be used to add custom tags to a span and Tracer::nextSpan() can be used to create a child of whatever is in-flight.

A common use case for the current span is to instrument RPC clients. For example:

/**
  * This http clients composes an http client using PSR7
  */
class TraceClient implements ClientInterface
{
    public function request($method, $uri = '', array $options = [])
    {
        /* Gets the child Span of the current one */
        $span = $this->tracer->nextSpan();
        $span->setKind(Zipkin\Kind\CLIENT);
        $span->tag(Tags\HTTP_PATH, $uri);

        try {
            $response = $this->client->request($method, $uri, $options);
            $span->tag(Tags\HTTP_STATUS_CODE, $response->getStatusCode());

            return $response;
        catch (Throwable $e) {
            $span->setError($e);
            throw $e;
        } finally {
            $span->finish();
        }
    }
}

Setting a span in scope manually

When writing new instrumentation, it is important to place a span you created in scope as the current span.

In edge cases, you may need to clear the current span temporarily. For example, launching a task that should not be associated with the current request. To do this, simply pass null to openScope.

Instrumentation

Tests

Tests can be run by

composer test

Whereas static checks can be run by:

composer static-check

Reference

Comments
  • Explore possibilities for bulk reporting

    Explore possibilities for bulk reporting

    At the moment, every trace (a set of spans) from a request will end up being one http request to the reporter. This is not ideal but limitation in the language as PHP is, in many real-world contexts, single-threaded and does not have an event loop like Node.js so we must flush when the request finishes. This is something convenient at small scale but not much at a big scale. As the outcome of this issue we should come up with a solution to avoid the overhead on the immediate reporter vs. bulk reporter.

    Ping @adriancole @basvanbeek @beberlei @felixfbecker

    help wanted 
    opened by jcchavezs 23
  • Support for PHP 8.0

    Support for PHP 8.0

    Hi,

    I've noticed that there are 2 PR's already on this topic (#200 and #198 ), so I thought it might be ok to also have an issue about the challenges around this. Also being selfish and all I was hit by the incompatibility with PHP 8 as we're going through a migration process with a couple of projects that also use zipkin.

    Given that both PHP 7.1 & PHP 7.2 are past their EOL dates, is there a support target/plan with respect to backwards compatibility of various PHP versions?

    Thanks

    opened by andrei-dascalu 21
  • Add Memcached Reporter

    Add Memcached Reporter

    This PR adds memcached reporter. So basically it is similar to InMemory but it stores the value in a memcached server. It also should work as expected in case of concurrent reads and writes. it uses this feature from memcached https://www.php.net/manual/en/memcached.cas.php. This requires php-memcached extension, so it will be a breaking change.

    Usage

    In application, we use Memcached reporter not HTTP reporter.

    <?php
    // app.php
    include_once dirname(__FILE__) . "/vendor/autoload.php";
    
    use Zipkin\Annotation;
    use Zipkin\Endpoint;
    use Zipkin\Samplers\BinarySampler;
    use Zipkin\TracingBuilder;
    use Zipkin\Reporters\Aggregation\MemcachedClient;
    use Zipkin\Reporters\Memcached;
    
    $endpoint = Endpoint::create('clivern');
    
    $reporter = new Memcached([], new MemcachedClient('127.0.0.1'));
    
    $sampler = BinarySampler::createAsAlwaysSample();
    $tracing = TracingBuilder::create()
        ->havingLocalEndpoint($endpoint)
        ->havingSampler($sampler)
        ->havingReporter($reporter)
        ->build();
    
    $tracer = $tracing->getTracer();
    
    for ($i=1; $i <= 10000; $i++) {
      $span = $tracer->newTrace();
      $span->setName(sprintf("span_%d", $i));
      $span->start();
    
      try {
        // something quite fast
        var_dump("test");
      } finally {
        $span->finish();
      }
    
      $tracer->flush();
    }
    

    Then we create a cron job or a command to read from Memcached reporter and send to Zipkin using HTTP reporter. We may even add this as application middleware with a time interval.

    <?php
    // daemon.php
    include_once dirname(__FILE__) . "/vendor/autoload.php";
    
    use Zipkin\Reporters\Aggregation\MemcachedClient;
    use Zipkin\Reporters\Memcached;
    use Zipkin\Reporters\Http;
    
    $reporter = new Memcached([], new MemcachedClient('127.0.0.1'));
    $httpReporter = new Http(['endpoint_url' => 'http://zipkin.local:9411/api/v2/spans']);
    
    while (true) {
        $spans = $reporter->flush();
    
        if (!empty($spans)){
            $httpReporter->report($spans);
        }
    
        sleep(5);
    }
    

    Flushing can be based on a time interval or the stored value size (Memcached support value up to 1MB by default that's ~1000000 chars). i didn't add any implementation since it is totally up to the developer and the scale zipkin is used. reporting 2 spans/second will have a different implementation than 1000 spans/second and I think this shouldn't be part of the package. in case you will hit the 1MB size limit in a second, you can either increase memcached maximum object size or report with different memcached keys, so basically you split the collected spans across different memcached keys to get more space before flushing.

    Please let me know if something need to be adjusted!

    Fix #22

    Update:

    To run as single process

    <?php
    
    include_once dirname(__FILE__) . "/vendor/autoload.php";
    
    use Zipkin\Annotation;
    use Zipkin\Endpoint;
    use Zipkin\Samplers\BinarySampler;
    use Zipkin\TracingBuilder;
    use Zipkin\Reporters\Aggregation\MemcachedClient;
    use Zipkin\Reporters\Memcached;
    use Zipkin\Reporters\Http;
    
    
    $endpoint = Endpoint::create('orders_service');
    
    $httpReporter = new Http([
      'endpoint_url' => 'http://zipkin.local:9411/api/v2/spans'
    ]);
    
    $reporter = new Memcached(
        [],
        $httpReporter,
        new MemcachedClient('127.0.0.1')
    );
    
    $sampler = BinarySampler::createAsAlwaysSample();
    $tracing = TracingBuilder::create()
        ->havingLocalEndpoint($endpoint)
        ->havingSampler($sampler)
        ->havingReporter($reporter)
        ->build();
    
    $tracer = $tracing->getTracer();
    
    for ($i=1; $i <= 400; $i++) {
      $span = $tracer->newTrace();
      $span->setName(sprintf("span_%d", $i));
      $span->start();
    
      try {
        var_dump("report");
      } finally {
        $span->finish();
      }
    
      $tracer->flush();
    }
    
    opened by Clivern 16
  • Allow using custom Recorder and add option to always record spans

    Allow using custom Recorder and add option to always record spans

    This will let me implement "firehose mode", similar to what we have in py_zipkin.

    Basically what I need is a way to call 2 different Reporters:

    • one gets called only when sampled is True
    • one gets called every time (this is the firehose recorder) This cannot be accomplished with just one Reporter, because once we're inside the reporter we've lost any info on whether the trace was sampled or not.

    I can almost do this in zipkin-php, there are only 2 things missing.

    • if sampled is False, we create a NoopSpan. So I need an extra flag to inform the tracer that I always want to create a RealSpan
    • the Recorder is hardcoded inside the Tracer class, so I cannot pass my own.

    Once those 2 things are supported, I can write my own Recorder subclass that calls the right Reporters as needed with minimal changes to the core zipkin-php code.

    cc @adriancole

    opened by drolando 12
  • Enhancement: Normalize composer.json

    Enhancement: Normalize composer.json

    This PR

    • [x] normalizes composer.json

    💁‍♂️ I ran

    $ composer global require localheinz/composer-normalize
    

    followed by

    $ composer normalize
    

    For reference, see https://github.com/localheinz/composer-normalize.

    opened by localheinz 9
  • PHP 8: upgrade middlewares, phpunit and replace guzzle psr7 with nyholm

    PHP 8: upgrade middlewares, phpunit and replace guzzle psr7 with nyholm

    Proposal for issue #202

    • there was a bit of a snowball there with respect to aligning dependencies to work with minor PHP versions (I did not try too hard to find a way to keep 7.2 as per issue comments).
    • See https://github.com/php-http/discovery/issues/164 - guzzlehttp doesn't provide expected PSR-17 factories (there's code available ready for their v2, but that would mean dropping some stability constraints) => switched to nyholm (it claims some performance boost as well, though probably not too relevant since we're talking tests)
    • some tweaks around the tests: eg dechex() needs an int, but hexdec() returns int|float, running afoul of strong type check.
    • updated phpunit also due to version constraints (phpunit 8 was still complaining about running on php 8) which led to lots of warnings about prophecy having to use a trait for integration with phpunit (could ignore those I guess to aim for 7.2 compatibility), which requires phpspec/prophecy-phpunit which in turn requires min. 7.3
    • rename class that did not conform to PSR-4
    opened by andrei-dascalu 6
  • Add inSpan method for tracer

    Add inSpan method for tracer

    Sometimes you need to instrument operations that are being performed by legacy code. E.g. http call to a service but instead of using a http standard library like guzzle, it is being done with raw curl. Those times, the effort to actually replace the curl call and use a new shiny and instrumented library like guzzle is already a big effort and it is very error prone.

    In those cases, having a Tracer::inSpan($options, $callable, $args) method would be helpful as that method is going to do tracing around that legacy call without forcing you to touch the logic (more than passing the right variables into the callable). Does that sound a reasonable use case?

    Initial feedback from @adriancole:

    I think there have been similar discussions around this.. sleuth has the ability to do this also py_zipkin. to a degree zipkin-js does (promise tracing)

    Ping @adriancole @basvanbeek

    opened by jcchavezs 6
  • Http Reporter always calling http://localhost

    Http Reporter always calling http://localhost

    Hello,

    While trying to use zipkin-php in a docker-compose context, I found that traces sent to a zipkin server running inside compose network from a php script also running in compose would not be picked up, whereas the same script sent from local machine to the same zipkin (but running with exposed port 9411) would work ok.

    I found that:

    • as per zipkin-php-example code, simply creating the endpoint with $endpoint = Endpoint::create($endpointName, $ipv4, null, $port); doesn't have an impact on where the HttpReporter makes api calls (I would be expecting it calls a server found at $ipv4 ip)
    • passing an options array specifying the url to the Http reporter constructor works (endpoint_url key)

    How create_tracing method looks now:

    $endpoint = Endpoint::create($endpointName, $ipv4, null, $port); $http = \Zipkin\Reporters\Http\CurlFactory::create(); $reporter = new Zipkin\Reporters\Http($http, [ 'endpoint_url' => sprintf('http://%s:%s/api/v2/spans', $ipv4, $port) ]); $sampler = BinarySampler::createAsAlwaysSample(); $tracing = TracingBuilder::create() ->havingLocalEndpoint($endpoint) ->havingSampler($sampler) ->havingReporter($reporter) ->build();

    I'm not entirely sure whether my understanding is completely off (eg: is the $ipv4 where api calls should be made?) or whether this is a bug and what would be a way to handle it.

    I believe at the very least the docs should reflect this.

    Cheers

    opened by andrei-dascalu 6
  • Reporter silent error handling

    Reporter silent error handling

    Currently it is hard to debug/understand when our spans are not accepted by the zipkin Server.

    For instance my Zipkin client was sending a null value in a tag by doing $span->tag('curl.total_time', $info['total_time']); //total_time was null

    Zipkin Server response was 400 but that was hidden from me because of the try/catch block here https://github.com/openzipkin/zipkin-php/blob/master/src/Zipkin/Reporters/Http.php#L63

    I suggest adding Debug mode or Verbosity config to the client so that we know when things start failing for some reason.

    opened by telemmaite 6
  • Allow a timeout value to be set on the cURL Call.

    Allow a timeout value to be set on the cURL Call.

    Generally speaking, the Zipkin reporting call should be non-blocking and asynchronous. But since PHP almost doesn't have either of these properties, it's good to at least be sure that reporting of the Zipkin Trace is not causing a major delay in sampled traces.

    Closes #94

    opened by Aideen-Nasirishargh-CK 6
  • [#27] Removes dependency on guzzle.

    [#27] Removes dependency on guzzle.

    This PR removes the dependency on the guzzle client using curl by default. The factory interface allows users to create their own clients tho.

    Ping @beberlei @felixfbecker @cc5092

    Closes #27

    opened by jcchavezs 6
  • The field for Log Events cannot be set(key)

    The field for Log Events cannot be set(key)

                $span->log([
                    'event'=>'error',
                    'stack'=> (string)$exception,
                ]);
    

    image

    event and stack valid

    opened by tw2066 0
  • Calculate number of messages and message size among microservices

    Calculate number of messages and message size among microservices

    Hello everyone,

    I have a php app which communicates with other microservices for its operations.

    Can i use Zipkin to observe every message between microservices and their size?

    Essentially, i need to have a clear picture for the affinities between the microservices of my architecture.

    How can i do it?

    opened by ktsakos 2
  • Make CI use script based convention used in other projects

    Make CI use script based convention used in other projects

    If you don't mind, please move some of the logic inlined into ci.yml into build-bin, with a README and RELEASE.md like the other projects. Also, if you can, please change the GH actions file and job names so that they are basically the same (makes badges easier also).

    Here's a couple examples:

    • https://github.com/openzipkin/zipkin-ruby/pull/180
    • https://github.com/openzipkin/zipkin-api

    Motivation

    We are standardizing build script and job names for easy reference when people switch from one project to another. It is important that the tasks done in CI do not heavily rely on CI specific tools as in the future we may get into trouble like this again. For example, in the past we had to switch from travis to circle back to travis. Using scripts we control as entrypoints gives us flexibility as CI providers change their policies around open source communities.

    opened by codefromthecrypt 0
  • Reporter can't provide feedback on success

    Reporter can't provide feedback on success

    Currently reporter is not providing any feedback about the call to the zipkin server, if it fails it logs the error and don't fail and more so if it success, it won't notify the user about it.

    This is alright in normal situations but can be a bit obscure in tooling, for example: https://github.com/jcchavezs/jaeger2zipkin/blob/master/Main.php#L53

    One option is to add a debug log line on success. Any ideas @anuraaga @adriancole @basvanbeek ?

    opened by jcchavezs 3
  • Map is already too complicated

    Map is already too complicated

    Initially Map was a Getter/Setter supposed to act as a usual map (i.e. set/get by key, see https://github.com/openzipkin/zipkin-php/blob/master/src/Zipkin/Propagation/Map.php), unfortunately I also promoted its use for HTTP headers (for things like Symfony) and that is how Map also supported case insensitiviness and array access.

    Nowadays the lesson learnt is that each different Getter/Setter format deserve its own implementation rather than trying to reuse Map and hence to not add crap into existing abstractions. We can't change Map to be simpler now but we can create a very simple class for a truly simple map and use for the messaging abstraction (and deprecate Map), not sure how to call it tho:

    • SimpleMap
    • Array
    • ?

    Any idea @adriancole @anuraaga

    opened by jcchavezs 2
Releases(3.0.0)
  • 3.0.0(Nov 18, 2021)

    This version includes improvements in the API by introducing PHP attribute types in classes and also restricts support for PHP 7.4+. The new feature introduced is the MySQL instrumentation.

    What's Changed

    • PHP 8: upgrade middlewares, phpunit and replace guzzle psr7 with nyholm by @andrei-dascalu in https://github.com/openzipkin/zipkin-php/pull/203
    • chore(http-reporter): removes retrocompatibility constructor signature in https://github.com/openzipkin/zipkin-php/pull/205
    • Restrict support for PHP 7.4 in https://github.com/openzipkin/zipkin-php/pull/211
    • Removes span to array as it is deprecated in https://github.com/openzipkin/zipkin-php/pull/212
    • Uses unknown servicename in https://github.com/openzipkin/zipkin-php/pull/216
    • feat: adds Mysqli instrumentation in https://github.com/openzipkin/zipkin-php/pull/150
    • Allow different versions of psr/log for better compatibility by @adiachenko in https://github.com/openzipkin/zipkin-php/pull/219

    Thanks to the new contributors @andrei-dascalu and @adiachenko and others for the feedback.

    Full Changelog: https://github.com/openzipkin/zipkin-php/compare/2.0.2...3.0.0

    Source code(tar.gz)
    Source code(zip)
  • 3.0.0-rc.2(Nov 7, 2021)

    What's Changed

    • Allow different versions of psr/log for better compatibility by @adiachenko in https://github.com/openzipkin/zipkin-php/pull/219
    • Removes return type unwrap by @jcchavezs in https://github.com/openzipkin/zipkin-php/pull/220

    New Contributors

    • @adiachenko made their first contribution in https://github.com/openzipkin/zipkin-php/pull/219

    Full Changelog: https://github.com/openzipkin/zipkin-php/compare/3.0.0-rc.1...3.0.0-rc.2

    Source code(tar.gz)
    Source code(zip)
  • 3.0.0-rc.1(Oct 25, 2021)

  • 2.0.2(Nov 24, 2020)

    Span names containing \ like in My\Command would fail to serialize as we were not escaping them correctly. This release fixes that.

    Thanks to @KinaneD @adiachenko for detecting this.

    Source code(tar.gz)
    Source code(zip)
  • 2.0.1(Oct 21, 2020)

    @telemmaite found that it wasn't possible to assign the route to the HTTP span if it wasn't know at request parsing time. This wasn't the intended behaviour and hence this release solves that problem.

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(Oct 2, 2020)

    Version 2.0 is here. This release was mainly motivated by the new type system introduced in PHP 7.0 but in the way new amazing features appeared.

    Features

    • HTTP instrumentation
    • Firehose mode (thanks to @drolando)
    • Span Customizer
    • Span::error
    • b3 header for reporting calls to avoid sampling

    Bugfixes

    • Lowercase span name and service name as per swagger definition
    • RequestHeaders setter puts the value, overriding it if already exists

    Breaking changes

    • Minimum supported version PHP 7.1
    • Added typing to signatures
    • Removed metrics API

    Notice we did our best to not to break compatibility with 1.x users but it was impossible for some cases (e.g. custom samplers) but other than that there are not other major changes.

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-beta1(Jul 29, 2020)

    This is a pre-release for 2.0.0 and a call for users to try it out this new release that supports PHP 7.1+.

    No breaking changes have been introduced (besides the typing which is unavoidable) so if there is any please raise an issue.

    Source code(tar.gz)
    Source code(zip)
  • 1.3.6(May 18, 2020)

    Currently the put behaviour was misleading as it was appending values if the header already existed. With this change it will honour the name put as it will override whatever is in there.

    Source code(tar.gz)
    Source code(zip)
  • 1.3.5(Apr 24, 2020)

  • 1.3.4(Jul 30, 2019)

  • 1.3.3(Jul 3, 2019)

  • 1.3.2(Oct 5, 2018)

  • 1.3.1(Aug 28, 2018)

  • 1.3.0(Jul 24, 2018)

    A new cool feature was introduced:

    • #81: Option to add additional headers to endpoint request. Thanks to @anensshiya-govinthas-ck

    And some other important improvements:

    • #87: Reference phpunit schema as installed with composer. Thanks to @localheinz
    • #86: Normalize composer.json. Thanks to @localheinz
    • #88: Fixes dash characters in README. Thanks to @altitude
    Source code(tar.gz)
    Source code(zip)
  • 1.2.4(Jul 11, 2018)

    cURL reporter is outputting a OK when the request to the collector was successful. This could cause a lot of noise in the stdout. Fixed in https://github.com/jcchavezs/zipkin-php/pull/79 by @anensshiya-govinthas-ck

    Source code(tar.gz)
    Source code(zip)
  • 1.2.3(Jun 23, 2018)

  • 1.2.0(Mar 7, 2018)

    Failures on reporting used to polute logs as they were throwing exceptions, now exceptions are not being propagated but instead they are reported with metrics.

    Source code(tar.gz)
    Source code(zip)
  • 1.1.1(Mar 6, 2018)

  • 1.1.0(Mar 3, 2018)

  • 1.0.2(Feb 6, 2018)

    • Adds documentation to tags (a393eeccac211b613696dd073c80b5d92be22ff2)
    • Removes try/catch in the reporter (4e92bcfb3d6b474d87031629f28d767da29dd3b1)
    • Fixes PercentageSampler namespace (6ebebb6c2db751a7d10ccfbe700be127c2e6bc66)
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Jan 24, 2018)

    In 1.0.0 we have been discarding traceId and spanId with no 32 and 16 respectively length. Since brave does support shorter traceIds and spanIds as long as they are not empty we need parity on that to be tolerant readers.

    Source code(tar.gz)
    Source code(zip)
  • 1.0.0-beta7(Jan 18, 2018)

  • 1.0.0-beta6(Jan 16, 2018)

  • 1.0.0-beta5(Jan 10, 2018)

  • 1.0.0-beta4(Dec 4, 2017)

    • Adds support for in process context propagation (https://github.com/jcchavezs/zipkin-php/issues/29).
    • Minor fixes in the namespace of tests.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0-beta3(Nov 24, 2017)

  • 1.0.0-beta2(Nov 22, 2017)

Owner
Open Zipkin
Open Zipkin
PHP APM (Alternative PHP Monitor)

APM (Alternative PHP Monitor) APM (Alternative PHP Monitor) is a monitoring extension enabling native Application Performance Management (APM) for PHP

Patrick Allaert 310 Dec 4, 2022
Debug bar for PHP

PHP Debug Bar Displays a debug bar in the browser with information from php. No more var_dump() in your code! Features: Generic debug bar Easy to inte

Maxime Bouroumeau-Fuseau 4k Jan 8, 2023
Xdebug — Step Debugger and Debugging Aid for PHP

Xdebug Xdebug is a debugging tool for PHP. It provides step-debugging and a whole range of development aids, such as stack traces, a code profiler, fe

Xdebug 2.8k Jan 3, 2023
Kint - a powerful and modern PHP debugging tool.

Kint - debugging helper for PHP developers What am I looking at? At first glance Kint is just a pretty replacement for var_dump(), print_r() and debug

null 2.7k Dec 25, 2022
😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.

Tracy - PHP debugger Introduction Tracy library is a useful helper for everyday PHP programmers. It helps you to: quickly detect and correct errors lo

Nette Foundation 1.6k Dec 23, 2022
PHP Benchmarking framework

PHPBench is a benchmark runner for PHP analogous to PHPUnit but for performance rather than correctness. Features include: Revolutions: Repeat your co

PHPBench 1.7k Jan 2, 2023
The Interactive PHP Debugger

The interactive PHP debugger Implemented as a SAPI module, phpdbg can exert complete control over the environment without impacting the functionality

Joe Watkins 841 Oct 9, 2022
Dontbug is a reverse debugger for PHP

Dontbug Debugger Dontbug is a reverse debugger (aka time travel debugger) for PHP. It allows you to record the execution of PHP scripts (in command li

Sidharth Kshatriya 709 Dec 30, 2022
PHP Debug Console

PHP Console A web console to try your PHP code into Creating a test file or using php's interactive mode can be a bit cumbersome to try random php sni

Jordi Boggiano 523 Nov 7, 2022
Php Debugger to run in terminal to debug your code easily.

What is Dephpugger? Dephpugger (read depugger) is an open source lib to make a debug in php direct in terminal, without necessary configure an IDE. Th

Renato Cassino 190 Dec 3, 2022
PCOV - CodeCoverage compatible driver for PHP

PCOV A self contained CodeCoverage compatible driver for PHP Requirements and Installation See INSTALL.md API /** * Shall start recording coverage in

Joe Watkins 613 Dec 21, 2022
Low-overhead sampling profiler for PHP 7+

phpspy phpspy is a low-overhead sampling profiler for PHP. For now, it works with Linux 3.2+ x86_64 non-ZTS PHP 7.0+ with CLI, Apache, and FPM SAPIs.

Adam 1.3k Dec 24, 2022
The VarDumper component provides mechanisms for walking through any arbitrary PHP variable. It provides a better dump() function that you can use instead of var_dump().

VarDumper Component The VarDumper component provides mechanisms for walking through any arbitrary PHP variable. It provides a better dump() function t

Symfony 7.1k Jan 1, 2023
PHP errors for cool kids

whoops PHP errors for cool kids whoops is an error handler framework for PHP. Out-of-the-box, it provides a pretty error interface that helps you debu

Filipe Dobreira 12.9k Dec 24, 2022
Clockwork - php dev tools in your browser - server-side component

Clockwork is a development tool for PHP available right in your browser. Clockwork gives you an insight into your application runtime - including requ

its 4.8k Dec 29, 2022
Laravel Debugbar (Integrates PHP Debug Bar)

Laravel Debugbar This is a package to integrate PHP Debug Bar with Laravel. It includes a ServiceProvider to register the debugbar and attach it to th

Barry vd. Heuvel 14.8k Jan 9, 2023
This package connects a Laravel Octance application with Tideways for PHP Monitoring, Profiling and Exception Tracking.

Tideways Middleware for Laravel Octane This package connects a Laravel Octance application with Tideways for PHP Monitoring, Profiling and Exception T

Tideways 7 Jan 6, 2022
A tool to profile mysql queries in php env.

MysqlQueryProfiler This tool helps you to quickly profile a mysql query in a PHP 7.4+ environnement. You can also compare 2 queries. This image shows

null 8 Jul 30, 2021
Datadog Tracing PHP Client

DD Trace PHP PHP Tracer Getting Started The Datadog PHP Tracer (ddtrace) brings APM and distributed tracing to PHP. Installing the extension Visit the

Datadog, Inc. 307 Jan 7, 2023