jcchavezs/zipkin-instrumentation-symfony

A Zipkin integration for Symfony applications

2.4.2 2020-04-08 21:09 UTC

README

Build Status CircleCI Latest Stable Version Minimum PHP Version Total Downloads License

A Zipkin integration for Symfony applications

Installation

composer require jcchavezs/zipkin-instrumentation-symfony

Getting started

This Symfony bundle provides a middleware that can be used to trace HTTP requests. In order to use it, it is important that you declare the middleware by adding this to app/config/services.yml or any other dependency injection declaration.

services:
  tracing_middleware:
    class: ZipkinBundle\Middleware
    arguments:
      - "@zipkin.default_tracing"
      - "@logger"
    tags:
      - { name: kernel.event_listener, event: kernel.request, priority: 2560 }
      - { name: kernel.event_listener, event: kernel.response, priority: -2560 }
      - { name: kernel.event_listener, event: kernel.exception }
      - { name: kernel.event_listener, event: kernel.terminate }

@zipkin.default_tracing is a Zipkin\DefaultTracing instance which is being built based on the configuration (add this to app/config/config.yml):

zipkin:
  noop: false # if set to true, no request will be traced
  service_name: my_service # the name of the service
  sampler:
    type: percentage
    percentage: 0.1

Samplers

Besides always, and never there are three other sampling strategies: by path, by route and by percentage, however it is also possible yo use your own sampler.

It is important to mention that the sampling decision is made on two situations: a) when a new trace is being started, b) when the extracted context does not include a sampling decision.

By path

This is for those cases where you want to make a sampling decision based on the url path:

zipkin:
  ...
  sampler:
    type: path
    path:
      included_paths:
        - "/my/resource/[0-9]"
      excluded_paths:
        - "/another/path/"

By route

This is for those cases where you want to make a sampling decision based on the symfony route:

zipkin:
  ...
  sampler:
    type: route
    route:
      included_routes:
        - "my_route"
      excluded_routes:
        - "another_route"

By percentage

This one is for those cases where you want to sample only a percentage of the requests (a.k.a "Sampling rate")

zipkin:
  ...
  sampler:
    type: percentage
    percentage: 0.1

Custom samplers

You can pass a custom sampler as long as it implements the Zipkin\Sampler interface. You just need to use the service id declared in the service container.

zipkin:
  ...
  sampler:
    type: custom
    custom: my_service_name

Reporters

By default, the bundle reports to Log reporter which wraps @logger.

HTTP reporter

This is the most common use case, it reports to a HTTP backend of Zipkin

zipkin:
  ...
  reporter:
    type: http
    http:
      endpoint_url: http://zipkin:9411/api/v2/spans
      timeout: ~

Default tags

You can add tags to every span being created by the tracer. This functionality is useful when you need to add tags like instance name.

services:
  tracing_middleware:
    class: ZipkinBundle\Middleware
    arguments:
      - "@zipkin.default_tracing"
      - "@logger"
      - { instance: %instance_name% }
    tags:
      - { name: kernel.event_listener, event: kernel.request, priority: 2560 }
      - { name: kernel.event_listener, event: kernel.response, priority: -2560 }
      - { name: kernel.event_listener, event: kernel.exception }
      - { name: kernel.event_listener, event: kernel.terminate }

Custom Tracing

Although this bundle provides a tracer based on the configuration parameters under the zipkin node, you can inject your own tracing component to the middleware as long as it implements the Zipkin\Tracing interface:

services:
  tracing_middleware:
    class: ZipkinBundle\Middleware
    arguments:
      - "@my_own_tracing"
      - "@logger"
    tags:
      - { name: kernel.event_listener, event: kernel.request, priority: 2560 }
      - { name: kernel.event_listener, event: kernel.response, priority: -2560 }
      - { name: kernel.event_listener, event: kernel.exception }
      - { name: kernel.event_listener, event: kernel.terminate }

Span customizers

Span customizers allow the user to add custom information to the span based on the request. For example by default the span name is being defined by the HTTP verb. This approach is a not so bad option seeking for low cardinality in span naming. A more useful approach is to use the route path: /user/{user_id} however including the @router in the middleware is expensive and reduces its performance thus the best is to precompile (aka cache warm up) a map of name => path in cache that can be used to resolve the path in runtime.

services:
  zipkin.span_customizer.by_path_namer:
    class: ZipkinBundle\SpanCustomizers\ByPathNamer\SpanCustomizer
    factory: [ZipkinBundle\SpanCustomizers\ByPathNamer\SpanCustomizer, 'create']
    arguments:
      - "%kernel.cache_dir%"

  zipkin.span_customizer.by_path_namer.cache_warmer:
    class: ZipkinBundle\SpanCustomizers\ByPathNamer\CacheWarmer
    arguments:
      - "@router"
    tags:
      - { name: kernel.cache_warmer, priority: 0 }

  tracing_middleware:
    class: ZipkinBundle\Middleware
    arguments:
      - "@zipkin.default_tracing"
      - "@logger"
      - { instance: %instance_name% }
      - "@zipkin.span_customizer.by_path_namer"
    tags:
      - { name: kernel.event_listener, event: kernel.request, priority: 2560 }
      - { name: kernel.event_listener, event: kernel.response, priority: -2560 }
      - { name: kernel.event_listener, event: kernel.exception }
      - { name: kernel.event_listener, event: kernel.terminate }

HTTP Client

This bundle includes an adapter for HTTP Client. For more details, read this doc.

Contributing

All contributions and feedback are welcome.

Unit testing

Run the unit tests with:

composer test

E2E testing

On every build we run a end to end (E2E) test against a symfony application. This test run in our CI tests but it can be also reproduced in local by:

  1. Go to tests/E2E
  2. Run SYMFONY_VERSION={{SYMFONY_VERSION}} make build to build the test application (by default newest version)
  3. Run make run-zipkin to start zipkin sever
  4. Run make run-app to start the test application
  5. Hit the application curl -i http://localhost:8002/_health
  6. Check that traces are in zipkin (http://localhost:9411/zipkin/)