SkyWalking Ruby 快速开始与原理介绍

本文演示如何将应用程序与 SkyWalking Ruby 集成,并对 Ruby 自动探针插件实现机制进行简要解读

By 周梓鑫 | Thursday, March 06, 2025

背景

Ruby 是一种动态、面向对象的编程语言,它的语法简洁优雅,支持多种编程范式,包括面向对象、函数式和元编程。其中依靠强大的元编程能力,Ruby 允许在运行时修改类和对象的行为。 SkyWalking 提供了 Ruby gem,方便 Ruby 项目集成, 该 gem 支持许多开箱即用的框架 和 gem。

本文基于 skywalking-ruby-v0.1,我们将指导你如何快速将 skywalking-ruby 项目集成到 Ruby 项目中,并以 redis-rb 为例,简要地介绍 SkyWalking Ruby 对插件自动探针的实现原理。

演示部分包括以下步骤:

  1. 部署 SkyWalking:这涉及设置 SkyWalking 后端和 UI 程序,使你能够看到最终效果。
  2. 为不同 Ruby 项目集成 skywalking:这里介绍了不同的 Ruby 项目如何集成 skywalking。
  3. 应用部署:你将导出环境变量并部署应用程序,以促进你的服务与 SkyWalking 后端之间的通信。
  4. 在 SkyWalking UI 上可视化:最后,你将发送请求并在 SkyWalking UI 中观察效果。

部署 SkyWalking

请从官方 SkyWalking 网站下载 SkyWalking APM 程序,然后 可以根据快速启动脚本启动所有所需服务。

接下来,你可以访问地址 http://localhost:8080/ 。此时,由于尚未部署任何应用程序,因此你将看不到任何数据。

为不同 Ruby 项目集成 SkyWalking

推荐使用 Bundler 来安装和管理 skywalking 的依赖。只需在 Gemfile 中声明,然后运行 bundle install 即可完成安装。

bash 复制代码
# Gemfile
source "https://rubygems.org"

gem "skywalking"

在 Rails 项目中集成

对于 Rails 项目,推荐使用以下命令自动生成配置文件:

sql 复制代码
bundle exec rails generate skywalking:start

该命令会在 config/initializers 目录下自动生成 skywalking.rb 文件,你可以在其中配置启动参数。

在 Sinatra 项目中集成

对于 Sinatra 项目,你需要手动在应用启动时调用 Skywalking.start。例如:

lua 复制代码
require 'sinatra'
require 'skywalking'

Skywalking.start

get '/sw' do
  "Hello SkyWalking!"
end

在 Gemfile 中,将 skywalking 放在 sinatra 之后,并在初始化时使用 Bundler.require,或者在 sinatra gem 加载后 调用 require 'skywalking'。注意,skywalking gem 需要位于其他 gem(如 redis、elasticsearch)之后。

应用部署

在开始部署应用程序之前,你可以通过环境变量更改 SkyWalking 中当前应用程序的服务名称。你还可以更改其配置,例如服务器端的地址。有关详细信息,请参阅文档

在这里,我们将当前服务的名称更改为 sw-ruby

接下来,你可以启动应用程序,这里以 sinatra 作为示例:

ini 复制代码
export SW_AGENT_SERVICE_NAME=sw-ruby

ruby sinatra.rb

在 SkyWalking UI 上可视化

现在,向应用程序发送请求并在 SkyWalking UI 中观察结果。

几秒钟后,重新访问 http://localhost:8080 的 SkyWalking UI。能够在主页上看到部署的 demo 服务。

此外,在追踪页面上,可以看到刚刚发送的请求。

插件实现机制

要了解 Ruby Agent 对插件自动探针的实现机制,首先要了解 Ruby 中祖先链的概念。祖先链是一个有序的列表,在 Ruby 中,每个类或模块都有一个祖先链, 它包含了一个类或模块的所有父类以及 mixin 模块(通过 include、prepend 或 extend 混入的模块)。 Ruby 在查找方法时,会按照祖先链的顺序依次查找,直到找到目标方法或抛出 NoMethodError。

