Giter VIP home page Giter VIP logo

aiozipkin's Introduction

aiozipkin

Maintainability Documentation Status Chat on Gitter

aiozipkin is Python 3.6+ module that adds distributed tracing capabilities from asyncio applications with zipkin (http://zipkin.io) server instrumentation.

zipkin is a distributed tracing system. It helps gather timing data needed to troubleshoot latency problems in microservice architectures. It manages both the collection and lookup of this data. Zipkin’s design is based on the Google Dapper paper.

Applications are instrumented with aiozipkin report timing data to zipkin. The Zipkin UI also presents a Dependency diagram showing how many traced requests went through each application. If you are troubleshooting latency problems or errors, you can filter or sort all traces based on the application, length of trace, annotation, or timestamp.

zipkin ui animation

Features

  • Distributed tracing capabilities to asyncio applications.
  • Support zipkin v2 protocol.
  • Easy to use API.
  • Explicit context handling, no thread local variables.
  • Can work with jaeger and stackdriver through zipkin compatible API.

zipkin vocabulary

Before code lets learn important zipkin vocabulary, for more detailed information please visit https://zipkin.io/pages/instrumenting

zipkin ui glossary

  • Span represents one specific method (RPC) call
  • Annotation string data associated with a particular timestamp in span
  • Tag - key and value associated with given span
  • Trace - collection of spans, related to serving particular request

Simple example

import asyncio
import aiozipkin as az


async def run():
    # setup zipkin client
    zipkin_address = 'http://127.0.0.1:9411/api/v2/spans'
    endpoint = az.create_endpoint(
        "simple_service", ipv4="127.0.0.1", port=8080)
    tracer = await az.create(zipkin_address, endpoint, sample_rate=1.0)

    # create and setup new trace
    with tracer.new_trace(sampled=True) as span:
        # give a name for the span
        span.name("Slow SQL")
        # tag with relevant information
        span.tag("span_type", "root")
        # indicate that this is client span
        span.kind(az.CLIENT)
        # make timestamp and name it with START SQL query
        span.annotate("START SQL SELECT * FROM")
        # imitate long SQL query
        await asyncio.sleep(0.1)
        # make other timestamp and name it "END SQL"
        span.annotate("END SQL")

    await tracer.close()

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run())

aiohttp example

aiozipkin includes aiohttp server instrumentation, for this create web.Application() as usual and install aiozipkin plugin:

import aiozipkin as az

def init_app():
    host, port = "127.0.0.1", 8080
    app = web.Application()
    endpoint = az.create_endpoint("AIOHTTP_SERVER", ipv4=host, port=port)
    tracer = await az.create(zipkin_address, endpoint, sample_rate=1.0)
    az.setup(app, tracer)

That is it, plugin adds middleware that tries to fetch context from headers, and create/join new trace. Optionally on client side you can add propagation headers in order to force tracing and to see network latency between client and server.

import aiozipkin as az

endpoint = az.create_endpoint("AIOHTTP_CLIENT")
tracer = await az.create(zipkin_address, endpoint)

with tracer.new_trace() as span:
    span.kind(az.CLIENT)
    headers = span.context.make_headers()
    host = "http://127.0.0.1:8080/api/v1/posts/{}".format(i)
    resp = await session.get(host, headers=headers)
    await resp.text()

Documentation

http://aiozipkin.readthedocs.io/

Installation

Installation process is simple, just:

$ pip install aiozipkin

Support of other collectors

aiozipkin can work with any other zipkin compatible service, currently we tested it with jaeger and stackdriver.

Jaeger support

jaeger supports zipkin span format as result it is possible to use aiozipkin with jaeger server. You just need to specify jaeger server address and it should work out of the box. Not need to run local zipkin server. For more informations see tests and jaeger documentation.

jaeger ui animation

Stackdriver support

Google stackdriver supports zipkin span format as result it is possible to use aiozipkin with this google service. In order to make this work you need to setup zipkin service locally, that will send trace to the cloud. See google cloud documentation how to setup make zipkin collector:

