This is an automated email from the ASF dual-hosted git repository.

zhouzixin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-ruby.git


The following commit(s) were added to refs/heads/main by this push:
     new d38f200  Polish the code and add plugins (#4)
d38f200 is described below

commit d38f2009c327cb0add05abe22b4cb812fbbac6e6
Author: Zixin Zhou <[email protected]>
AuthorDate: Wed Jan 15 23:20:09 2025 +0800

    Polish the code and add plugins (#4)
---
 CHANGELOG.md                                       |  3 +-
 docs/en/agent/plugins.md                           | 12 +--
 docs/en/setup/quick-start.md                       |  2 +-
 lib/skywalking/configuration.rb                    |  2 +-
 lib/skywalking/plugins/elasticsearch.rb            | 61 ++++++++++++++
 lib/skywalking/plugins/memcached.rb                | 74 +++++++++++++++++
 lib/skywalking/plugins/net_http.rb                 |  2 +-
 lib/skywalking/plugins/redis5.rb                   |  6 +-
 lib/skywalking/plugins/sinatra.rb                  |  7 +-
 lib/skywalking/plugins_manager.rb                  |  2 +-
 lib/skywalking/tracing/carrier.rb                  |  2 +-
 lib/skywalking/tracing/constants.rb                |  4 +-
 lib/skywalking/tracing/segment.rb                  |  2 +-
 lib/skywalking/tracing/span.rb                     |  1 +
 lib/skywalking/tracing/span_context.rb             |  4 +-
 lib/skywalking/tracing/tag.rb                      | 14 ++++
 lib/skywalking/version.rb                          |  2 +-
 skywalking.gemspec                                 |  5 +-
 spec/scenarios/common/compose_context.rb           |  2 +-
 spec/scenarios/elasticsearch/docker-compose.yml    | 72 +++++++++++++++++
 spec/scenarios/elasticsearch/elasticsearch.rb      | 54 +++++++++++++
 .../scenarios/elasticsearch/elasticsearch_spec.rb  | 17 +++-
 spec/scenarios/elasticsearch/expected.yml          | 94 ++++++++++++++++++++++
 spec/scenarios/memcached/docker-compose.yml        | 67 +++++++++++++++
 spec/scenarios/memcached/expected.yml              | 81 +++++++++++++++++++
 .../scenarios/memcached/memcached.rb               | 17 +++-
 .../scenarios/memcached/memcached_spec.rb          | 17 +++-
 27 files changed, 593 insertions(+), 33 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c8861b4..80a611c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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.
\ No newline at end of file
diff --git a/docs/en/agent/plugins.md b/docs/en/agent/plugins.md
index a22d930..6c3ca8c 100644
--- a/docs/en/agent/plugins.md
+++ b/docs/en/agent/plugins.md
@@ -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`   |
\ No newline at end of file
+| 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` |
\ No newline at end of file
diff --git a/docs/en/setup/quick-start.md b/docs/en/setup/quick-start.md
index 68f4f9e..e367d35 100644
--- a/docs/en/setup/quick-start.md
+++ b/docs/en/setup/quick-start.md
@@ -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"}`.                                            
  |
diff --git a/lib/skywalking/configuration.rb b/lib/skywalking/configuration.rb
index 2d83988..6efe3ae 100644
--- a/lib/skywalking/configuration.rb
+++ b/lib/skywalking/configuration.rb
@@ -67,7 +67,7 @@ module Skywalking
       :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,
diff --git a/lib/skywalking/plugins/elasticsearch.rb 
b/lib/skywalking/plugins/elasticsearch.rb
new file mode 100644
index 0000000..1ad6975
--- /dev/null
+++ b/lib/skywalking/plugins/elasticsearch.rb
@@ -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
diff --git a/lib/skywalking/plugins/memcached.rb 
b/lib/skywalking/plugins/memcached.rb
new file mode 100644
index 0000000..d2f1f86
--- /dev/null
+++ b/lib/skywalking/plugins/memcached.rb
@@ -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
diff --git a/lib/skywalking/plugins/net_http.rb 
b/lib/skywalking/plugins/net_http.rb
index 64cb328..08e6b9c 100644
--- a/lib/skywalking/plugins/net_http.rb
+++ b/lib/skywalking/plugins/net_http.rb
@@ -35,7 +35,7 @@ module Skywalking
           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))
