refactor: split code blocks into functions

mainly for two reasons:
 * easier to profile and find out hot code path
 * easier to change some of the implementation later, for example, a faster
   list sum implementation for gauge metrics.
update gitignore
add tox.ini
chore: fix pep errors