ruby 复制代码
class User
end

我们定义了一个 User 类,那么它的祖先链是如下图:

接下来用 prepend 方法混入一个模块:

ruby 复制代码
module Dapper
  def brave
    "Hello from brave"
  end
end

class User
  prepend Dapper
end

p User.new.brave # => "Hello from brave"

prepend 会在上图 1 处进行插入,Ruby 首先在 Dapper 模块中查找 brave 方法,找到并调用,如果 Dapper 中没有 brave 方法, Ruby 会继续查找 User 类。 如果 User 类中也没有,Ruby 会继续查找 Object,依此类推。

根据这样的机制,简单介绍下我们如何对 redis-rb 进行方法插桩,下面代码是要进行插桩的目标方法:

ruby 复制代码
# lib/redis/client.rb
class Redis
  class Client < ::RedisClient
    def call_v(command, &block)
     super(command, &block)
    rescue ::RedisClient::Error => error
     Client.translate_error!(error)
    end
  end
end

下面是进行插桩的核心代码:

ruby 复制代码
module Skywalking
  module Plugins
    class Redis5 < PluginsManager::SWPlugin
      module Redis5Intercept
        def call_v(args, &block)
          operation = args[0] rescue "UNKNOWN"
          return super if operation == :auth

          Tracing::ContextManager.new_exit_span(
            operation: "Redis/#{operation.upcase}"
          ) do |span|
            # 省略对 span 的处理 
            super(args, &block) # 调用原方法
          end
        end
      end

      def install
        ::Redis::Client.prepend Redis5Intercept
      end
    end
  end
end

这里我们定义了一个 Redis5Intercept 模块,并将其作为 ::Redis::Client 的前置模块,根据 Ruby 方法查找机制, 当 Redis::Clientcall_v 方法被调用时,Ruby 会首先会执行 Redis5Intercept 中的 call_v 方法,这里祖先链的顺序如下:

rust 复制代码
Redis5Intercept -> Redis::Client -> ...(其他父类和模块)

同时在 Redis5Intercept 中的 call_v 方法中,super(args, &block) 会沿着祖先链找到下一个同名方法, 在这里也就是 Redis::Client 中的原始 call_v 方法,同时传递原始的参数和代码块。

总结

本文讲述了 Skywalking Ruby 在 Ruby 项目中的集成方法,并简要介绍了 SkyWalking Ruby 对插件自动探针的实现机制。

目前 Ruby 探针处于早期的开发阶段,未来我们将继续扩展 SkyWalking Ruby 的功能,添加更多插件支持。所以,请继续关注!

相关推荐
无聊的小强14 小时前
被告警吵醒太多次,我做了个让告警自动修复的监控工具
监控
冬奇Lab2 天前
一天一个开源项目(第37篇):awesome-selfhosted - 自托管软件资源集合
开源·自动化运维·资讯
可观测性用观测云5 天前
观测云错误中心:帮助团队统一错误视图,定位错误根因并快速修复
监控
OpsEye5 天前
监控 100 问(七):混合云环境下的 IT 监控策略
运维·it·监控·混合云
国思RDIF框架6 天前
Docker Compose多后端+多前端部署:日志集中管理实操指南(基础版+进阶版,亲测可用)
docker·容器·自动化运维
明月_清风12 天前
源码回溯的艺术:SourceMap 底层 VLQ 编码与离线解析架构实战
前端·监控
明月_清风13 天前
无感监控:深度拆解监控 SDK 的性能平衡术与调度策略
前端·监控
OpsEye15 天前
交换分区优化实战:从监控到调优,让系统告别卡顿
运维·it·监控·告警·swap·监控系统·交换分区
政安晨17 天前
政安晨【人工智能项目随笔】OpenClaw(AI人工智能助手)集成SMB服务器实现自动化音效素材处理实战
运维·自动化·自动化运维·samba·ai-agent·openclaw·音频素材openclaw处理
曹工不加班21 天前
别再用旧版了!OpenClaw 2026.2.9 更新迁移避坑指南
机器人·aigc·自动化运维