stackify-api-ruby 1.0.15 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ require 'net_http_unix'
2
+ require 'ostruct'
3
+
4
+ #
5
+ # This class will handle the sending of log messages to unix domain socket
6
+ #
7
+ module Stackify
8
+ class UnixSocketSender < AgentBaseSender
9
+
10
+ # send_request() This function will send http request via unix domain socket
11
+ # @msgs {Object} log group message
12
+ # return {Object} Return an object {status, message}
13
+ def send_request log_group
14
+ begin
15
+ client = NetX::HTTPUnix.new('unix://' + Stackify.configuration.unix_socket_path)
16
+ req = Net::HTTP::Post.new(Stackify.configuration.agent_log_url)
17
+ req.set_content_type('application/json')
18
+ req.body = log_group
19
+ response = client.request(req)
20
+ Stackify.internal_log :debug, "[UnixSocketSender] status_code = #{response.code}"
21
+ if response.code.to_i == 200
22
+ Stackify.internal_log :debug, "[UnixSocketSender]: Successfully send message via unix domain socket."
23
+ return OpenStruct.new({status: 200, msg: 'OK'})
24
+ else
25
+ Stackify.internal_log :debug, "[UnixSocketSender] Sending failed."
26
+ return OpenStruct.new({status: 500, msg: 'Not OK'})
27
+ end
28
+ rescue => exception
29
+ Stackify.log_internal_error "[UnixSocketSender] send_logs() Error: #{exception}"
30
+ return OpenStruct.new({status: 500, msg: exception})
31
+ end
32
+ end
33
+ end
34
+ end
@@ -3,6 +3,7 @@ module Stackify::Backtrace
3
3
  ALL_TEXT_FROM_START_TO_FIRST_COLON_REGEXP = /\A([^:]+)/
4
4
  NUMBER_BETWEEN_TWO_COLONS_REGEXP = /:(\d+):/
