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.
This is a Flask web app which predicts fare of Flight ticket

Flight Fare Prediction: Table of Content Demo Overview Motivation Installation Deployement on Heroku Directory Tree Bug / Feature Request Future scope

Ayshwarya 1 Jan 24, 2022
Alexa Skills Kit for Python

Program the Amazon Echo with Python Flask-Ask is a Flask extension that makes building Alexa skills for the Amazon Echo easier and much more fun. Flas

John Wheeler 1.9k Dec 30, 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
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
Flask-Diamond is a batteries-included Flask framework.

Flask-Diamond Flask-Diamond is a batteries-included Python Flask framework, sortof like Django but radically decomposable. Flask-Diamond offers some o

Diamond Methods 173 Dec 22, 2022
Making a simple app using React, Flask and MySQL.

Samys-Cookbook Making a simple app using React and Flask. What This will be a simple site to host my recipes. It will have a react front-end, a flask

Samridh Anand Paatni 1 Jul 07, 2022
SeCl - A really easy to deploy and use made-on Flask API to manage your files remotely from Terminal

SeCl SeCl it's a really easy to deploy and use made-on Flask API to manage your

ZSendokame 3 Jan 15, 2022
Curso Desenvolvimento avançado Python com Flask e REST API

Curso Desenvolvimento avançado Python com Flask e REST API Curso da Digital Innovation One Professor: Rafael Galleani Conteudo do curso Introdução ao

Elizeu Barbosa Abreu 1 Nov 14, 2021
Serve angular production application from python flask backend. Quick and Easy

Serve angular production application from python flask backend. Quick and Easy

mark 1 Dec 01, 2022
SqlAlchemy Flask-Restful Swagger Json:API OpenAPI

SAFRS: Python OpenAPI & JSON:API Framework Overview Installation JSON:API Interface Resource Objects Relationships Methods Custom Methods Class Method

Thomas Pollet 365 Jan 06, 2023
A Flask wrapper of Starknet state. Similar in purpose to Ganache.

Introduction A Flask wrapper of Starknet state. Similar in purpose to Ganache. Aims to mimic Starknet's Alpha testnet, but with simplified functionali

Shard Labs 159 Jan 04, 2023
This repo contains the Flask API to expose model and get predictions.

Tea Leaf Quality Srilanka Chapter This repo contains the Flask API to expose model and get predictions. Expose Model As An API Model Trainig will happ

DuKe786 2 Nov 12, 2021
Learn python and flask,just a tony blog system

flaskblog Learn python and flask,just a tony blog system based on flask and mysql It is similar to cleanblog, a blog system based on flask and mongoen

shin 174 Dec 01, 2022
An python flask app with webserver example

python-flask-example-keepalive How it works? Basically its just a python flask webserver which can be used to keep any repl/herokuapp or any other ser

KangersHub 2 Sep 28, 2022
RestApi_flask_sql.alchemy - Product REST API With Flask & SQL Alchemy

REST API With Flask & SQL Alchemy Products API using Python Flask, SQL Alchemy and Marshmallow Quick Start Using Pipenv # Activate venv $ pipenv shell

amirwahla 1 Jan 01, 2022
Getting Started with Docker and Flask

Getting-Started-with-Docker-and-Flask Introduction Docker makes it easier, simpler and safer to build, deploy and manage applications in a docker cont

Phylis Jepchumba 1 Oct 08, 2021
Flask-template - A simple template for make an flask api

flask-template By GaGoU :3 a simple template for make an flask api notes: you ca

GaGoU 2 Feb 17, 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
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