jaeger ui animation

Requirements

aiozipkin's People

Contributors

asovchar avatar asvetlov avatar asyd avatar deejay1 avatar dependabot-preview[bot] avatar dependabot[bot] avatar dreamsorcerer avatar dsantosfff avatar faulkner avatar gugu avatar jameshilliard avatar jettify avatar konstantin-stepanov avatar leenr avatar pre-commit-ci[bot] avatar pyup-bot avatar rdehouss avatar shadchin avatar zubenkoivan 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  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  avatar

aiozipkin's Issues

implement "b3 single" header format

As discussed on openzipkin/b3-propagation#21 and first implemented here: https://github.com/openzipkin/brave/blob/master/brave/src/main/java/brave/propagation/B3SingleFormat.java https://github.com/openzipkin/brave/blob/master/brave/src/test/java/brave/propagation/B3SingleFormatTest.java

Let's support at least reading "b3" header from a single string, most commonly traceid-spanid-1
It would also be nice to support optionally writing this, especially in message providers or others with constrained environments.

Brave currently has a property like this, but its name could change with feedback:

    /**
     * When true, only writes a single {@link B3SingleFormat b3 header} for outbound propagation.
     *
     * <p>Use this to reduce overhead. Note: normal {@link Tracing#propagation()} is used to parse
     * incoming headers. The implementation must be able to read "b3" headers.
     */
    public Builder b3SingleFormat(boolean b3SingleFormat) {
      this.b3SingleFormat = b3SingleFormat;
      return this;
}

the example may need to change

This example

await tracer.close()
import asyncio
import aiozipkin as az


async def run():
    # setup zipkin client
    zipkin_address = 'http://127.0.0.1:9411'
    endpoint = az.create_endpoint(
        'simple_service', ipv4='127.0.0.1', port=8080)

    # creates tracer object that traces all calls, if you want sample
    # only 50% just set sample_rate=0.5
    tracer = az.create(zipkin_address, endpoint, sample_rate=1.0)

    # create and setup new trace
    with tracer.new_trace(sampled=True) as span:
        span.name('root_span')
        span.tag('span_type', 'root')
        span.kind(az.CLIENT)
        span.annotate('SELECT * FROM')
        # imitate long SQL query
        await asyncio.sleep(0.1)
        span.annotate('start end sql')

        # create child span
        with tracer.new_child(span.context) as nested_span:
            nested_span.name('nested_span_1')
            nested_span.kind(az.CLIENT)
            nested_span.tag('span_type', 'inner1')
            nested_span.remote_endpoint('remote_service_1')
            await asyncio.sleep(0.01)

        # create other child span
        with tracer.new_child(span.context) as nested_span:
            nested_span.name('nested_span_2')
            nested_span.kind(az.CLIENT)
            nested_span.remote_endpoint('remote_service_2')
            nested_span.tag('span_type', 'inner2')
            await asyncio.sleep(0.01)

        await asyncio.sleep(30)
        await tracer.close()

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run())

The await tracer.close() may be need put outside the with. Otherwise the root span can't be sent to collecter.

Release with latest commits

Is it possible to release the packet with the latests commits ?

I currently need what's in 5.1. Can you release it on pypi ? Thanks !

Investigate logging transport like in py_zipkin

Currently aiozipkin uses HTTP transport to send spans, I think it will be useful to implement sending spans with logging subsystems.

  1. investigate how other clients employ logging subsystem (scribe?)
  2. figure out how to do testing infrastructure

aiohttp: Implement a list of ignored url/patterns

Hi,

i'm wondering if you're agree to provide an optional argument to aiohttp_helpers to define a list of url/patterns that should be ignored by the middleware? I use aiozipkin in APIs that provide healtcheck and I don't want to have trace for each healthcheck call (but I want a sample_rate set to 1)

Thanks

Implement simple hash based sampler (sample request based on hash value of trace_id)

  1. Create abstract base class SamplerAbc
  2. Make current class subclass of SamplerAbc
  3. Implement one more sampler class base and hash idea from brave

