Skip to content

Commit

Permalink
Polish the code and add plugins (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
CodePrometheus authored Jan 15, 2025
1 parent 4f3e927 commit d38f200
Show file tree
Hide file tree
Showing 27 changed files with 639 additions and 25 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ Release Notes.
#### Features
- Initialize the ruby agent core.
- Implement e2e tests.
- Add docs.

#### Plugins
* Support [Sinatra](https://github.com/sinatra/sinatra)
* Support [redis-rb](https://github.com/redis/redis-rb)
* Support [net-http](https://github.com/ruby/net-http)
* Support [memcached](https://github.com/petergoldstein/dalli)
* Support [elasticsearch](https://github.com/elastic/elasticsearch-ruby)

#### Documentation
* Initialize the documentation.
12 changes: 7 additions & 5 deletions docs/en/agent/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
The following plugins provide the distributed tracing capability, and the OAP backend would analyze the topology and
metrics based on the tracing data.

| Library | Version | Plugin Name |
|:----------------------------------------------|:---------|:------------|
| [redis](https://github.com/redis/redis-rb) | ~> 5.0 | `redis` |
| [net-http](https://github.com/ruby/net-http) | ~> 0.6.0 | `net_http` |
| [sinatra](https://github.com/sinatra/sinatra) | ~> 4.1 | `sinatra` |
| Library | Version | Plugin Name |
|:---------------------------------------------------------------|:---------|:----------------|
| [redis](https://github.com/redis/redis-rb) | ~> 5.0 | `redis5` |
| [net-http](https://github.com/ruby/net-http) | ~> 0.6.0 | `net_http` |
| [sinatra](https://github.com/sinatra/sinatra) | ~> 4.1 | `sinatra` |
| [memcached](https://github.com/petergoldstein/dalli) | ~> 3.2 | `memcached` |
| [elasticsearch](https://github.com/elastic/elasticsearch-ruby) | ~> 8.0.0 | `elasticsearch` |
2 changes: 1 addition & 1 deletion docs/en/setup/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ The following lists all the configuration options:
| log_file_name | SW_AGENT_LOG_FILE_NAME | skywalking | The name of the log file. |
| log_file_path | SW_AGENT_LOG_FILE_PATH | Not set | The path to the log file. |
| log_level | SW_AGENT_LOG_LEVEL | info | The log level. |
| disable_plugins | SW_AGENT_DISABLE_PLUGINS | Not set | The plugins to disable. |
| disable_plugins | SW_AGENT_DISABLE_PLUGINS | Not set | The plugins to disable, multiple names should be split by comma, e.g. 'redis5,elasticsearch'. |
| report_protocol | SW_AGENT_REPORT_PROTOCOL | grpc | The protocol to use for reporting. |
| re_ignore_operation | SW_AGENT_RE_IGNORE_OPERATION | Not set | Ignore specific URL paths. |
| instance_properties_json | SW_AGENT_INSTANCE_PROPERTIES_JSON | Not set | A custom JSON string to be reported as service instance properties, e.g. `{"key": "value"}`. |
Expand Down
2 changes: 1 addition & 1 deletion lib/skywalking/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Configuration
:disable_plugins => {
type: :string,
default: '',
desc: 'The plugins to disable'
desc: "The plugins to disable, multiple names should be split by comma, e.g. 'redis5,elasticsearch'"
},
:report_protocol => {
type: :string,
Expand Down
61 changes: 61 additions & 0 deletions lib/skywalking/plugins/elasticsearch.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

module Skywalking
module Plugins
class Elasticsearch < PluginsManager::SWPlugin
def plugin_valid?
defined?(::Elasticsearch)
end

def install
inst_target = if defined?(::Elastic::Transport::Client)
::Elastic::Transport::Client
elsif defined?(::Elasticsearch::Transport::Client)
::Elasticsearch::Transport::Client
end

inst_target.class_eval do
def perform_request_with_skywalking(method, path, *args, &block)
peer_info = transport.hosts.first
db_statement = [{ params: args&.[](0) }]
unless args[1].nil? || args[1].empty?
db_statement << { body: args[1] }
end

Tracing::ContextManager.new_exit_span(
operation: "Elasticsearch/#{method}/#{path}",
peer: "#{peer_info[:protocol]}://#{peer_info[:host]}:#{peer_info[:port]}",
component: Tracing::Component::Elasticsearch
) do |span|
span&.tag(Tracing::TagDbType.new("Elasticsearch"))
span&.tag(Tracing::TagDbStatement.new(db_statement))
span&.layer = Tracing::Layer::Database

zuper_perform_request(method, path, *args, &block)
rescue
span&.error_occurred = true
end
end

alias_method :zuper_perform_request, :perform_request
alias_method :perform_request, :perform_request_with_skywalking
end
end

register :elasticsearch
end
end
end
74 changes: 74 additions & 0 deletions lib/skywalking/plugins/memcached.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

module Skywalking
module Plugins
module MemcachedIntercept
def self.included(klass)
supported_method =
[:add, :append, :delete, :cas, :incr, :increment, :prepend, :replace, :set, :get, :fetch]
.select do |method_name|
klass.method_defined?(method_name) || klass.private_method_defined?(method_name)
end

supported_method.each do |method_name|
zuper_method = :"zuper_#{method_name}"
method_with_skywalking = :"#{method_name}_with_skywalking"

klass.class_eval do
define_method(method_with_skywalking) do |*args, &block|
cache_key = args[0].to_s if args.length && !args[0].is_a?(Array)
Tracing::ContextManager.new_exit_span(
operation: "Memcached/#{method_name}",
peer: @normalized_servers.join(','),
component: Tracing::Component::Memcached
) do |span|
span&.layer = Tracing::Layer::Cache
span&.tag(Tracing::TagCacheType.new("Memcached"))
span&.tag(Tracing::TagCacheKey.new(cache_key))

resp = __send__(zuper_method, *args, &block)
if method_name == :get && args.length && args[0].instance_of?(String)
span&.tag(Tracing::TagCacheMiss.new(resp.nil?))
end

resp
rescue
span&.error_occurred = true
end
end

alias_method zuper_method, method_name
alias_method method_name, method_with_skywalking
end
end
end
end

class Memcached < PluginsManager::SWPlugin
def plugin_valid?
defined?(::Dalli::Client)
end

def install
::Dalli::Client.class_eval do
include Skywalking::Plugins::MemcachedIntercept
end
end

register :memcached
end
end
end
2 changes: 1 addition & 1 deletion lib/skywalking/plugins/net_http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def request(req, body = nil, &block)
Tracing::ContextManager.new_exit_span(
operation: "#{method}:#{req_info}",
peer: host,
component: Tracing::Component::Http
component: Tracing::Component::HttpClient
) do |span|
span&.tag(Tracing::TagHttpMethod.new(method))
span&.tag(Tracing::TagHttpURL.new(uri))
Expand Down
6 changes: 5 additions & 1 deletion lib/skywalking/plugins/redis5.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ def call_v(args, &block)
span&.tag(Tracing::TagCacheOp.new(operation))
span&.layer = Tracing::Layer::Cache

super(args, &block)
begin
super(args, &block)
rescue
span&.error_occurred = true
end
end
end

Expand Down
7 changes: 4 additions & 3 deletions lib/skywalking/plugins/sinatra.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ def dispatch!(*args, &block)
req_method = @request.request_method if @request.respond_to?(:request_method)
carrier = Tracing::Carrier.new
carrier.each do |item|
item.val = request.env[item.key.capitalize] if request.env[item.key.capitalize]
item.value = request.env["HTTP_#{item.key.upcase}"]
end

Tracing::ContextManager.new_entry_span(
operation: "#{req_method}:#{request.env['REQUEST_URI']}",
carrier: carrier,
inherit: Tracing::Component::General
carrier: carrier
) do |span|
span&.tag(Tracing::TagHttpMethod.new(req_method))
span&.tag(Tracing::TagHttpURL.new(request.env['REQUEST_URI']))
Expand All @@ -36,6 +35,8 @@ def dispatch!(*args, &block)
span&.component = Tracing::Component::Sinatra

super(*args, &block)
rescue
span&.error_occurred = true
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/skywalking/plugins_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def init_plugins
Dir[File.join(__dir__, 'plugins', '*.rb')].each { |file| require file }

installed_plugins = self.class.installed.keys
@enabled_plugins ||= installed_plugins - @config[:disable_plugins].split(',')
@enabled_plugins ||= installed_plugins - @config[:disable_plugins].split(',').map(&:to_sym)
@enabled_plugins.each do |plugin_name|
self.class.installed[plugin_name].try_install(plugin_name)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/skywalking/tracing/carrier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module Tracing
class Carrier < CarrierItem
attr_reader :trace_id, :correlation_carrier, :service_instance,
:endpoint, :segment_id, :span_id,
:peer, :items, :iter_index
:peer, :items, :iter_index, :service

def initialize(
trace_id: '',
Expand Down
4 changes: 3 additions & 1 deletion lib/skywalking/tracing/constants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ module Skywalking
module Tracing
module Component
Unknown = 0
Http = 2
HttpClient = 2
Redis = 7
Memcached = 20
Elasticsearch = 47
General = 12000
Sinatra = 12001
end
Expand Down
2 changes: 1 addition & 1 deletion lib/skywalking/tracing/segment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def archive(span)
end

def relate(trace_id)
@related_traces.shift if @related_traces.first.is_a?(Utils::IDGen.new)
@related_traces.pop if @related_traces[0].is_a?(Utils::IDGen)
@related_traces << trace_id
end
end
Expand Down
1 change: 1 addition & 0 deletions lib/skywalking/tracing/span.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def extract(carrier)

ref = SegmentRef.new(carrier)
@refs << ref unless @refs.include?(ref)

self
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/skywalking/tracing/span_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,9 @@ def current_context
end
end

def new_exit_span(operation:, peer: nil, component: nil, &block)
def new_exit_span(operation:, peer: nil, component: nil, inherit: nil, &block)
context = current_context
span = context.new_exit_span(operation, peer, component: component)
span = context.new_exit_span(operation, peer, component: component, inherit: inherit)
span&.start

begin
Expand Down
14 changes: 14 additions & 0 deletions lib/skywalking/tracing/tag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ def initialize(val)
end
end

class TagDbStatement < Tag
def initialize(val)
super
@key = 'db.statement'
end
end

class TagCacheType < Tag
def initialize(val)
super
Expand Down Expand Up @@ -80,5 +87,12 @@ def initialize(val)
@key = 'cache.key'
end
end

class TagCacheMiss < Tag
def initialize(val)
super
@key = 'cache.miss'
end
end
end
end
2 changes: 1 addition & 1 deletion lib/skywalking/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
# limitations under the License.

module Skywalking
VERSION = "0.0.0.beta1".freeze
VERSION = "0.0.0.beta2".freeze
end
5 changes: 1 addition & 4 deletions skywalking.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Gem::Specification.new do |spec|
spec.require_paths = ['lib']

# Communication with OAP
spec.add_dependency 'grpc', '1.68.1'
spec.add_dependency 'grpc', '~> 1.68.0'

# Base dev dependency
spec.add_development_dependency 'bundler', '~> 2.0'
Expand All @@ -53,9 +53,6 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'bigdecimal', '3.1.5'

# E2E test dependency
spec.add_development_dependency 'redis', '~> 5.0'
spec.add_development_dependency 'sinatra', '~> 4.1'
spec.add_development_dependency 'testcontainers-compose', '~> 0.2.0'
spec.add_development_dependency 'faraday', '~> 2.12'
spec.add_development_dependency 'rspec-wait', '~> 1.0'
end
2 changes: 1 addition & 1 deletion spec/scenarios/common/compose_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

before(:each) do
compose.start
compose.wait_for_http(url: client_url, timeout: 600)
compose.wait_for_http(url: client_url, timeout: 800)
end

after(:each) do
Expand Down
Loading

0 comments on commit d38f200

Please sign in to comment.