Python函数调用追踪实现代码
对于分布式追踪,主要有以下的几个概念:
- 追踪Trace:就是由分布的微服务协作所支撑的一个事务。一个追踪,包含为该事务提供服务的各个服务请求。
- 跨度Span:Span是事务中的一个工作流,一个Span包含了时间戳,日志和标签信息。Span之间包含父子关系,或者主从(Followup)关系。
- 跨度上下文SpanContext:跨度上下文是支撑分布式追踪的关键,它可以在调用的服务之间传递,上下文的内容包括诸如:从一个服务传递到另一个服务的时间,追踪的ID,Span的ID还有其它需要从上游服务传递到下游服务的信息。
我实现了一种简单的调用追踪。
importuuid importos importtime l=[] classRecorder(object): def__init__(self,servername,root_span=None): ifroot_span==None: self.__span=Span(servername) else: self.__span=Span(servername,root_span) #上下文管理器 def__enter__(self): returnself.__span #退出方法中,用来实现善后处理工作 def__exit__(self,exc_type,exc_val,exc_tb): self.__span.record() self.__span.record_save(self.__span.span) classSpan(object): def__init__(self,servername,root_span=None): self.servername=servername self.span=self.newspan() ifroot_span!=None: root_span.dic['child_span']=self.span self.span["root_span_flag"]=False defnewspan(self): self.dic={ "spanid":uuid.uuid4().int, "servername":self.servername, "location":"", "ip":"", "durationtime":0, "starttime":time.time(), "endtime":0, "tag":"", "log":"", "root_span_flag":True, "child_span":"" } returnself.dic defrecord_save(self,span): currenttracer={"id":span["spanid"],"data":span} print(currenttracer) l.append(currenttracer) defrecord(self): self.span["servername"]=self.servername self.span["location"]=os.getcwd()+"."+self.servername self.span["endtime"]=time.time() self.span["durationtime"]=self.span["endtime"]-self.span["starttime"] defsetspantag(self,tag): self.span["tag"]=tag defsetspanlog(self,log): self.span["log"]=log #连续调用 withRecorder('server1')asspan: time.sleep(1) span.setspantag("test") #调用server1方法 print("server1") withRecorder('server2',span)asspan1: time.sleep(2) #调用server2方法 print("server2") withRecorder('server3',span1)asspan2: time.sleep(0.5) #调用server3方法 print("server3") #单独调用记录 withRecorder('server4')asspan_test1: time.sleep(1.5) print("server4") withRecorder('server5')asspan_test2: time.sleep(2) print("server5")
运行结果:
server1 server2 server3 {'id':224716339449765695394515303164364012192,'data':{'spanid':224716339449765695394515303164364012192,'servername':'server3','location':'D:\\python_protest\\protest\\trace\\trace_main.server3','ip':'','durationtime':0.5004403591156006,'starttime':1598947338.0551107,'endtime':1598947338.555551,'tag':'','log':'','root_span_flag':False,'child_span':None}} {'id':254736847532758359233387151739984206570,'data':{'spanid':254736847532758359233387151739984206570,'servername':'server2','location':'D:\\python_protest\\protest\\trace\\trace_main.server2','ip':'','durationtime':2.501264810562134,'starttime':1598947336.0542862,'endtime':1598947338.555551,'tag':'','log':'','root_span_flag':False,'child_span':{'spanid':224716339449765695394515303164364012192,'servername':'server3','location':'D:\\python_protest\\protest\\trace\\trace_main.server3','ip':'','durationtime':0.5004403591156006,'starttime':1598947338.0551107,'endtime':1598947338.555551,'tag':'','log':'','root_span_flag':False,'child_span':None}}} {'id':91028031631192607088457781914309166266,'data':{'spanid':91028031631192607088457781914309166266,'servername':'server1','location':'D:\\python_protest\\protest\\trace\\trace_main.server1','ip':'','durationtime':3.5021069049835205,'starttime':1598947335.0534441,'endtime':1598947338.555551,'tag':'test','log':'','root_span_flag':True,'child_span':{'spanid':254736847532758359233387151739984206570,'servername':'server2','location':'D:\\python_protest\\protest\\trace\\trace_main.server2','ip':'','durationtime':2.501264810562134,'starttime':1598947336.0542862,'endtime':1598947338.555551,'tag':'','log':'','root_span_flag':False,'child_span':{'spanid':224716339449765695394515303164364012192,'servername':'server3','location':'D:\\python_protest\\protest\\trace\\trace_main.server3','ip':'','durationtime':0.5004403591156006,'starttime':1598947338.0551107,'endtime':1598947338.555551,'tag':'','log':'','root_span_flag':False,'child_span':None}}}} server4 {'id':103171729522922437998918618387133480096,'data':{'spanid':103171729522922437998918618387133480096,'servername':'server4','location':'D:\\python_protest\\protest\\trace\\trace_main.server4','ip':'','durationtime':1.5001769065856934,'starttime':1598947338.555551,'endtime':1598947340.055728,'tag':'','log':'','root_span_flag':True,'child_span':None}} server5 {'id':320091321623887285825256878422834254741,'data':{'spanid':320091321623887285825256878422834254741,'servername':'server5','location':'D:\\python_protest\\protest\\trace\\trace_main.server5','ip':'','durationtime':2.0005736351013184,'starttime':1598947340.055728,'endtime':1598947342.0563016,'tag':'','log':'','root_span_flag':True,'child_span':None}}
关于下一步,会使用redis存储其结果,并进行相应的输出分析。
修过不能追踪同级调用的问题
importuuid importos importtime l=[] classRecorder(object): def__init__(self,servername,root_span=None): ifroot_span==None: self.__span=Span(servername) else: self.__span=Span(servername,root_span) #上下文管理器 def__enter__(self): returnself.__span #退出方法中,用来实现善后处理工作 def__exit__(self,exc_type,exc_val,exc_tb): self.__span.record() self.__span.record_save(self.__span.span) classSpan(object): def__init__(self,servername,root_span=None): self.servername=servername self.span=self.newspan() ifroot_span!=None: root_span.dic['child_span'].append(self.span) self.span["root_span_flag"]=False defnewspan(self): self.dic={ "spanid":uuid.uuid4().int, "servername":self.servername, "location":"", "ip":"", "durationtime":0, "starttime":time.time(), "endtime":0, "tag":"", "log":"", "root_span_flag":True, "child_span":[] } returnself.dic defrecord_save(self,span): currenttracer={"id":span["spanid"],"data":span} print(currenttracer) l.append(currenttracer) defrecord(self): self.span["servername"]=self.servername self.span["location"]=os.getcwd()+"."+self.servername self.span["endtime"]=time.time() self.span["durationtime"]=self.span["endtime"]-self.span["starttime"] defsetspantag(self,tag): self.span["tag"]=tag defsetspanlog(self,log): self.span["log"]=log #连续调用 withRecorder('server1')asspan: time.sleep(1) span.setspantag("test") #调用server1方法 print("server1") withRecorder('server2',span)asspan1: time.sleep(2) #调用server2方法 print("server2") withRecorder('server3',span1)asspan2: time.sleep(0.5) #调用server3方法 print("server3") #并级连续调用 #withRecorder('server1')asspan1: #time.sleep(1) #span1.setspantag("test") ##调用server1方法 #print("server1") #withRecorder('server2',span1)asspan2: #time.sleep(2) ##调用server2方法 #print("server2") #withRecorder('server3',span1)asspan3: #time.sleep(0.5) ##调用server3方法 #print("server3") ##单独调用记录 #withRecorder('server4')asspan_test1: #time.sleep(1.5) #print("server4") # #withRecorder('server5')asspan_test2: #time.sleep(2) #print("server5")
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。