Apache DevLake 是一个DevOps数据收集和整合工具,通过 Grafana 为开发团队呈现出不同阶段的数据,让团队能够以数据为驱动改进开发流程。
接下来我们就详细聊一聊系统是怎么跑起来的。
在我们的 golang 程序启动之前,首先会自动调用各个 package 的 init() 方法,我们主要看看services 包的载入,下面的代码有详细注释:
func init() { var err error // 获取配置信息 cfg = config.GetConfig() // 获取到数据库 db, err = runner.NewGormDb(cfg, logger.Global.Nested("db")) // 配置时区 location := cron.WithLocation(time.UTC) // 创建定时任务管理器 cronManager = cron.New(location) if err != nil { panic(err) } // 初始化数据迁移 migration.Init(db) // 注册框架的数据迁移脚本 migrationscripts.RegisterAll() // 载入插件,从cfg.GetString("PLUGIN_DIR")获取到的文件夹中载入所有.so文件,在LoadPlugins方法中,具体来讲,通过调用runner.LoadPlugins将pluginName:PluginMeta键值对存入到core.plugins中 err = runner.LoadPlugins( cfg.GetString("PLUGIN_DIR"), cfg, logger.Global.Nested("plugin"), db, ) if err != nil { panic(err) } // 执行数据迁移脚本,完成数据库框架层各个表的初始化 err = migration.Execute(context.Background()) if err != nil { panic(err) } // call service init pipelineServiceInit() }
Pipeline的运行流程
在讲解Pipeline流程之前,我们需要先解释一下Blueprint。
Blueprint是一个定时任务,包含了需要执行的子任务以及执行计划。Blueprint 的每一次执行记录是一条Historical Run(也称为 Pipeline),代表 DevLake 一次触发,通过一个或多个插件,完成了一个或多个数据收集转换的任务。
以下是 Pipeline 运行流程图:
一个pipeline包含一个二维数组tasks,主要是为了保证一系列任务按预设顺序执行。如果下图中的 Stage3 的插件需要依赖其他插件准备数据(例如 refdiff 的运行需要依赖 gitextractor 和 github,数据源与插件的更多信息请看文档),那么 Stage 3 开始执行时,需要保证其依赖项已在 Stage1 和 Stage2 执行完成:
Task的运行流程
在stage1,stage2,stage3中的各插件任务都是并行执行:
接下来就是顺序执行插件中的子任务
每一个插件子任务的运行流程(涉及到的 interface 及 func 会在下一节详细阐述)
options["tasks"]
以及subtaskMeta组建需要执行的子任务集合subtaskMetashelper.NewDefaultTaskContext
构建taskCtxpluginTask.PrepareTaskData
构建taskData,taskCtx.SubTaskContext(subtaskMeta.Name)
获取到子任务的subtaskCtxsubtaskMeta.EntryPoint(subtaskCtx)
type PluginMeta interface { Description() string //PkgPath information will be lost when compiled as plugin(.so), this func will return that info RootPkgPath() string }
type PluginTask interface { // return all available subtasks, framework will run them for you in order SubTaskMetas() []SubTaskMeta // based on task context and user input options, return data that shared among all subtasks PrepareTaskData(taskCtx TaskContext, options map[string]interface{}) (interface{}, error) }
var CollectMeetingTopUserItemMeta = core.SubTaskMeta{
Name: "collectMeetingTopUserItem",
EntryPoint: CollectMeetingTopUserItem,
EnabledByDefault: true,
Description: "Collect top user meeting data from Feishu api",
}
这篇文章介绍了 DevLake 的架构以及运行流程,还有三个核心 api_collector、api_extractor 和 data_convertor 将会在下一篇文章进行剖析。