#可观测性
在java体系下,skywalking是借助于jvm提供agent功能实现,中文互联网上介绍原理的内容较多。
既然skywalking支持python,那么在python中,其实现原理是如何?
在python中使用,需要手动启动,用法如下
from skywalking import agent, config
config.init(collector='127.0.0.1:11800', service='your awesome service')
agent.start()
在agent.start()
函数中,会调用各个组件插件模块,实现代理。以redis插件的代码为例:
插件skywalking\plugins\sw_redis.py
def install():
from redis.connection import Connection
_send_command = Connection.send_command
def _sw_send_command(this: Connection, *args, **kwargs):
peer = f'{this.host}:{this.port}'
if len(args) == 1:
cmd = args[0]
key = ''
elif len(args) > 1:
cmd, key = args[0], args[1]
else: # just to be safe
cmd = key = ''
if cmd in OPERATIONS_WRITE:
op = 'write'
elif cmd in OPERATIONS_READ:
op = 'read'
else:
op = ''
context = get_context()
with context.new_exit_span(op=f'Redis/{cmd}' or '/', peer=peer, component=Component.Redis) as span:
span.layer = Layer.Cache
res = _send_command(this, *args, **kwargs)
span.tag(TagCacheType('Redis'))
span.tag(TagCacheKey(key))
span.tag(TagCacheCmd(cmd))
span.tag(TagCacheOp(op))
return res
Connection.send_command = _sw_send_command
因为python是弱类型的动态语言,使用过程中不对对象的类型进行限制,且可以在运行过程中随时随地的动态获取或修改任一对象。
而python的模块(用到的库)在被import后,也是以对象的形式存在的,也可以被获取、被修改。而模块中的类定义,也是以对象的形式存在的,也可以被获取、被修改。
所以在业务代码启动运行前,加载redis对应的模块,并使用代理之后的函数替代Connection的send_command方法,在这之后再执行业务代码,此时再创建Connection类的示例,调用其send_command方法时,实际上是执行自定义的_sw_send_command方法,在这个方法中就可以完成trace和记录。
最终实现了 #代理模式