class Sampler:
def __init__(self, *, sample_rate=1.0, seed=None):
self._sample_rate = sample_rate
self._rng = Random(seed)
def is_sampled(self, trace_id):
if self._sample_rate == 0.0:
sampled = False
else:
sampled = self._rng.random() <= self._sample_rate
return sampled

But sampling logic ported from here:
https://github.com/openzipkin/brave/blob/967e48507f6267c07e3238b8f30575c683690ef6/brave/src/main/java/brave/sampler/BoundarySampler.java#L43-L47

Span's context manager marks aiohttp.HTTPException as an error

aiohttp provides HTTPException, so the return values can be raised as exceptions.
The problem is that the context manager of the span.Span class handles them as a common exception and adds an error tag to the span.
Is there any way not to add this tag to HTTPSuccessful, HTTPRedirection and HTTPClientError?

Memory leak

To quickly reproduce the problem, you need to reduce the value of the argument send_inteval to a very small value and see what happens with the memory.

Here is an example of code for reproduce a memory leak:

import gc
import asyncio
import aiozipkin as az
from functools import partial
from pympler import muppy, summary


def mem_test(loop):
    gc.collect()
    try:
        all_objects = muppy.get_objects()
        sum = summary.summarize(all_objects)
        summary.print_(sum)
    finally:
        loop.call_later(1, partial(mem_test, loop))


async def run():
    zipkin_address = 'http://127.0.0.1:9411'
    endpoint = az.create_endpoint('minimal_example', ipv4='127.0.0.1')

    tracer = az.create(zipkin_address, endpoint, sample_rate=1.0,
                       send_inteval=0.001)

    await asyncio.sleep(60)

    await tracer.close()

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.call_soon(partial(mem_test, loop))
    try:
        loop.run_until_complete(run())
    except KeyboardInterrupt:
        pass

The problem in function _wait of Transport.

It's difficult for me to explain this behavior, but replacing the function asyncio.as_completed to asyncio.wait solves this problem

    async def _wait(self) -> None:
        self._timer = asyncio.ensure_future(
            asyncio.sleep(self._send_interval, loop=self._loop),
            loop=self._loop)

        await asyncio.wait([self._timer, self._ender], loop=self._loop,
                           return_when=asyncio.FIRST_COMPLETED)

Loop argument deprecated in Python 3.8

In Python 3.8, there's a lot of warnings around the loop argument in asyncio being dropped. This should be fixed so as it doesn't break in the future.

