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")
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。