a flask zipkin extension based on py_zipkin.

Related tags

Flaskflask-zipkin
Overview

flask-zipkin

a flask zipkin extension based on py_zipkin.

Installation

pip install flask_zipkin

usage

you can simply use it as other flask extensions.

from flask_zipkin import Zipkin

zipkin = Zipkin(app, sample_rate=10)
app.config['ZIPKIN_DSN'] = "http://127.0.0.1:9411/api/v1/spans"

Advance Usage

you could gen a header to pass it to other services, the downstream service will recieve this header.

@bp.route('/')
def hello():
    headers = {}
    headers.update(zipkin.create_http_headers_for_new_span())
    r = requests.get('http://localhost:5001', headers=headers)
    return r.text

flask_zipkin will use http transport by default. You could define a transport, like:

@zipkin.transport_handler
def default_handler(encoded_span):
    return requests.post(
		'your transport dsn',
        data=encoded_span,
        headers={'Content-Type': 'application/x-thrift'},
)

flask_zipkin eats all transport exception by default. You could define an exception handler, like:

@zipkin.transport_exception_handler
def default_ex_handler(ex):
    raise ex

and also, you could exempt some views, like:

@zipkin.exempt
@bp.route('/')
def hello():
    return 'hello world'

add key, value for your tracing record, like:

zipkin.update_tags(id=1, user_id=2)

app configs

ZIPKIN_DISABLE disable zipkin tracking if value is True

ZIPKIN_DSN http transport dsn: such as http://localhost:9411/api/v1/spans

