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.
Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application.

Flask-Bcrypt Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application. Due to the recent increased prevelance of

Max Countryman 310 Dec 14, 2022
Sample Dockerized flask app deployed on Kubernetes on Azure using AKS

Sample Dockerized flask app deployed on Kubernetes on Azure using AKS

Ahmed khémiri 22 Sep 08, 2021
Set up a modern flask web server by running one command.

Build Flask App · Set up a modern flask web server by running one command. Installing / Getting started pip install build-flask-app Usage build-flask-

Kushagra Bainsla 5 Jul 16, 2022
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
A Python chat app built with Flask that runs in the browser.

A Python chat app built with Flask that runs in the browser. Designed for local area networks that are not connected to the Internet.

Leonard Kleber 1 Dec 23, 2021
Brandnew-flask is a CLI tool used to generate a powerful and mordern flask-app that supports the production environment.

Brandnew-flask is still in the initial stage and needs to be updated and improved continuously. Everyone is welcome to maintain and improve this CLI.

brandonye 4 Jul 17, 2022
Seamlessly serve your static assets of your Flask app from Amazon S3

flask-s3 Seamlessly serve the static assets of your Flask app from Amazon S3. Maintainers Flask-S3 is maintained by @e-dard, @eriktaubeneck and @SunDw

Edd Robinson 188 Aug 24, 2022
A YouTube webscraper made with flask.

YouTube Webscraper This website is for you to check all the stats on your favorite Youtube video! Technologies Python Flask HTML CSS Pafy Contributing

Proconsulates 3 Nov 25, 2021
Forum written for learning purposes in flask and sqlalchemy

Flask-forum forum written for learning purposes using SQLalchemy and flask How to install install requirements pip install sqlalchemy flask clone repo

Kamil 0 May 23, 2022
A Flask web application that manages student entries in a SQL database

Student Database App This is a Flask web application that manages student entries in a SQL database. Users can upload a CSV into the SQL database, mak

rebecca 1 Oct 20, 2021
The Coodesh Python Backend Challenge (2021) written in Flask

Coodesh Back-end Challenge 🏅 2021 ID: 917 The Python Back-end Coodesh Challenge Description This API automatically retrieves users from the RandomUse

Marcus Vinicius Pereira 1 Oct 20, 2021
A web application that consists of a collection of board games

PyBoardGame About This website contains a collection of board games for users to enjoy, as well as various guides for the games. The web app is built

Larry Shi 0 Aug 11, 2021
Pf-flask-rest-com - Flask REST API Common Implementation by Problem Fighter Library

In the name of God, the Most Gracious, the Most Merciful. PF-Flask-Rest-Com Docu

Problem Fighter 3 Jan 15, 2022
A swagger 2.0 spec extractor for flask

flask-swagger A Swagger 2.0 spec extractor for Flask You can now specify base path for yml files: app = Flask(__name__) @app.route("/spec") def spec(

Sling 457 Dec 02, 2022
Regex Converter for Flask URL Routes

Flask-Reggie Enable Regex Routes within Flask Installation pip install flask-reggie Configuration To enable regex routes within your application from

Rhys Elsmore 48 Mar 07, 2022
A simple way to demo Flask apps from your machine.

flask-ngrok A simple way to demo Flask apps from your machine. Makes your Flask apps running on localhost available over the internet via the excellen

117 Dec 27, 2022
An extension to add support of Plugin in Flask.

An extension to add support of Plugin in Flask.

Doge Gui 31 May 19, 2022
A nice anonymous messaging api (Uses Flask's restful api)

anonymous-message-api A nice anonymous message api (Uses Flask's restful api) How it works: 1. The user send a put request to your api server: Require

6 Nov 07, 2021
Geometry Dash Song Bypass with Python Flask Server

Geometry Dash Song Bypass with Python Flask Server

pixelsuft‮ 1 Nov 16, 2021