Skip to main content

A wrapper around the Tornado web framework that supports logs with traceId.

Project description

================================================
    _____            _ 
   |_   _|   _ _ __ | |__  based on Tornado
     | || | | | '_ \| '_ \ / _ \ / _ \| '_ \ 
     | || |_| | |_) | | | | (_) | (_) | | | |
     |_| \__, | .__/|_| |_|\___/ \___/|_| |_|
         |___/|_|
================================================

Typhoon is a wrapper around the Tornado web framework. It offers the ability to attach log records with a trace id, which is used to trace individual HTTP requests. By default Typhoon obtains trace id from the request's header X-TRACEID. To change this behavior, subclass typhoon.web.Application and overwrite the get_trace_id method.

Requirements

  • tornado >= 5.1

Installation

  • Use pip:
    pip install typhoon-web
    pip install typhoon-web --upgrade
    
  • Clone repository and install with:
    python setup.py install
    

Hello, world

Here is a simple “Hello, world” example web app for Typhoon:

import logging
import time

import tornado.ioloop
import typhoon.web
import typhoon.log

class MainHandler(typhoon.web.RequestHandler):
    @typhoon.web.run_in_executor
    def process(self):
        logging.info('go to sleep')
        time.sleep(3)
        logging.info('wake up')
        return 'Hello, world'

    async def get(self):
        result = await self.process()
        self.write(result)
    
    # Native coroutine (using async def and await) was introduced in Python 3.5.
    # For previous version, use generator-based coroutine. 
    # For example:
    #
    # @tornado.gen.coroutine
    # def get(self):
    #     result = yield self.process()
    #     self.write(result)

def make_app():
    return typhoon.web.Application([
        (r'/', MainHandler),
    ])

if __name__ == '__main__':
    typhoon.log.configure(log_path='/home/logs')
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()

In this example, three different log files will be generated in the log_path:

  • access.log records summaries of each http request.
  • stats.log records messages for statistics and analysis.
  • app.log contains all logs that are neither access logs nor stats logs.

To log to stats.log, use an instance of typhoon.log.StatsLogger:

import typhoon.log

stats_log = typhoon.log.StatsLogger()

stats_log.info({'user_count': 100})
stats_log.info({'job_register': 20}, topic='register')

Notice that logging methods of StatsLogger only accept a dict object as message.

Trace id

By default trace id is automatically obtained and handled by Typhoon only when the client sends a request with a header X-TRACEID: some-value:

$ curl -H "X-TRACEID: ceon1haa6cau1dung1" http://127.0.0.1:8888

To customize the way trace id is passed, subclass typhoon.web.Application and overwrite the get_trace_id method.

import typhoon.web

class MyApplication(typhoon.web.Application):
    def get_trace_id(self, handler):
        # obtain trace id from URL Parameter.
        return handler.get_argument('traceId', '-')

In the above example, trace id is passed through an URL parameter:

$ curl http://127.0.0.1:8888?traceId=ceon1haa6cau1dung1

You may have to call another service and pass down the trace id. In this case, use typhoon.log.TRACE_ID() to obtain current trace id:

import requests
import typhoon.web
import typhoon.log

class MainHandler(typhoon.web.RequestHandler):
    @typhoon.web.run_in_executor
    def process(self):
        # call another service and pass down current trace id.
        r = request.get('http://127.0.0.1:9990/hello', header={'X-TRACEID': typhoon.log.TRACE_ID()})
        if r.status_code == 200:
            return 'Hello, world'
        else:
            return 'oops!'

    async def get(self):
        result = await self.process()
        self.write(result)

[new] High-Level API

For those who are not familiar with Tornado, Typhoon provides high-level api since v1.0.2.

Neither RequestHandler, nor Application. Just subclass typhoon.rest.RestControler, and decorated method with typhoon.rest.route decorator.

Here is a “Hello, world” example.

from typhoon.rest import RestController, RestResult, route, start_server
from typhoon.status import OK

class Controller(RestController):
    @route(uri=r'/hello', method='get')
    def greet(self, user=None):
        if user is not None:
            content = f'Hello, {user}'
        else:
            content = 'Hello, world'
        return RestResult(status=OK, content=content)

if __name__ == '__main__':
    start_server(
        controller = Controller(),
        port=8888
    )

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

typhoon-web-2.0.0.tar.gz (13.7 kB view details)

Uploaded Source

File details

Details for the file typhoon-web-2.0.0.tar.gz.

File metadata

  • Download URL: typhoon-web-2.0.0.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0.post20200210 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.7.6

File hashes

Hashes for typhoon-web-2.0.0.tar.gz
Algorithm Hash digest
SHA256 16d1c3bee9af56ae402c6a7925464ae7aa86f3e3d39a7cae0eb2cdc851319a38
MD5 94081a123198af676f9f5bc9372dd331
BLAKE2b-256 d6afbfce3b45e031194485cd7044d5b08dd6ec35ffe8ae3ff92ba8f7fc1df88b

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page