.../aiozipkin/transport.py:113: DeprecationWarning: The loop argument is deprecated since Python 3.8, and scheduled for removal in Python 3.10.
  await asyncio.wait([self._timer, self._ender], loop=self._loop,

implement `new_child` method in Span class

I think that would be useful. Because now I have to write something like:

with parent_span.tracer.new_child(parent_span.context) as span:
    span.name('some:action')
    span.kind(CLIENT)
    # do something

I propose to define a method new_child in Span class(also in SpanAbs and SpanNoop) like:

class Span(SpanAbc):

    def new_child(self, name: str = None, kind: str = None) -> 'Span':
        span = self.tracer.new_child(self.context)
        if name is not None:
            span.name(name)
        if kind is not None:
            span.kind(kind)
        return span

    ...

then it could be used like:

with parent_span.new_child('some:action', CLIENT) as span:
    # do some thing

What do you think about it?

example/queue: Application.make_handler(...) is deprecated

Thanks for the good examples.
There's warning when running example/queue:
queue/runner.py:19: DeprecationWarning: Application.make_handler(...) is deprecated, use AppRunner API instead

python 3.7.2
aiozipkin==0.5.0
aiohttp==3.5.4
aiojobs==0.2.2

Checked latest aiohttp doc., maybe need to update like this (it works without warnings):

# /examples/queue/runner.py
def run():
    ...
    fe_handler = web.AppRunner(fe_app)
    be_handler = web.AppRunner(be_app)
    handlers = [fe_handler, be_handler]
    
    loop_run(fe_handler.setup())
    loop_run(be_handler.setup())

    loop_run(loop.create_server(fe_handler.server, host, fe_port))
    loop_run(loop.create_server(be_handler.server, host, be_port))

Provide an example to set parent_id

Hi,

I want to use aiozipkin in a micro services architecture, so my goal is to have a whole span with child span for each services. However I was not able to find how to create a child span with a given parent_id, can you provide an example please?

Thanks

Tornado Instrumentation

Hi, thanks for this project.

Is there any interest in a Tornado instrumentation? I'd love to implement it if there's interest and some pointers can be given on how to best do it.

Implement async context manager API for az.create

  1. az.create should be coroutine if at some point we decide to include rabbit/kafka/other integration, it will be very essential. From other side the is breaking change, better to do this earlier.

  2. Context manager API should look like:

async with az.create(zipkin_address, endpoint, sample_rate=1.0) as tracer
    with tracer.new_trace(sampled=True) as span:
        span.name('root_span')
  1. Old approach should work also:
tracer = await az.create(zipkin_address, endpoint, sample_rate=1.0)
await tracer.close()

Allow for specifying full path to zipkin endpoint

Right now the zipkin address always has api/v2/spans appended to it, which doesn't allow for providing a full URL for the transport when the receiver requires a different URL (in our case it's a custom queue provider which then forwards the spans to proper collectors). Overriding that requires creation of a custom transport and create() function.

This is somewhat related to #140

coroutine 'Tracer.close' was never awaited

Hi,

I see I get this message on my API when I close it with CTRL-C:

aiozipkin/aiohttp_helpers.py:60: RuntimeWarning: coroutine 'Tracer.close' was never awaited
  app[tracer_key].close()
