# 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 NetHttp < PluginsManager::SWPlugin module HttpIntercept def request(req, body = nil, &block) method = req.method host = req['host']&.split(':')&.first || address || 'localhost' req_path = URI(req.path) req_info = "" uri = if req_path.host req_path else path, query = req.path.split('?') scheme = use_ssl? ? 'https' : 'http' req_info = "#{path}#{query ? "?#{query}" : ''}" full_url = "#{scheme}://#{host}#{":#{port}" if port}#{req_info}" URI(full_url) end Tracing::ContextManager.new_exit_span( operation: "#{method}:#{req_info}", peer: host, component: Tracing::Component::HttpClient ) do |span| span&.tag(Tracing::TagHttpMethod.new(method)) span&.tag(Tracing::TagHttpURL.new(uri)) span&.layer = Tracing::Layer::Http carrier = span&.inject headers = req.instance_variable_get(:@header) carrier&.each do |item| headers[item.key] ||= [] headers[item.key].concat(Array(item.value)) end result = super(req, body, &block) span&.tag(Tracing::TagHttpStatusCode.new(result.code)) if result.code >= "400" span&.error_occurred = true end result end end end def plugin_valid? defined?(::Net) && defined?(::Net::HTTP) end def install ::Net::HTTP.prepend HttpIntercept end register :net_http end end end