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)
<font color='green'>[new]</font> 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.