5
5
  TEXT_AFTER_IN_BEFORE_END_REGEXP = /in\s`(\S+)'\z/
6
+ TEXT_AFTER_IN_BEFORE_END_REGEXP_ = /in\s(\S+)'\z/
6
7
 
7
8
  def self.line_number backtrace_str
8
9
  backtrace_str[NUMBER_BETWEEN_TWO_COLONS_REGEXP, 1]
@@ -10,7 +11,7 @@ module Stackify::Backtrace
10
11
 
11
12
  def self.method_name backtrace_str
12
13
  return nil unless backtrace_str
13
- backtrace_str[TEXT_AFTER_IN_BEFORE_END_REGEXP, 1]
14
+ backtrace_str[TEXT_AFTER_IN_BEFORE_END_REGEXP, 1] || backtrace_str[TEXT_AFTER_IN_BEFORE_END_REGEXP_, 1]
14
15
  end
15
16
 
16
17
  def self.file_name backtrace_str
@@ -3,14 +3,16 @@ module Stackify
3
3
  class Configuration
4
4
 
5
5
  attr_accessor :api_key, :app_name, :app_location, :env, :log_level, :logger,
6
- :proxy, :mode, :base_api_url, :api_enabled
6
+ :proxy, :mode, :base_api_url, :api_enabled, :transport, :errors, :http_endpoint, :stdout_output, :buffered_logger
7
7
 
8
- attr_reader :errors, :send_interval, :flood_limit, :queue_max_size
8
+ attr_reader :send_interval, :flood_limit, :queue_max_size, :agent_log_url, :unix_socket_path, :http_endpoint
9
9
 
10
10
  def initialize
11
11
  @base_api_url = 'https://api.stackify.com'
12
12
  @errors = []
13
+ @app_name = ''
13
14
  @api_key = ''
15
+ @transport = get_env 'STACKIFY_TRANSPORT', 'default'
14
16
  @env = :production
15
17
  @flood_limit = 100
16
18
  @queue_max_size = 10000
@@ -20,14 +22,36 @@ module Stackify
20
22
  @mode = MODES[:both]
21
23
  @logger = Logger.new(STDOUT)
22
24
  @logger.level = Logger::UNKNOWN
25
+ @agent_log_url = '/log'
26
+ @unix_socket_path = '/usr/local/stackify/stackify.sock'
27
+ @http_endpoint = get_env 'STACKIFY_TRANSPORT_HTTP_ENDPOINT', 'https://localhost:10601'
28
+ @stdout_output = false
29
+ @buffered_logger = false
30
+ end
31
+
32
+ def get_env env_key, default
33
+ value = default
34
+ if ENV.keys.include? env_key
35
+ value = ENV[env_key]
36
+ end
37
+ return value
23
38
  end
24
39
 
25
40
  def is_valid?
26
- @errors = []
27
- validate_mode if validate_config_types
41
+ case Stackify.configuration.transport
42
+ when Stackify::DEFAULT
43
+ validate_default_transport
44
+ when Stackify::UNIX_SOCKET, Stackify::AGENT_HTTP
45
+ validate_agent_transport
46
+ end
28
47
  @errors.empty?
29
48
  end
30
49
 
50
+ def validate_transport_type
51
+ return true if ['agent_socket', 'agent_http', 'default'].include? @transport
52
+ @errors << 'Transport should be one of these values: [agent_socket, agent_http, default]. Should be a String.'
53
+ end
54
+
31
55
  private
32
56
 
33
57
  def validate_config_types
@@ -36,6 +60,27 @@ module Stackify
36
60
  validate_mode_type
37
61
  end
38
62
 
63
+ # Perform validation if transport type is default
64
+ # Required parameters are: env, app_name, api_key, log_level
65
+ def validate_default_transport
66
+ validate_app_name &&
67
+ validate_transport_type &&
68
+ validate_api_key &&
69
+ validate_env &&
70
+ validate_log_level &&
71
+ validate_mode_type
72
+ end
73
+
74
+ # Perform validation if transport type is agent_socket or agent_http
75
+ # Required parameters are: env, app_name, log_level
76
+ def validate_agent_transport
77
+ validate_env &&
78
+ validate_transport_type &&
79
+ validate_app_name &&
80
+ validate_log_level &&
81
+ validate_mode_type
82
+ end
83
+
39
84
  def validate_mode_type
40
85
  return true if @mode.is_a? Symbol
41
86
  @errors << 'Mode should be a Symbol'
@@ -43,7 +88,17 @@ module Stackify
43
88
 
44
89
  def validate_api_key
45
90
  return true if @api_key.is_a?(String) && !@api_key.empty?
46
- @errors << 'API_KEY should be a String and not empty'
91
+ @errors << 'Api_key should be a String and not empty'
92
+ end
93
+
94
+ def validate_app_name
95
+ return true if @app_name.is_a?(String) && !@app_name.empty?
96
+ @errors << 'App_name should be a String and not empty'
97
+ end
98
+
99
+ def validate_env
100
+ return true if @env.is_a?(Symbol) && !@env.empty?
101
+ @errors << 'Env should be a Symbol and not empty'
47
102
  end
48
103
 
49
104
  def validate_log_level
@@ -14,16 +14,20 @@ module Stackify::Utils
14
14
  end
15
15
 
16
16
  def self.do_only_if_authorized_and_mode_is_on mode, &block
17
- if Stackify.configuration.api_enabled
18
- if Stackify.authorized?
19
- if is_mode_on? mode
20
- yield
17
+ begin
18
+ if Stackify.configuration.api_enabled
19
+ if Stackify.authorized?
20
+ if is_mode_on? mode
21
+ yield
22
+ else
23
+ Stackify.internal_log :warn, "[Stackify::Utils] - #{caller[0]}: Skipped because mode - #{mode.to_s} is disabled at configuration"
24
+ end
21
25
  else
22
- Stackify.internal_log :warn, "#{caller[0]}: Skipped because mode - #{mode.to_s} is disabled at configuration"
26
+ Stackify.internal_log :warn, "[Stackify::Utils] - #{caller[0]}: Skipped due to authorization failure"
23
27
  end
24
- else
25
- Stackify.internal_log :warn, "#{caller[0]}: Skipped due to authorization failure"
26
28
  end
29
+ rescue => ex
30
+ Stackify.internal_log :warn, "[Stackify::Utils] do_only_if_authorized_and_mode_is_on ex: #{ex.inspect}"
27
31
  end
28
32
  end
29
33
 
@@ -33,4 +37,38 @@ module Stackify::Utils
33
37
  found = exclude.select{|e| e =~ /#{cmd}/i}
34
38
  Stackify.configuration.api_enabled = false if found.count > 0
35
39
  end
36
- end
40
+
41
+ def self.get_app_settings
42
+ @env = {
43
+ 'env' => Stackify.configuration.env,
44
+ 'app_name' => Stackify.configuration.app_name,
45
+ 'server_name' => Socket.gethostname,
46
+ 'app_location' => Stackify.configuration.app_location || Dir.pwd
47
+ }
48
+ end
49
+
50
+ # Check if the app is running on rails and the logger output is using STDOUT
51
+ def self.check_log_output
52
+ if defined? Rails
53
+ if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new('5.0')
54
+ Stackify.configuration.stdout_output = ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDOUT)
55
+ else
56
+ Stackify.configuration.stdout_output = self.logger_stdout
57
+ end
58
+ end
59
+ end
60
+
61
+ def self.logger_stdout
62
+ logdev = ::Rails.logger.instance_variable_get(:@logdev)
63
+ logger_source = logdev.dev if logdev.respond_to?(:dev)
64
+ sources = [$stdout]
65
+ found = sources.any? { |source| source == logger_source }
66
+ end
67
+
68
+ # Check if the rails version 3 and it's using the buffered logger
69
+ def self.check_buffered_logger
70
+ is_buffered_logger = false
71
+ is_buffered_logger = true if ::Rails.logger.is_a?(ActiveSupport::BufferedLogger)
72
+ Stackify.configuration.buffered_logger = is_buffered_logger
73
+ end
74
+ end
@@ -0,0 +1,85 @@
1
+ module Stackify
2
+ class ProtobufLogObject
3
+ def initialize level, msg, caller_str, trans_id=nil, log_uuid=nil, ex=nil
4
+ @level, @msg, @caller_str, @ex = level, msg, caller_str, ex, @trans_id = trans_id,
5
+ @log_uuid = log_uuid
6
+ end
7
+
8
+ # Create a LogMsgGroup Protobuf Object
9
+ def to_obj
10
+ begin
11
+ log = Stackify::LogGroup::Log.new
12
+ log.message = @msg
13
+ log.thread_name = Thread.current.object_id.to_s
14
+ log.date_millis = (Time.now.to_f * 1000).to_i
15
+ log.level = @level.to_s.upcase!
16
+ log.source_method = Stackify::Backtrace.method_name(@caller_str).to_s
17
+ log.source_line = Stackify::Backtrace.line_number(@caller_str).to_i
18
+ log.transaction_id = @trans_id unless @trans_id.nil?
19
+ log.id = @log_uuid unless @log_uuid.nil?
20
+ if @ex.try(:to_h)
21
+ ex = @ex.try(:to_h)
22
+ log_error = Stackify::LogGroup::Log::Error.new
23
+ log_error.date_millis = ex['OccurredEpochMillis'].to_i
24
+ if ex['EnvironmentDetail']
25
+ env = ex['EnvironmentDetail']
26
+ env_detail = Stackify::LogGroup::Log::Error::EnvironmentDetail.new
27
+ env_detail.device_name = env['DeviceName'].to_s
28
+ env_detail.application_name = env['AppName'].to_s
29
+ env_detail.application_location = env['AppLocation'].to_s
30
+ env_detail.configured_application_name = env['ConfiguredAppName'].to_s
31
+ env_detail.configured_environment_name = env['ConfiguredEnvironmentName'].to_s
32
+ log_error.environment_detail = env_detail
33
+ end
34
+ if ex['Error']
35
+ err = ex['Error']
36
+ error_item = Stackify::LogGroup::Log::Error::ErrorItem.new
37
+ error_item.message = err['Message'].to_s
38
+ error_item.error_type = err['ErrorType'].to_s
39
+ error_item.error_type_code = err['ErrorTypeCode'].to_s
40
+ if err['Data']
41
+ map_data = Google::Protobuf::Map.new(:string, :string)
42
+ err['Data'].each { |key, value| map_data["#{key}"] = value }
43
+ error_item.data = map_data
44
+ end
45
+ error_item.inner_error = err['InnerError']
46
+ error_item.source_method = err['SourceMethod'].to_s
47
+ if err['StackTrace']
48
+ stack = err['StackTrace']
49
+ stack.each do |stk|
50
+ trace_frame = Stackify::LogGroup::Log::Error::ErrorItem::TraceFrame.new
51
+ trace_frame.code_filename = stk['CodeFileName'].to_s
52
+ trace_frame.line_number = stk['LineNum'].to_i
53
+ trace_frame.method = stk['Method'].to_s
54
+ error_item.stacktrace.push(trace_frame)
55
+ end
56
+ end
57
+ log_error.error_item = error_item
58
+ end
59
+ if ex['WebRequestDetail']
60
+ req_details = ex['WebRequestDetail']
61
+ web_request = Stackify::LogGroup::Log::Error::WebRequestDetail.new
62
+ web_request.user_ip_address = req_details['UserIPAddress'].to_s
63
+ web_request.http_method = req_details['HttpMethod'].to_s
64
+ web_request.request_url = req_details['RequestUrl'].to_s
65
+ web_request.request_url_root = req_details['RequestUrlRoot'].to_s
66
+ web_request.referral_url = req_details['ReferralUrl'].to_s
67
+ web_request.post_data_raw = req_details['PostDataRaw'].to_s
68
+ log_error.web_request_detail = web_request
69
+ end
70
+ if !ex['ServerVariables'].empty?
71
+ map_server_vars = Google::Protobuf::Map.new(:string, :string)
72
+ ex['ServerVariables'].each { |key, value| map_server_vars["#{key.to_s}"] = value.to_s }
73
+ log_error.server_variables = map_server_vars
74
+ end
75
+
76
+ log.error = log_error
77
+ end
78
+ log
79
+ rescue => exception
80
+ Stackify.internal_log :info, "[ProtobufLogObject] Error: "
81
+ Stackify.internal_log :info, exception
82
+ end
83
+ end
84
+ end
85
+ end
@@ -1,3 +1,3 @@
1
1
  module Stackify
2
- VERSION = '1.0.15'
2
+ VERSION = '1.2.9'
3
3
  end
@@ -3,6 +3,16 @@ module Stackify
3
3
 
4
4
  def initialize name = 'LogsSender worker'
5
5
  super
6
+ case Stackify.configuration.transport
7
+ when Stackify::DEFAULT
8
+ name = 'LogsSender worker'
9
+ when Stackify::UNIX_SOCKET
10
+ name = 'UnixSocketSender worker'
11
+ when Stackify::AGENT_HTTP
12
+ name = 'AgentHTTPSender worker'
13
+ end
14
+ @name = name
15
+ @name += " ##{self.id}"
6
16
  @type = :logs_send
7
17
  end
8
18
 
@@ -22,4 +22,5 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency 'bundler', '~> 1.6'
23
23
  spec.add_development_dependency 'rake', '~> 0'
24
24
  spec.add_runtime_dependency 'faraday', '~> 0.8'
25
+ spec.add_runtime_dependency 'net_http_unix', '~> 0.2'
25
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stackify-api-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.15
4
+ version: 1.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stackify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-16 00:00:00.000000000 Z
11
+ date: 2020-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: net_http_unix
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.2'
55
69
  description: Stackify Logs and Metrics API for Ruby
56
70
  email:
57
71
  - support@stackify.com
@@ -67,11 +81,14 @@ files:
67
81
  - README.md
68
82
  - Rakefile
69
83
  - lib/core_ext/core_ext.rb
70
- - lib/core_ext/fixnum.rb
71
84
  - lib/core_ext/object.rb
72
85
  - lib/generators/stackify/stackify_generator.rb
73
86
  - lib/generators/stackify/templates/stackify.rb
87
+ - lib/proto/stackify-agent.rb
74
88
  - lib/stackify-api-ruby.rb
89
+ - lib/stackify/agent_base_sender.rb
90
+ - lib/stackify/agent_client.rb
91
+ - lib/stackify/agent_http_sender.rb
75
92
  - lib/stackify/authorization/authorizable.rb
76
93
  - lib/stackify/authorization/authorization_client.rb
77
94
  - lib/stackify/engine.rb
@@ -94,10 +111,13 @@ files:
94
111
  - lib/stackify/schedule_delay.rb
95
112
  - lib/stackify/schedule_task.rb
96
113
  - lib/stackify/scheduler.rb
114
+ - lib/stackify/transport_selector.rb
115
+ - lib/stackify/unix_socket_sender.rb
97
116
  - lib/stackify/utils/backtrace.rb
98
117
  - lib/stackify/utils/configuration.rb
99
118
  - lib/stackify/utils/methods.rb
100
119
  - lib/stackify/utils/msg_object.rb
120
+ - lib/stackify/utils/protobuf_log_object.rb
101
121
  - lib/stackify/version.rb
102
122
  - lib/stackify/workers/add_msg_worker.rb
103
123
  - lib/stackify/workers/auth_worker.rb
@@ -1,17 +0,0 @@
1
- class Fixnum
2
- SECONDS_IN_MINUTE = 60
3
- SECONDS_IN_HOUR = 60 * SECONDS_IN_MINUTE
4
- SECONDS_IN_DAY = 24 * SECONDS_IN_HOUR
5
-
6
- def days
7
- self * SECONDS_IN_DAY
8
- end
9
-
10
- def minutes
11
- self * SECONDS_IN_MINUTE
12
- end
13
-
14
- def ago
15
- Time.now - self
16
- end
17
- end