diff --git a/lib/skywalking/plugins/redis5.rb b/lib/skywalking/plugins/redis5.rb
index db5b777..d2e11ed 100644
--- a/lib/skywalking/plugins/redis5.rb
+++ b/lib/skywalking/plugins/redis5.rb
@@ -30,7 +30,11 @@ module Skywalking
             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
 
diff --git a/lib/skywalking/plugins/sinatra.rb 
b/lib/skywalking/plugins/sinatra.rb
index a9bf511..c1ea9ba 100644
--- a/lib/skywalking/plugins/sinatra.rb
+++ b/lib/skywalking/plugins/sinatra.rb
@@ -21,13 +21,12 @@ module Skywalking
           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']))
@@ -36,6 +35,8 @@ module Skywalking
             span&.component = Tracing::Component::Sinatra
 
             super(*args, &block)
+          rescue
+            span&.error_occurred = true
           end
         end
       end
diff --git a/lib/skywalking/plugins_manager.rb 
b/lib/skywalking/plugins_manager.rb
index 2a46155..d9387bc 100644
--- a/lib/skywalking/plugins_manager.rb
+++ b/lib/skywalking/plugins_manager.rb
@@ -34,7 +34,7 @@ module Skywalking
         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
diff --git a/lib/skywalking/tracing/carrier.rb 
b/lib/skywalking/tracing/carrier.rb
index d53472e..2acdd68 100644
--- a/lib/skywalking/tracing/carrier.rb
+++ b/lib/skywalking/tracing/carrier.rb
@@ -21,7 +21,7 @@ module Skywalking
     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: '',
diff --git a/lib/skywalking/tracing/constants.rb 
b/lib/skywalking/tracing/constants.rb
index 6c3422c..ebffd1c 100644
--- a/lib/skywalking/tracing/constants.rb
+++ b/lib/skywalking/tracing/constants.rb
@@ -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
diff --git a/lib/skywalking/tracing/segment.rb 
b/lib/skywalking/tracing/segment.rb
index 258892a..101fe00 100644
--- a/lib/skywalking/tracing/segment.rb
+++ b/lib/skywalking/tracing/segment.rb
@@ -32,7 +32,7 @@ module Skywalking
       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
diff --git a/lib/skywalking/tracing/span.rb b/lib/skywalking/tracing/span.rb
index 1f18760..4eb1108 100644
--- a/lib/skywalking/tracing/span.rb
+++ b/lib/skywalking/tracing/span.rb
@@ -104,6 +104,7 @@ module Skywalking
 
         ref = SegmentRef.new(carrier)
         @refs << ref unless @refs.include?(ref)
+
         self
       end
     end
diff --git a/lib/skywalking/tracing/span_context.rb 
b/lib/skywalking/tracing/span_context.rb
index 6dff1a5..fa882cc 100644
--- a/lib/skywalking/tracing/span_context.rb
+++ b/lib/skywalking/tracing/span_context.rb
@@ -201,9 +201,9 @@ module Skywalking
           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
diff --git a/lib/skywalking/tracing/tag.rb b/lib/skywalking/tracing/tag.rb
index 2cf348d..2bf45c7 100644
--- a/lib/skywalking/tracing/tag.rb
+++ b/lib/skywalking/tracing/tag.rb
@@ -53,6 +53,13 @@ module Skywalking
       end
     end
 
+    class TagDbStatement < Tag
+      def initialize(val)
+        super
+        @key = 'db.statement'
+      end
+    end
+
     class TagCacheType < Tag
       def initialize(val)
         super
@@ -80,5 +87,12 @@ module Skywalking
         @key = 'cache.key'
       end
     end
+
+    class TagCacheMiss < Tag
+      def initialize(val)
+        super
+        @key = 'cache.miss'
+      end
+    end
   end
 end
diff --git a/lib/skywalking/version.rb b/lib/skywalking/version.rb
index feec054..e4d1e85 100644
--- a/lib/skywalking/version.rb
+++ b/lib/skywalking/version.rb
@@ -14,5 +14,5 @@
 #  limitations under the License.
 
 module Skywalking
