Skywalking与前端交互扩展开发(一文全掌握)
最近发现很多技术男都是lsp(手动狗头),所以我也先来一张美女镇楼,给大家提提神,别看我的文章看困了,哈哈。
对于想要扩展Skywalking OAP端的小伙伴们估计很容易发现一个问题,在官方和网上的资料很少,而且讲的都太浅显了。鄙人不才,作为一个研究了蛮久Skywalking的混子,打算写一篇oap实战的文章,并以此作为切入点来聊聊如果扩展和踩坑血泪史。
研发需求:
统计使用skywalking页面的pv(如果有说可以安装前端监控agent就能解决问题的杠精,请出门右转😄)
绘制的pv需求草图如下:
需求拆解:
- 编写graphqls文件的接口
- 编写前端代码【本文略】
- 使用ES作为数据源,完成接口的内部实现
实战开始:
Tip1:一般开源项目往往不会使用spring系列,所以一般来说都是通过系统生命周期的管理,一般套路是prepare() --> start() --> run() —>after() --> notify() 酱紫,在这些偏前面的方法里植入注册逻辑,再偏后面的方法里去获取对象来处理,就能达到spring的getBean的效果。
Tip2: 因为skywalking-oap是模块化的,但是有时候我们想要一个环绕的非业务性的通用逻辑,例如事件机制,记日志,配置中心(oap中配置中心依赖中间件,且模块层级偏深,个人感觉不是很好),导致了很难跨模块获取信息。这一点在后续的文章中再细聊吧。
编写graphqls文件的接口
直接看代码,不懂graphql语法也没关系,照葫芦画瓢即可。
## ------------------ 前端埋点 ------------------ ##
type PVData {
# 访问的页面名称
pageName: String
#pv数值
pv: Int
# 当前时间戳
dayTimestamp: Long
}
# 天级别的时间段
input DayDuration {
# 开始时间戳
start: Long!
# 结束时间戳
end: Long!
}
extend type Query {
# 仅支持天级别的查询
getPV(duration: DayDuration!): [PVData]
}
input UpdatePVRequest {
# 访问的页面名称(前端映射好)
pageName: String!
# 开始访问时间,UNIX时间戳
timestamp: Long!
}
type UpdatePVResponse {
# True means change successfully.
status: Boolean!
message: String!
}
extend type Mutation {
updatePV(updatePVRequest: UpdatePVRequest!): UpdatePVResponse!
}
使用ES作为数据源,完成接口的内部实现
结合上面Tip1讲的和接下来的代码细品 O(∩_∩)O~~
注册好graphql文件
修改GraphQLQueryProvider添加我们所需要的数据结构体,在prepare方法里面添加注册逻辑
.file("query-protocol/buried-point.graphqls")
.resolvers(new BuriedPointQuery(getManager()), new BuriedPointMutation(getManager()))
注册好Controller层
修改CoreModule,在addQueryService加我们所需的service
// add BuriedPointQueryService and BuriedPointQueryService
classes.add(BuriedPointQueryService.class);
classes.add(BuriedPointMutationService.class);
编写Controller接口代码
// 查询类型的实现
public class BuriedPointQuery implements GraphQLQueryResolver {
private final ModuleManager moduleManager;
private BuriedPointQueryService buriedPointQueryService;
public BuriedPointQuery(ModuleManager moduleManager) {
this.moduleManager = moduleManager;
}
private BuriedPointQueryService getBuriedPointQueryService() {
if (buriedPointQueryService == null) {
this.buriedPointQueryService = moduleManager.find(CoreModule.NAME)
.provider()
.getService(BuriedPointQueryService.class);
}
return buriedPointQueryService;
}
public List<PVData> getPV(DayDuration duration) throws IOException {
return getBuriedPointQueryService().getPV(duration);
}