PK!f^^formation/__init__.pyfrom .__version__ import __version__ # noqa from .formation import wrap __all__ = ["wrap"] PK! formation/__version__.py__version__ = "0.1.14"PK!Aformation/for_requests.pyimport requests from .formation import wrap from attr import attrib, attrs, fields, asdict __all__ = ["build_sender"] @attrs class FormationHttpRequest(object): url = attrib() method = attrib(default="get") headers = attrib(default={}) params = attrib(default={}) auth = attrib(default=None) data = attrib(default=None) def build_sender(middleware=[]): wrapped = wrap(requests_adapter, middleware=middleware) def sender(method, url, **kwargs): ctx = {"fmtn.req": FormationHttpRequest(url=url, method=method, **kwargs)} ctx = wrapped(ctx) return ctx["fmtn.res"] return sender def requests_adapter(ctx): req = ctx["fmtn.req"] meth = getattr(requests, req.method.lower()) # TODO ship var as kwargs and not explicitly res = meth( req.url, headers=req.headers, params=req.params, auth=req.auth, data=req.data ) ctx["fmtn.res"] = res return ctx PK!?nKformation/formation.pyfrom toolz import reduce def wrap(call, middleware=[]): return reduce( lambda acc, m: lambda ctx: m(ctx, acc), reversed(middleware), lambda ctx: call(ctx), ) PK!7r r formation/middleware.pyimport threading import datetime from uuid import uuid4 from toolz.curried import valfilter import os def create_request_id(key="x-request-id", idgen=uuid4): def requests_id(ctx, next): headers = ctx["fmtn.req"].headers headers[key] = headers.get(key, str(idgen())) ctx["req.id"] = headers[key] ctx = next(ctx) return ctx return requests_id def create_request_duration(now=datetime.datetime.now): def request_duration(ctx, next): start = now() ctx = next(ctx) end = now() - start ctx["req.duration_us"] = end.microseconds return ctx return request_duration def logger_context( request_id=None, request_parent_id=None, namespace="service", env="local", sha="dev", version="0.0.1", scope="service", uid=None, ): pid = os.getpid() tid = threading.get_ident() return { "v": version, "sha": sha, "env": env, "pid": pid, "tid": tid, "uid": uid, "scope": scope, "ns": namespace, "rid": request_id, "rid_p": request_parent_id, } def create_request_logger( logger, context_fn=logger_context, namespace="service", scope="all", env="local", sha="dev", version="0.01", ): no_nones = valfilter(lambda x: x) def request_logger(ctx, next): req = ctx["fmtn.req"] request_id = ctx["req.id"] uid = ctx.get("user.id", None) request_parent_id = ctx.get("req.parent.id", None) msg = "request.http" log = logger.bind( **context_fn( env=env, sha=sha, version=version, request_id=request_id, request_parent_id=request_parent_id, scope=scope, uid=uid, ) ) log.info(msg, url=req.url, method=req.method, params=no_nones(req.params)) log.debug(msg, headers=req.headers) ctx = next(ctx) res = ctx["fmtn.res"] msg = "response.http" log.info( msg, url=res.request.url, status=res.status_code, method=res.request.method, elapsed=res.elapsed, size=len(res.content), duration_us=ctx.get("req.duration_us", None), ) log.debug(msg, headers=res.headers) return ctx return request_logger def retry(max_retries=3): def retry_middleware(ctx, call): try: res = call(ctx) return res except Exception as ex: retries = ctx.get("fmtn.retry", 0) if retries > max_retries: raise ex ctx["fmtn.retry"] = 1 + retries # TODO exponential backoff res = retry_middleware(ctx, call) return res return retry_middleware PK!H9VWX formation-0.1.14.dist-info/WHEEL A н#f."jm)!fb҅~ܴA,mTD}E n0H饹*|D[¬c i=0(q3PK!Hqj #formation-0.1.14.dist-info/METADATAVnF}WL I뤈Qum} kҒZ{-Ĩ`93sf ))GtEeVa}y%GϢ릪]rlUJYӀ%UJʒ2)YmRr 蝩xP k7sf~0Z?Q8W)kq Jp tn?6w/4]\ U*<")8)FԵ5w,=Xm^briMnEU)9H6H8*xP|=[W-*{@r t@wQb>rE?9mS>EOnJ:X q륱 nB=^_MP:9n[_K; <:$EgY%5.Ls!Y ٧ F60HԆ]HIjh;PIrjT ]&+:< ) ן]806Jx*”3 <L%5u4kT)CKXq--ڸqw^{(sfJ*;*O w=ȶ=Ȍ  = UǑwv??q]ag_VB@W:H(B^Y+K.P<q%tLӷooE◾(YcQ}_PK!Hxa!formation-0.1.14.dist-info/RECORD}r@} N!5dC! vAiӏUS3C6N9t=-ҵyNZ22sX2n~peQ:EK9HsG&N k{oo[;mWة) Vp[GՏ (.G}}^ R6{8б7V9H]$ TK؏ywO-4 ]c'䛼)$Xa7b>8A]ΣTb6(x.qxJQUecu rYJX Ҫ"lI{螱޺@tѤxs.\ͭPf{!C)O4Sd`wEş@qR<\.Ɖf@L{ PK!f^^formation/__init__.pyPK! formation/__version__.pyPK!Aformation/for_requests.pyPK!?nKformation/formation.pyPK!7r r formation/middleware.pyPK!H9VWX _formation-0.1.14.dist-info/WHEELPK!Hqj #formation-0.1.14.dist-info/METADATAPK!Hxa!-formation-0.1.14.dist-info/RECORDPKG