2017-11-17 23:05:03,077 - asyncio - ERROR - Unclosed client session```

When I close the tracer myself with `await tracer.close()`, it's fine.

I think it's just about adding `await` there: https://github.com/aio-libs/aiozipkin/blob/master/aiozipkin/aiohttp_helpers.py#L60

Cheers,

Raphaël

Rework queue example

For better demo queue (producer/consumer) demo, we need to rework it. Following features should be added:

  • Use real queue, like rabbigmq
  • Use docker to automate start queue servcie
  • Service could do simple page scraping, say user submit URL using frontend service as result
    workers pick it, and fetch page.

Move docstrings into code

Maybe we should move the docstrings from api.rst into the code itself. This would allow the docs to be kept more up to date.

Support @trace decorator using contextvars (similar to starlette-zipkin)

I would like if aiozipkin support such a syntax below:

@trace(exclude_params=["auth"])
async def my_func(
    a: int,
    b: str,
    auth: str,
    c: dict[str, int],
):
    # ...


def other_func(a: int, b: list[str]):
    # ...
    x = get_my_array()
    y = get_my_str()

    with new_child_from_fls(name="calculate_then_do_something") as span:
        span.tag_input(x=x, y=y)
        r = calculate_result(x, y)
        r2 = do_something_more(r)
        span.tag_output(r2)

The main advantage of this design is,
it does not require tracer-context explicitly, by using contextvars (I'll call it as fiber-local storage, FLS),
so we don't have to modify existing functions.
In case of decorator, if span_name is not given, we can automatically get the function name.
We can also collect input args and return value of the function, and add tags (i.e. Span.tag(...)) for them automatically.
(That's what exclude_params exists for)

Actually I've already implemented it and tested it on python 3.10+, with fastapi.
After put @trace decorator to everywhere I want, two things were needed.

  • I created a tracer using az.create, and stored it in app context (e.g. fastapi.FastAPI.extra["tracer"] = tracer)
  • In a middleware function, for every request, get the tracer from the app context, then store the tracer and root span in FLS variables.
    • At the and of the middleware function, it's better to reset(=undo) FLS variables.

Firstly I saw decorator design from starlette-zipkin,
but I found out that starlette-zipkin's @trace decorator is not fiber-safe...

Anyway, is there any technical problem with this design?
Is it dangerous to use FLS variables?

Microservices Demo: no services interconnection in Zipkin UI

I am trying to run Microservices Demo. After doing all the operations, when I open Zipkin UI, I see the following:

Снимок экрана от 2020-09-09 16:01:04

5 single traces instead one, no services interconnection.

But I was expecting something like this:
image

I don't really understand what I am doing wrong. Can anyone please help?

Make aiozipkin work with stackdriver

Looks like stackdriver-zipkin does not like when kind is null

2017-12-29 21:26:03.741  WARN 5 --- [tp1325056130-17] zipkin.server.ZipkinHttpCollector        : Cannot decode spans due to IllegalArgumentException(Expected a string but was NULL at line 1 column 144 path $[0].kind reading List<Span2> from json: [{"traceId": "aaf6a73afc1331c969f58e8d3bad1c3a", "name": "mysql:select", "parentId": "970a503795e2f192", "id": "f3793bd84c69b83d", "kind": null, "timestamp": 1514582758614251, "duration": 10204, "debug": false, "shared": false, "localEndpoint": {"serviceName": "aiohttp_server", "ipv4": "127.0.0.1", "port": 8080}, "remoteEndpoint": null, "annotations": [], "tags": {}}, {"traceId": "aaf6a73afc1331c969f58e8d3bad1c3a", "name": "GET /api/v1/posts/0", "parentId": null, "id": "970a503795e2f192", "kind": "SERVER", "timestamp": 1514582758614171, "duration": 10433, "debug": false, "shared": true, "localEndpoint": {"serviceName": "aiohttp_server", "ipv4": "127.0.0.1", "port": 8080}, "remoteEndpoint": {"ipv4": "127.0.0.1"}, "annotations": [], "tags": {"http.path": "/api/v1/posts/0", "http.method": "GET", "http.status_code": "200"}}])

java.lang.IllegalArgumentException: Expected a string but was NULL at line 1 column 144 path $[0].kind reading List<Span2> from json: [{"traceId": "aaf6a73afc1331c969f58e8d3bad1c3a", "name": "mysql:select", "parentId": "970a503795e2f192", "id": "f3793bd84c69b83d", "kind": null, "timestamp": 1514582758614251, "duration": 10204, "debug": false, "shared": false, "localEndpoint": {"serviceName": "aiohttp_server", "ipv4": "127.0.0.1", "port": 8080}, "remoteEndpoint": null, "annotations": [], "tags": {}}, {"traceId": "aaf6a73afc1331c969f58e8d3bad1c3a", "name": "GET /api/v1/posts/0", "parentId": null, "id": "970a503795e2f192", "kind": "SERVER", "timestamp": 1514582758614171, "duration": 10433, "debug": false, "shared": true, "localEndpoint": {"serviceName": "aiohttp_server", "ipv4": "127.0.0.1", "port": 8080}, "remoteEndpoint": {"ipv4": "127.0.0.1"}, "annotations": [], "tags": {"http.path": "/api/v1/posts/0", "http.method": "GET", "http.status_code": "200"}}]
	at zipkin.internal.JsonCodec.exceptionReading(JsonCodec.java:738) ~[zipkin-1.30.2.jar!/:na]
	at zipkin.internal.JsonCodec.readList(JsonCodec.java:661) ~[zipkin-1.30.2.jar!/:na]
	at zipkin.internal.Span2JsonCodec.readSpans(Span2JsonCodec.java:48) ~[zipkin-1.30.2.jar!/:na]
	at zipkin.internal.Span2JsonDecoder.readSpans(Span2JsonDecoder.java:29) ~[zipkin-1.30.2.jar!/:na]
	at zipkin.collector.Collector.acceptSpans(Collector.java:93) ~[zipkin-1.30.2.jar!/:na]
	at zipkin.server.ZipkinHttpCollector.validateAndStoreSpans(ZipkinHttpCollector.java:99) [zipkin-server-1.30.2.jar!/:na]
	at zipkin.server.ZipkinHttpCollector.uploadSpansJson2(ZipkinHttpCollector.java:68) [zipkin-server-1.30.2.jar!/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_131]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) [spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) [spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) [spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) [spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) [spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) [spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) [javax.servlet-api-3.1.0.jar!/:3.1.0]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [javax.servlet-api-3.1.0.jar!/:3.1.0]
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:206) [websocket-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55) [spring-boot-1.5.6.RELEASE.jar!/:1.5.6.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110) [spring-boot-actuator-1.5.6.RELEASE.jar!/:1.5.6.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) [spring-boot-actuator-1.5.6.RELEASE.jar!/:1.5.6.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) [jetty-security-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) [jetty-servlet-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:454) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.Server.handle(Server.java:564) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:317) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251) [jetty-server-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279) [jetty-io-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110) [jetty-io-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124) [jetty-io-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:673) [jetty-util-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:591) [jetty-util-9.4.6.v20170531.jar!/:9.4.6.v20170531]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
Caused by: java.lang.IllegalStateException: Expected a string but was NULL at line 1 column 144 path $[0].kind
	at zipkin.internal.gson.stream.JsonReader.nextString(JsonReader.java:825) ~[zipkin-1.30.2.jar!/:na]
	at zipkin.internal.Span2JsonCodec$SimpleSpanReader.fromJson(Span2JsonCodec.java:74) ~[zipkin-1.30.2.jar!/:na]
	at zipkin.internal.Span2JsonCodec$SimpleSpanReader.fromJson(Span2JsonCodec.java:55) ~[zipkin-1.30.2.jar!/:na]
	at zipkin.internal.JsonCodec.readList(JsonCodec.java:657) ~[zipkin-1.30.2.jar!/:na]
	... 72 common frames omitted

Add support for jaeger-collector

Jaeger-collector can accept zipkin spans, but in current implementation it does not working. It because there is no header Content-Type: application/json in the request and there may be nulls ​​in the values ​​of ip addresses

Resolve warning from aiohttp related to new middleware API

=============================== warnings summary ===============================
tests/test_aiohttp_helpers.py::test_middleware_cleanup_app
  /home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/aiohttp/web_app.py:165: DeprecationWarning: old-style middleware "<function middleware_maker.<locals>.middleware_factory at 0x2b55120660d0>" deprecated, see #2252
    self._middlewares_handlers = tuple(self._prepare_middleware())
tests/test_aiohttp_ingegration.py::test_handler_with_client_signals
  /home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/aiohttp/pytest_plugin.py:329: DeprecationWarning: Deprecated, use aiohttp_client fixture instead
    DeprecationWarning)
  /home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/aiohttp/web_app.py:165: DeprecationWarning: old-style middleware "<function middleware_maker.<locals>.middleware_factory at 0x2b5512052620>" deprecated, see #2252
    self._middlewares_handlers = tuple(self._prepare_middleware())
tests/test_aiohttp_ingegration.py::test_handler_with_client_signals_error
  /home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/aiohttp/pytest_plugin.py:329: DeprecationWarning: Deprecated, use aiohttp_client fixture instead
    DeprecationWarning)
  /home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/aiohttp/web_app.py:165: DeprecationWarning: old-style middleware "<function middleware_maker.<locals>.middleware_factory at 0x2b5511ff5488>" deprecated, see #2252
    self._middlewares_handlers = tuple(self._prepare_middleware())
-- Docs: https://docs.pytest.org/en/latest/warnings.html

aio-libs/aiohttp#2252

Record.annotate() behavior

Is it correct behavior for method Record.annotate?

def annotate(self, value, ts):
        if value == CLIENT_SEND:
            self.kind(CLIENT)
            self._timestamp = ts
        elif value == SERVER_RECEIVED:
            self.kind(SERVER)
            self._timestamp = ts
        elif value == CLIENT_RECEIVED:
            self.kind(CLIENT)
            self.finish(ts)
        elif value == SERVER_SEND:
            self.kind(SERVER)
            self.finish(ts)
        else:
            v = {'value': value, 'timestamp': int(ts)}
            self._annotations.append(v)
        return self

What if user want to send "cs" value as annotation, like span.annotate('cs')? And user want to see it as annotation, not as timestamp correction.
For example, I log every request body of inbound requests in my API and some one sent sr in request body. In this case, I will not see anything in the annotation.
It can be any other example in which we store some random data as an annotation.

If you want to keep the current behavior, you can make the value of CLIENT_SEND (and others) as instance of the class inherited from str. And in the annotate method check for isinstance, not for equivalence

aiozipkin 0.5.0 does not work with python 3.5.3 and aiohttp >= 3.0 , < 3.1

Hello,

  1. aiozipkin 0.5.0 does not work with python 3.5.3 and aiohttp >= 3.0 , < 3.1.
    Indeed, my tests failed with: cannot import name 'AsyncContextManager'. So, python 3.5.4 is required because typing.AsyncGenerator is new in python 3.5.4 (https://docs.python.org/3.5/library/typing.html#typing.AsyncGenerator)
...
[2020-05-19T08:46:37.878Z] ______________ ERROR collecting xxx/tests/test_xxx.py ______________
[2020-05-19T08:46:37.878Z] ImportError while importing test module 'xxx/tests/test_xxx.py'.
[2020-05-19T08:46:37.878Z] Hint: make sure your test modules/packages have valid Python names.
[2020-05-19T08:46:37.878Z] Traceback:
[2020-05-19T08:46:37.878Z] xxx/tests/__init__.py:16: in <module>
[2020-05-19T08:46:37.878Z]     from xxx.bin.api import init_webapp  # noqa
[2020-05-19T08:46:37.878Z] xxx/bin/api.py:8: in <module>
[2020-05-19T08:46:37.878Z]     import aiozipkin
[2020-05-19T08:46:37.878Z] .pyenv-python3.5/lib/python3.5/site-packages/aiozipkin/__init__.py:1: in <module>
[2020-05-19T08:46:37.878Z]     from .aiohttp_helpers import (
[2020-05-19T08:46:37.878Z] .pyenv-python3.5/lib/python3.5/site-packages/aiozipkin/aiohttp_helpers.py:15: in <module>
[2020-05-19T08:46:37.878Z]     from .tracer import Tracer
[2020-05-19T08:46:37.878Z] .pyenv-python3.5/lib/python3.5/site-packages/aiozipkin/tracer.py:1: in <module>
[2020-05-19T08:46:37.878Z]     from typing import Optional, Dict, Awaitable, Any, AsyncContextManager, cast, TYPE_CHECKING  # flake8: noqa
[2020-05-19T08:46:37.878Z] E   ImportError: cannot import name 'AsyncContextManager'
...
  1. Contrary to what is mentioned in your README file, aiozipkin is not a python 3.5+ module
aiozipkin is Python 3.5+ module ...

Can you update your documentation please?

Best regards,
rodnsi

exception raised for 404s

There is no relevant resource for 404s, yet in my case aiozipkin tries to access resource.canonical.

E.g.:

...
   File "/usr/local/lib/python3.7/dist-packages/aiohttp/web_middlewares.py", line 110, in impl
     return await handler(request)
   File "/usr/local/lib/python3.7/dist-packages/aiozipkin/aiohttp_helpers.py", line 154, in aiozipkin_middleware
     _set_span_properties(span, request)
   File "/usr/local/lib/python3.7/dist-packages/aiozipkin/aiohttp_helpers.py", line 102, in _set_span_properties
     route = resource.canonical
AttributeError: 'NoneType' object has no attribute 'canonical'

Happy to try and submit a fix for this, if this is indeed a bug.

aiozipkin 1.1.0 on Kali Linux.

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.