-  VERSION = "0.0.0.beta1".freeze
+  VERSION = "0.0.0.beta2".freeze
 end
diff --git a/skywalking.gemspec b/skywalking.gemspec
index cf46aa3..fb0c5b7 100644
--- a/skywalking.gemspec
+++ b/skywalking.gemspec
@@ -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'
@@ -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
diff --git a/spec/scenarios/common/compose_context.rb 
b/spec/scenarios/common/compose_context.rb
index 741291d..d771d95 100644
--- a/spec/scenarios/common/compose_context.rb
+++ b/spec/scenarios/common/compose_context.rb
@@ -30,7 +30,7 @@ RSpec.shared_context 'compose' do
 
   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
diff --git a/spec/scenarios/elasticsearch/docker-compose.yml 
b/spec/scenarios/elasticsearch/docker-compose.yml
new file mode 100644
index 0000000..880ec79
--- /dev/null
+++ b/spec/scenarios/elasticsearch/docker-compose.yml
@@ -0,0 +1,72 @@
+#
+# 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.
+#
+
+version: "2.1"
+
+services:
+  oap:
+    extends:
+      file: ../common/base-compose.yml
+      service: oap
+    networks:
+      - gem
+  
+  elasticsearch:
+    image: elasticsearch:8.0.0
+    hostname: elasticsearch
+    ports:
+      - "9200:9200"
+    environment:
+      - discovery.type=single-node
+      - bootstrap.memory_lock=true
+      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
+      - xpack.security.enabled=false
+    networks:
+      - gem
+    healthcheck:
+      test: [ "CMD-SHELL", "curl --silent --fail 
localhost:9200/_cluster/health || exit 1" ]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+  
+  service:
+    extends:
+      file: ../common/base-compose.yml
+      service: agent
+    ports:
+      - "8080:8080"
+    volumes:
+      - .:/app/spec/scenarios/elasticsearch
+    environment:
+      SW_AGENT_SERVICE_NAME: "elasticsearch"
+    healthcheck:
+      test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/8080" 
]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+    entrypoint:
+      - "sh"
+      - "-c"
+      - "gem install sinatra rackup puma elasticsearch && ruby 
/app/spec/scenarios/elasticsearch/elasticsearch.rb"
+    depends_on:
+      oap:
+        condition: service_healthy
+    networks:
+      - gem
+
+networks:
+  gem:
\ No newline at end of file
diff --git a/spec/scenarios/elasticsearch/elasticsearch.rb 
b/spec/scenarios/elasticsearch/elasticsearch.rb
new file mode 100644
index 0000000..eb788d9
--- /dev/null
+++ b/spec/scenarios/elasticsearch/elasticsearch.rb
@@ -0,0 +1,54 @@
+#  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.
+
+require_relative '../../../lib/skywalking'
+require 'sinatra'
+require 'elasticsearch'
+
+Skywalking.start(disable_plugins: 'net_http')
+
+def create_index(client)
+  client.indices.create(index: 'test_index', body: { mappings: { properties: { 
name: { type: 'text' } } } })
+  puts "Index created."
+end
+
+def add_document(client, id, name)
+  client.index(index: 'test_index', id: id, body: { name: name })
+  puts "Document added: #{id} => #{name}"
+end
+
+def get_document(client, id)
+  response = client.get(index: 'test_index', id: id)
+  puts "Document retrieved: #{response['_source']}"
+rescue Elasticsearch::Transport::Transport::Errors::NotFound
+  puts "Document not found."
+end
+
+def delete_document(client, id)
+  client.delete(index: 'test_index', id: id)
+  puts "Document deleted: #{id}"
+end
+
+get "/execute" do
+  client = Elasticsearch::Client.new(hosts: ['http://elasticsearch:9200'], 
log: true, 
+    transport_options: { request: { timeout: 5 } })
+  create_index(client)
+  add_document(client, '1', 'Document 1')
+  get_document(client, '1')
+  delete_document(client, '1')
+end
+
+set :bind, '0.0.0.0'
+set :port, 8080
\ No newline at end of file
diff --git a/lib/skywalking/version.rb 
b/spec/scenarios/elasticsearch/elasticsearch_spec.rb
similarity index 69%
copy from lib/skywalking/version.rb
copy to spec/scenarios/elasticsearch/elasticsearch_spec.rb
index feec054..7059ed9 100644
--- a/lib/skywalking/version.rb
+++ b/spec/scenarios/elasticsearch/elasticsearch_spec.rb
@@ -13,6 +13,17 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 
-module Skywalking
-  VERSION = "0.0.0.beta1".freeze
-end
+require_relative '../common/common_spec_helper'
+require_relative '../common/compose_context'
+
+RSpec.describe "Elasticsearch" do
+  include CommonSpecHelper
+  include_context 'compose'
+  include_context 'scenario value'
+
+  let(:root_dir) { File.expand_path(__dir__) }
+
+  it 'test elasticsearch plugin' do
+    test_plugin('elasticsearch')
+  end
+end
\ No newline at end of file
diff --git a/spec/scenarios/elasticsearch/expected.yml 
b/spec/scenarios/elasticsearch/expected.yml
new file mode 100644
index 0000000..4dffeba
--- /dev/null
+++ b/spec/scenarios/elasticsearch/expected.yml
@@ -0,0 +1,94 @@
+# 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.
+
+segmentItems:
+  - serviceName: elasticsearch
+    segmentSize: ge 1
+    segments:
+      - segmentId: not null
+        spans:
+          - operationName: Elasticsearch/PUT/test_index
+            parentSpanId: 0
+            spanId: 1
+            spanLayer: Database
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 47
+            isError: false
+            spanType: Exit
+            peer: http://elasticsearch:9200
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Elasticsearch }
+              - { key: db.statement, value: '[{:params=>{}}, 
{:body=>{:mappings=>{:properties=>{:name=>{:type=>"text"}}}}}]' }
+          - operationName: Elasticsearch/PUT/test_index/_doc/1
+            parentSpanId: 0
+            spanId: 2
+            spanLayer: Database
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 47
+            isError: false
+            spanType: Exit
+            peer: http://elasticsearch:9200
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Elasticsearch }
+              - { key: db.statement, value: '[{:params=>{}}, 
{:body=>{:name=>"Document 1"}}]' }
+          - operationName: Elasticsearch/GET/test_index/_doc/1
+            parentSpanId: 0
+            spanId: 3
+            spanLayer: Database
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 47
+            isError: false
+            spanType: Exit
+            peer: http://elasticsearch:9200
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Elasticsearch }
+              - { key: db.statement, value: '[{:params=>{}}]' }
+          - operationName: Elasticsearch/DELETE/test_index/_doc/1
+            parentSpanId: 0
+            spanId: 4
+            spanLayer: Database
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 47
+            isError: false
+            spanType: Exit
+            peer: http://elasticsearch:9200
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Elasticsearch }
+              - { key: db.statement, value: '[{:params=>{}}]' }
+          - operationName: GET:/execute
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 12001
+            isError: false
+            spanType: Entry
+            peer: localhost:8080
+            skipAnalysis: false
+            tags:
+              - { key: http.method, value: GET }
+              - { key: http.url, value: /execute }
+meterItems: [ ]
+logItems: [ ]
\ No newline at end of file
diff --git a/spec/scenarios/memcached/docker-compose.yml 
b/spec/scenarios/memcached/docker-compose.yml
new file mode 100644
index 0000000..18dacdb
--- /dev/null
+++ b/spec/scenarios/memcached/docker-compose.yml
@@ -0,0 +1,67 @@
+#
+# 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.
+#
+
+version: "2.1"
+
+services:
+  oap:
+    extends:
+      file: ../common/base-compose.yml
+      service: oap
+    networks:
+      - gem
+  
+  memcached:
+    image: memcached:1.6
+    hostname: memcached
+    ports:
+      - "11211:11211"
+    networks:
+      - gem
+    healthcheck:
+      test: [ "CMD", "nc", "-z", "localhost", "11211" ]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+  
+  service:
+    extends:
+      file: ../common/base-compose.yml
+      service: agent
+    ports:
+      - "8080:8080"
+    volumes:
+      - .:/app/spec/scenarios/memcached
+    environment:
+      SW_AGENT_SERVICE_NAME: "memcached"
+    healthcheck:
+      test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/8080" 
]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+    entrypoint:
+      - "sh"
+      - "-c"
+      - "gem install sinatra rackup puma dalli && ruby 
/app/spec/scenarios/memcached/memcached.rb"
+    depends_on:
+      oap:
+        condition: service_healthy
+    networks:
+      - gem
+
+networks:
+  gem:
\ No newline at end of file
diff --git a/spec/scenarios/memcached/expected.yml 
b/spec/scenarios/memcached/expected.yml
new file mode 100644
index 0000000..37c4111
--- /dev/null
+++ b/spec/scenarios/memcached/expected.yml
@@ -0,0 +1,81 @@
+# 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.
+
+segmentItems:
+  - serviceName: memcached
+    segmentSize: ge 1
+    segments:
+      - segmentId: not null
+        spans:
+          - operationName: Memcached/set
+            parentSpanId: 0
+            spanId: 1
+            spanLayer: Cache
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 20
+            isError: false
+            spanType: Exit
+            peer: memcached:11211
+            skipAnalysis: false
+            tags:
+              - {key: cache.type, value: Memcached}
+              - {key: cache.key, value: sw_key}
+          - operationName: Memcached/get
+            parentSpanId: 0
+            spanId: 2
+            spanLayer: Cache
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 20
+            isError: false
+            spanType: Exit
+            peer: memcached:11211
+            skipAnalysis: false
+            tags:
+              - {key: cache.type, value: Memcached}
+              - {key: cache.key, value: sw_key}
+              - {key: cache.miss, value: 'false'}
+          - operationName: Memcached/delete
+            parentSpanId: 0
+            spanId: 3
+            spanLayer: Cache
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 20
+            isError: false
+            spanType: Exit
+            peer: memcached:11211
+            skipAnalysis: false
+            tags:
+              - {key: cache.type, value: Memcached}
+              - {key: cache.key, value: sw_key}
+          - operationName: GET:/execute
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 12001
+            isError: false
+            spanType: Entry
+            peer: localhost:8080
+            skipAnalysis: false
+            tags:
+              - {key: http.method, value: GET}
+              - {key: http.url, value: /execute}
+meterItems: []
+logItems: []
\ No newline at end of file
diff --git a/lib/skywalking/version.rb b/spec/scenarios/memcached/memcached.rb
similarity index 68%
copy from lib/skywalking/version.rb
copy to spec/scenarios/memcached/memcached.rb
index feec054..fbe493a 100644
--- a/lib/skywalking/version.rb
+++ b/spec/scenarios/memcached/memcached.rb
@@ -13,6 +13,19 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 
-module Skywalking
-  VERSION = "0.0.0.beta1".freeze
+require_relative '../../../lib/skywalking'
+require 'sinatra'
+require 'dalli'
+
+Skywalking.start
+
+get "/execute" do
+  client = Dalli::Client.new('memcached:11211', { namespace: "sw", compress: 
true })
+  client.set('sw_key', 'sw_value')
+  value = client.get('sw_key')
+  p "The value for 'sw_key' is: #{value}"
+  client.delete('sw_key')
 end
+
+set :bind, '0.0.0.0'
+set :port, 8080
\ No newline at end of file
diff --git a/lib/skywalking/version.rb 
b/spec/scenarios/memcached/memcached_spec.rb
similarity index 70%
copy from lib/skywalking/version.rb
copy to spec/scenarios/memcached/memcached_spec.rb
index feec054..1f00d92 100644
--- a/lib/skywalking/version.rb
+++ b/spec/scenarios/memcached/memcached_spec.rb
@@ -13,6 +13,17 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 
-module Skywalking
-  VERSION = "0.0.0.beta1".freeze
-end
+require_relative '../common/common_spec_helper'
+require_relative '../common/compose_context'
+
+RSpec.describe "Memcached" do
+  include CommonSpecHelper
+  include_context 'compose'
+  include_context 'scenario value'
+
+  let(:root_dir) { File.expand_path(__dir__) }
+
+  it 'test memcached plugin' do
+    test_plugin('memcached')
+  end
+end
\ No newline at end of file


Reply via email to