Comments
  • zipkin post span with http code 400

    zipkin post span with http code 400

    zipkin-server log: Cannot decode spans due to IllegalArgumentException(Error reading List from TBinary)

    when i modify like this ,it works. 39 40 def default_handler(self, encoded_span): 41 try: 42 #body = str.encode('\x0c\x00\x00\x00\x01') + encoded_span 43 body = encoded_span

    opened by chestarss 5
  • Add child span decorator

    Add child span decorator

    This decorator aims to make easier people creating child span. Normally we have to create a span resource everytime we want to create a child span. For example:

    def some_method():
        with zipkin_span(service_name='example', span_name='some_method') as z:
            result = do_something()
            z.update_binary_annotations({'result': result})
    

    Using this decorator we can do this instead:

    @flask_zipkin.child_span
    def some_method(*args, **kwargs):
        result = do_something()
        kwargs['span'].update_binary_annotations({'result': result})  
    

    The decorated method will use flask application name as service_name and the decorated method name as span_name.

    opened by asasmoyo 3
  • repeat problem Cannot decode spans

    repeat problem Cannot decode spans

    when i modify like this ,it works. 39 40 def default_handler(self, encoded_span): 41 try: 42 #body = str.encode('\x0c\x00\x00\x00\x01') + encoded_span 43 body = encoded_span

    repeat problem #17

    opened by leolinf 2
  • encoded_span missing.

    encoded_span missing.

    Hi. I follow the instruction here but I have an error. TypeError: default_handler() missing 1 required positional argument: 'encoded_span'

    I think this is because I may lose the span for the entry service. But I actually added it. My code is as below: image

    @zipkin.transport_handler def default_handler(self, encoded_span): body = str.encode('\x0c\x00\x00\x00\x01') + encoded_span return requests.post( 'http://144.173.55.61:9411/api/v1/spans', data=body, headers={'Content-Type': 'application/x-thrift'},)

    #index #@zipkin_span(service_name='my_service', span_name='index',transport_handler=default_handler, sample_rate=100) @app.route('/') def index(): with zipkin_span( service_name='webapp', span_name='index', transport_handler=default_handler, port=9411, sample_rate=100, #0.05, # Value between 0.0 and 100.0 ): return render_template('home.html')

    Could you please help me with it?

    question 
    opened by yzexeter 2
  • 400 Bad request from handler transport

    400 Bad request from handler transport

    Here is my code server: https://onlinegdb.com/r1gZ6lnFH

    After curl localhost:8080 the console show: call zipkin transport_handler code = 400, text = Expected value at line 1 column 1 path $ reading List from json , reason = Bad Request

    How can i Fixed it. Thanks you

    opened by ndh96coder 1
  • B3 propagation header capitalization

    B3 propagation header capitalization

    even though http headers are supposed to be case-insensitive, this "Parentspanid" header as capitalized previously was failing to be picked up by downstream instrumentations. if nothing else, good for consistency

    opened by natlownes 1
  • guard against _zipkin_span not set in g

    guard against _zipkin_span not set in g

    It is possible that zipkin.logging is called before request actually has been made -- in unit tests, for example (with app.test_request_context() does not run before/after request hooks).

    opened by santtu 1
  • ZipkinError error: argument out of range

    ZipkinError error: argument out of range

    Seeing errors like

      def _after_request(self, response):
            if self._disable:
                return response
            if not hasattr(g, '_zipkin_span'):
                return response
            g._zipkin_span.stop()
            return response
        def create_http_headers_for_new_span(self):
            if self._disable:
                return dict()
    

        'b6dbb1c2b362bf51' => -5270423489115668655
    :param hex_string: the string representation of a zipkin ID
    :returns: signed int representation
    """
    return struct.unpack('q', struct.pack('Q', int(hex_string, 16)))[0]
    

    def signed_int_to_unsigned_hex(signed_int): """Converts a signed int value to a 64-bit hex string.

    opened by posix4e 0
  • docs: fix simple typo, recieve -> receive

    docs: fix simple typo, recieve -> receive

    There is a small typo in README.md.

    Should read receive rather than recieve.

    Semi-automated pull request generated by https://github.com/timgates42/meticulous/blob/master/docs/NOTE.md

    opened by timgates42 0
  • Function

    Function "_safe_header" reuse the "_headers" attribute which caused the 1st inbound trace ID to be reused forever

    In function "_safe_header", it has the following logic:

    def _safe_headers(self, headers):
        if hasattr(self, "_headers"):
            return self._headers
        self._headers = dict((k.lower(), v) for k, v in headers.__iter__())
        return self._headers
    

    If the 1st request contains "X-B3*" headers, it will assign to self._headers. Then for every inbound request after that, it reuse the _headers based on the 1st request instead of parsing from the new header. This will cause all the newly created spans are chained with the 1st trace id. Therefore for any python app which is in the middle of any process, the zipkin tracing could be incorrect.

    I am not sure if this is an actual bug, or I implemented in a wrong way which caused this issue. Please have a review, I would love to hear your reply on this.

    opened by RunzhongHuang 0
  • Function

    Function "update_tags" not working

    Hi,

    In the README.md file, there is one part of tutorial is updating the tags to the span (zipkin.update_tags(id=1, user_id=2)). I tried this in two different approach and both returns me errors.

    1, AttributeError: 'ZipkinLoggingContext' object has no attribute 'binary_annotations_dict'

    I encountered this error while I put the "update_tags" inside the route function as below (function name "index").

    from flask import Flask
    from flask_zipkin import Zipkin
    import requests
    
    app = Flask(__name__)
    app.config['ZIPKIN_DISABLE'] = False
    app.config['ZIPKIN_DSN'] = "<url>"
    zipkin = Zipkin(app)
    
    @app.route('/')
    def index():
        headers = {}
        headers.update(zipkin.create_http_headers_for_new_span())
        zipkin.update_tags(id=1, user_id=2)
        r = requests.get('<url>', headers=headers)
        return r.text, 200
    
    # Start the app server
    if __name__ == '__main__':
        app.run(debug=True, host='127.0.0.1', threaded=True)
    
    -----------------------------------------------
    
    Traceback (most recent call last):
      File "C:\<path>\venv\lib\site-packages\flask\app.py", line 2091, in __call__
        return self.wsgi_app(environ, start_response)
      File "C:\<path>\venv\lib\site-packages\flask\app.py", line 2076, in wsgi_app
        response = self.handle_exception(e)
      File "C:\<path>\venv\lib\site-packages\flask\app.py", line 2073, in wsgi_app
        response = self.full_dispatch_request()
      File "C:\<path>\venv\lib\site-packages\flask\app.py", line 1518, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File "C:\<path>\venv\lib\site-packages\flask\app.py", line 1516, in full_dispatch_request
        rv = self.dispatch_request()
      File "C:\<path>\venv\lib\site-packages\flask\app.py", line 1502, in dispatch_request
        return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
      File "C:\<path>\flask-zipkin-test.py", line 26, in index
        zipkin.update_tags(id=1, user_id=2)
      File "C:\<path>\venv\lib\site-packages\flask_zipkin.py", line 152, in update_tags
        g._zipkin_span.logging_context.binary_annotations_dict.update(
    AttributeError: 'ZipkinLoggingContext' object has no attribute 'binary_annotations_dict'
    
    

    2, RuntimeError: Working outside of application context.

    This error is triggered if I put the "update_tag" function right after initialize Zipkin object.

    from flask import Flask
    from flask_zipkin import Zipkin
    import requests
    
    app = Flask(__name__)
    app.config['ZIPKIN_DISABLE'] = False
    app.config['ZIPKIN_DSN'] = "<URL>"
    zipkin = Zipkin(app)
    zipkin.update_tags(id=1, user_id=2)
    
    @app.route('/')
    def index():
        headers = {}
        headers.update(zipkin.create_http_headers_for_new_span())
        r = requests.get('<URL>', headers=headers)
        return r.text, 200
    
    # Start the app server
    if __name__ == '__main__':
        app.run(debug=True, host='127.0.0.1', threaded=True)
    
    ---------------------------------------------------
    
    Traceback (most recent call last):
      File "C:/<path>/flask-zipkin-test.py", line 10, in <module>
        zipkin.update_tags(id=1, user_id=2)
      File "C:\<path>\venv\lib\site-packages\flask_zipkin.py", line 149, in update_tags
        if all([hasattr(g, '_zipkin_span'),
      File "C:\<path>\venv\lib\site-packages\werkzeug\local.py", line 422, in __get__
        obj = instance._get_current_object()
      File "C:\<path>\venv\lib\site-packages\werkzeug\local.py", line 544, in _get_current_object
        return self.__local()  # type: ignore
      File "C:\<path>\venv\lib\site-packages\flask\globals.py", line 40, in _lookup_app_object
        raise RuntimeError(_app_ctx_err_msg)
    RuntimeError: Working outside of application context.
    

    I am not sure if I use the method in a wrong way, if yes, please let me know which part I did it wrong.

    opened by RunzhongHuang 0
  • fix span data is old

    fix span data is old

    I have two applications, one named a and the other named B. their request order is that the client requests application a, and application a requests application B again. The data sent by application B for the first time is OK, but the data sent later is old data

    opened by jiangyd 0
  • is_sampled is always False

    is_sampled is always False

    The is_sampled logic there will make it always be False. If the view function is the first span in a trace, X-B3-Sampled is not definded in headers so it is set as Fasle. And then all spans in the call chain will be False.

    I use it in two defferent flask applications and no one send trace info to server. When I changed this line to is_sampled = str(headers.get('X-B3-Sampled') or '1') == '1', it worked.

    opened by AlllenShen 0
Releases(v0.0.5)
  • v0.0.5(Dec 12, 2020)

    Mainly changes refer to https://github.com/qiajigou/flask-zipkin/pull/23 https://github.com/qiajigou/flask-zipkin/pull/27

    Contributors: @posix4e @abitrolly

    Source code(tar.gz)
    Source code(zip)
  • v0.0.3(Jul 24, 2017)

Owner
- what does qiajigou mean? - don't ask.
Analytics snippets generator extension for the Flask framework.

Flask-Analytics Flask Analytics is an extension for Flask which generates analytics snippets for inclusion in templates. Installation $ pip install Fl

Mihir 80 Nov 30, 2022
SQLAlchemy database migrations for Flask applications using Alembic

Flask-Migrate Flask-Migrate is an extension that handles SQLAlchemy database migrations for Flask applications using Alembic. The database operations

Miguel Grinberg 2.2k Dec 28, 2022
Formatting of dates and times in Flask templates using moment.js.

Flask-Moment This extension enhances Jinja2 templates with formatting of dates and times using moment.js. Quick Start Step 1: Initialize the extension

Miguel Grinberg 358 Nov 28, 2022
A simple Task todo application built with Flask

Task TODO Table An application built with Flask a Python framework and hosted on Heroku. Important notes GuniCorn (Green Unicorn): is a Python WSGI HT

DCN (Dubem Celestine Nwabuisi) 1 Dec 15, 2021
A template themes for phyton flask website

Flask Phyton Web template A template themes for phyton flask website

Mesin Kasir 2 Nov 29, 2021
A Flask app template with integrated SQLAlchemy, authentication, and Bootstrap frontend

Flask-Bootstrap Flask-Bootstrap is an Flask app template for users to clone and customize as desired, as opposed to a Flask extension that you can ins

Eric S. Bullington 204 Dec 26, 2022
Socket.IO integration for Flask applications.

Flask-SocketIO Socket.IO integration for Flask applications. Installation You can install this package as usual with pip: pip install flask-socketio

Miguel Grinberg 4.9k Jan 02, 2023
flask-reactize is a boostrap to serve any React JS application via a Python back-end, using Flask as web framework.

flask-reactize Purpose Developing a ReactJS application requires to use nodejs as back end server. What if you want to consume external APIs: how are

Julien Chomarat 4 Jan 11, 2022
Glauth management ui created with python/flask

glauth-ui Glauth-UI is a small flask web app i created to manage the minimal glauth ldap server. I created this as i wanted to use glauth for authenti

Nils Thiele 67 Nov 29, 2022
WebSocket support for Flask

flask-sock WebSocket support for Flask Installation pip install flask-sock Example from flask import Flask, render_template from flask_sock import Soc

Miguel Grinberg 165 Dec 27, 2022
Flask app for deploying DigitalOcean droplet using Pulumi.

Droplet Deployer Simple Flask app which deploys a droplet onto Digital ocean. Behind the scenes there's Pulumi being used. Background I have been Terr

Ahmed Sajid 1 Oct 30, 2021
Flask-app scaffold, generate flask restful backend

Flask-app scaffold, generate flask restful backend

jacksmile 1 Nov 24, 2021
Flask webassets integration.

Integrates the webassets library with Flask, adding support for merging, minifying and compiling CSS and Javascript files. Documentation: https://flas

Michael Elsdörfer 433 Dec 29, 2022
This is a API/Website to see the attendance recorded in your college website along with how many days you can take days off OR to attend class!!

Bunker-Website This is a GUI version of the Bunker-API along with some visualization charts to see your attendance progress. Website Link Check out th

Mathana Mathav 11 Dec 27, 2022
Flask Apps - Open-Source And Paid | AppSeed

Flask Apps Open-Source web apps built with automation tools, HTML parsing and boilerplated code in Flask - - Provided by AppSeed App Generator. What i

App Generator 120 Oct 04, 2022
Burp-UI is a web-ui for burp backup written in python with Flask and jQuery/Bootstrap

Burp-UI Contents Introduction Screenshots Demo What's that? Who are you? Documentation FAQ Community Notes See also Licenses Thanks Introduction Scree

Benjamin 84 Dec 20, 2022
A simple example using Flask inside a container

This is a simple example of how create a container for a Python Flask Web Application using Docker.

Fazt Web 8 Aug 30, 2022
Flask 文档中文翻译

Flask 中文文档 这里是 Flask 文档中文翻译项目,欢迎参与! 在开始翻译之前,请务必阅读下面的 Contributing Guide 了解贡献流程,然后阅读这个 Issue 了解翻译要求,在这个 Discussion 投票选出你认为合适的翻译词汇,在这个 Discussion 投票选出你喜

Grey Li 93 Nov 28, 2022
Mixer -- Is a fixtures replacement. Supported Django, Flask, SqlAlchemy and custom python objects.

The Mixer is a helper to generate instances of Django or SQLAlchemy models. It's useful for testing and fixture replacement. Fast and convenient test-

Kirill Klenov 870 Jan 08, 2023
A basic JSON-RPC implementation for your Flask-powered sites

Flask JSON-RPC A basic JSON-RPC implementation for your Flask-powered sites. Some reasons you might want to use: Simple, powerful, flexible and python

Cenobit Technologies 272 Jan 04, 2023