tracer_client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 824a991b553db0aefd11d0f2d83dafffd9435b28
4
+ data.tar.gz: 64248db71c319412b85f8be5e32187c7fe40530e
5
+ SHA512:
6
+ metadata.gz: 2475d3fa342a85d8564869043e85df849fe4cf9f35e8ab96e5b08813293a30e11e6da473ea866eb623c93df8cdadc25d7806ce265a42a8075cc3193c6d25ed26
7
+ data.tar.gz: a718a7a74831aee0f0d6aa13fa1d5d7851f1be9cf91cf91ab09c15a45c5a64e7696c56810fdecd4c06587e3756c7c85b4c116a6ba84f87f5e18e201121fa397d
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /,idea/
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
data/.idea/.name ADDED
@@ -0,0 +1 @@
1
+ tracer_client
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tracer_client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Serge Galanin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # TracerClient
2
+
3
+ Library for logging errors and ActiveRecord object changes to Tracer.
4
+
5
+ Tracer is a web application for accumulating, showing and analyzing of a vital application information.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'tracer_client'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install tracer_client
22
+
23
+ ## Usage
24
+
25
+ Methods for debugging:
26
+
27
+ ```ruby
28
+ Log.debug('Debug message') # log simple message
29
+ Log.debug({a: 2, b: 5}) # log hash values
30
+ Log.debug(any_object) # log any object
31
+ ```
32
+
33
+ Log some info with severity level. Each method requires message text and log tags and accepts optional data.
34
+ ```ruby
35
+ Log.info('Order created', 'order create', id: id)
36
+ Log.warn('Order shipping too long!', 'order shipping', id: id)
37
+ Log.error('Order was not paid', 'order payment', id: id)
38
+ ```
39
+
40
+ Log catched exception
41
+ ```ruby
42
+ begin
43
+ raise 'Some exception'
44
+ rescue => e
45
+ Log.exception(e, 'Unable to send request', 'request', request_data: data)
46
+ end
47
+ ```
48
+
49
+ ## Development
50
+
51
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
52
+
53
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
54
+
55
+ ## Contributing
56
+
57
+ Bug reports and pull requests are welcome on GitHub at https://github.com/galanin/tracer_client.
58
+
59
+
60
+ ## License
61
+
62
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
63
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "tracer_client"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ require 'tracer_client/version'
2
+ require 'tracer_client/server'
3
+ require 'tracer_client/client'
4
+ require 'tracer_client/log'
5
+ require 'tracer_client/changes'
@@ -0,0 +1,177 @@
1
+ module Tracer
2
+ module Changes
3
+
4
+ def self.included(base)
5
+ base.send :extend, ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ def log_record_changes(options = {})
11
+ send :include, InstanceMethods
12
+
13
+ class_attribute :changes_logging_options
14
+ self.changes_logging_options = options.dup
15
+
16
+ %i(ignore skip only).each do |k|
17
+ changes_logging_options[k] =
18
+ [changes_logging_options[k]].flatten.compact.map { |attr| attr.is_a?(Hash) ? attr.stringify_keys : attr.to_s }
19
+ end
20
+
21
+ options_on = Array(options[:on]) # so that a single symbol can be passed in without wrapping it in an `Array`
22
+
23
+ after_create :log_create, :if => :log_changes? if options_on.empty? || options_on.include?(:create)
24
+
25
+ if options_on.empty? || options_on.include?(:update)
26
+ before_update :log_update, :if => :log_changes?
27
+ end
28
+
29
+ after_destroy :log_destroy, :if => :log_changes? if options_on.empty? || options_on.include?(:destroy)
30
+ end
31
+
32
+ end
33
+
34
+
35
+ module InstanceMethods
36
+
37
+ private
38
+
39
+
40
+ def log_create
41
+ Tracer::Client.log_changes(
42
+ item_id: id,
43
+ item_type: self.class.base_class.name,
44
+ event: 'create',
45
+ changes: changes_for_tracing,
46
+ )
47
+ rescue Exception => e
48
+ Log.exception_with_alert(e, 'Ошибка регистрации создания', 'log_changes create',
49
+ item_id: id,
50
+ item_type: self.class.base_class.name)
51
+ end
52
+
53
+
54
+ def log_update
55
+ if changed_notably?
56
+ Tracer::Client.log_changes(
57
+ item_id: id,
58
+ item_type: self.class.base_class.name,
59
+ event: 'update',
60
+ object: object_attrs_for_tracing(item_before_change),
61
+ changes: changes_for_tracing,
62
+ )
63
+ end
64
+ rescue Exception => e
65
+ Log.exception_with_alert(e, 'Ошибка регистрации изменения', 'log_changes update',
66
+ item_id: id,
67
+ item_type: self.class.base_class.name)
68
+ end
69
+
70
+
71
+ def log_destroy
72
+ if persisted?
73
+ Tracer::Client.log_changes(
74
+ item_id: id,
75
+ item_type: self.class.base_class.name,
76
+ event: 'destroy',
77
+ object: object_attrs_for_tracing(item_before_change),
78
+ )
79
+ end
80
+ rescue Exception => e
81
+ Log.exception_with_alert(e, 'Ошибка регистрации удаления', 'log_changes destroy',
82
+ item_id: id,
83
+ item_type: self.class.base_class.name)
84
+ end
85
+
86
+
87
+ def object_attrs_for_tracing(object)
88
+ object_attrs = object.attributes.except(*changes_logging_options[:skip]).with_indifferent_access
89
+
90
+ unwrap_serialized_attributes(object_attrs) do |object_attrs, values, attr|
91
+ object_attrs[attr] = values[attr] if values.key?(attr)
92
+ end
93
+
94
+ object_attrs.as_json
95
+ end
96
+
97
+
98
+ def changes_for_tracing
99
+ changed = self.changes.delete_if do |key, value|
100
+ !notably_changed.include?(key)
101
+ end
102
+
103
+ unwrap_serialized_attributes(changed) do |changed, (a, b), attr|
104
+ if (a.key?(attr) || b.key?(attr)) && a[attr] != b[attr]
105
+ changed[attr] = [a[attr], b[attr]]
106
+ end
107
+ end
108
+
109
+ changed.as_json
110
+ end
111
+
112
+
113
+ # attrs должны быть либо с ключами-символами, либо HashWithIndifferentAccess
114
+ def unwrap_serialized_attributes(attrs)
115
+ stored_attrs = self.class.stored_attributes
116
+ serialized = attrs.extract!(*stored_attrs.keys)
117
+
118
+ serialized.each do |store_attr, value|
119
+ stored_attrs[store_attr.to_sym].each do |attr|
120
+ yield(attrs, value, attr)
121
+ end
122
+ end
123
+ end
124
+
125
+
126
+ def item_before_change
127
+ previous = self.dup
128
+ # `dup` clears timestamps so we add them back.
129
+ all_timestamp_attributes.each do |column|
130
+ previous[column] = send(column) if self.class.column_names.include?(column.to_s) and not send(column).nil?
131
+ end
132
+ previous.tap do |prev|
133
+ prev.id = id # `dup` clears the `id` so we add that back
134
+ changed_attributes.select { |k,v| self.class.column_names.include?(k) }.each { |attr, before| prev[attr] = before }
135
+ end
136
+ end
137
+
138
+
139
+ def changed_notably?
140
+ notably_changed.any?
141
+ end
142
+
143
+
144
+ def notably_changed
145
+ only = self.changes_logging_options[:only].dup
146
+ # remove Hash arguments and then evaluate whether the attributes (the keys of the hash) should also get pushed into the collection
147
+ only.delete_if do |obj|
148
+ obj.is_a?(Hash) && obj.each { |attr, condition| only << attr if condition.respond_to?(:call) && condition.call(self) }
149
+ end
150
+ only.empty? ? changed_and_not_ignored : (changed_and_not_ignored & only)
151
+ end
152
+
153
+ def changed_and_not_ignored
154
+ ignore = self.changes_logging_options[:ignore].dup
155
+ # remove Hash arguments and then evaluate whether the attributes (the keys of the hash) should also get pushed into the collection
156
+ ignore.delete_if do |obj|
157
+ obj.is_a?(Hash) && obj.each { |attr, condition| ignore << attr if condition.respond_to?(:call) && condition.call(self) }
158
+ end
159
+ skip = self.changes_logging_options[:skip]
160
+ changed - ignore - skip
161
+ end
162
+
163
+ end
164
+
165
+
166
+ def log_changes?
167
+ if_condition = self.changes_logging_options[:if]
168
+ unless_condition = self.changes_logging_options[:unless]
169
+ (if_condition.blank? || if_condition.call(self)) && !unless_condition.try(:call, self)
170
+ end
171
+
172
+ end
173
+ end
174
+
175
+ ActiveSupport.on_load(:active_record) do
176
+ include Tracer::Changes
177
+ end
@@ -0,0 +1,122 @@
1
+ module Tracer
2
+ module Client
3
+
4
+ class << self
5
+
6
+ def start_request(current_user, request, params, session)
7
+ Thread.current[:tracer_current_user] = current_user
8
+ Thread.current[:tracer_request] = request
9
+ Thread.current[:tracer_params] = get_params(params)
10
+ end
11
+
12
+
13
+ def end_request
14
+ Thread.current[:tracer_current_user] = nil
15
+ Thread.current[:tracer_request] = nil
16
+ Thread.current[:tracer_params] = nil
17
+ end
18
+
19
+
20
+ def log(notice)
21
+ LogJob.new.async.perform(notice.merge(request_log_data))
22
+ end
23
+
24
+
25
+ def log_changes(changes)
26
+ LogChangesJob.new.async.perform(changes.merge(request_changes_data))
27
+ end
28
+
29
+
30
+ private
31
+
32
+
33
+ def get_params(params)
34
+ @parameter_filter ||= ActionDispatch::Http::ParameterFilter.new Rails.application.config.filter_parameters
35
+ @parameter_filter.filter(params.except(:utf8, :authenticity_token, :_method)).symbolize_keys
36
+ end
37
+
38
+
39
+ def request_data
40
+ data = {context: {}}
41
+
42
+ request = Thread.current[:tracer_request]
43
+ if request
44
+ data[:context].merge!(
45
+ url: request.original_url,
46
+ referer: request.headers['Referer'],
47
+ user_agent: request.headers['User-Agent'],
48
+ ip: request.remote_ip,
49
+ method: request.request_method,
50
+ request_id: request.uuid,
51
+ headers: {
52
+ accept: request.headers['Accept'],
53
+ }
54
+ )
55
+ end
56
+
57
+ cookies = Thread.current[:cookies]
58
+ if cookies && cookies[:administrator_id]
59
+ data[:context][:cookies] = {
60
+ administrator_id: cookies.signed[:administrator_id]
61
+ }
62
+ end
63
+
64
+ current_user = Thread.current[:tracer_current_user]
65
+ if current_user
66
+ data[:context].merge!(
67
+ userType: current_user[:type],
68
+ userId: current_user[:id],
69
+ )
70
+ end
71
+
72
+ params = Thread.current[:tracer_params]
73
+ if params
74
+ data[:context].merge!(
75
+ component: params[:controller],
76
+ action: params[:action],
77
+ )
78
+ data[:params] = params.except(:controller, :action)
79
+ end
80
+
81
+ data[:context].merge!(
82
+ environment: Rails.env,
83
+ rootDirectory: Rails.root,
84
+ )
85
+
86
+ data
87
+ end
88
+
89
+
90
+ def request_log_data
91
+ request_data
92
+ end
93
+
94
+
95
+ def request_changes_data
96
+ request_data
97
+ end
98
+
99
+ end
100
+
101
+
102
+ private
103
+
104
+
105
+ class LogJob
106
+ include SuckerPunch::Job
107
+
108
+ def perform(notice)
109
+ Tracer::Server.log(notice)
110
+ end
111
+ end
112
+
113
+ class LogChangesJob
114
+ include SuckerPunch::Job
115
+
116
+ def perform(changes)
117
+ Tracer::Server.log_changes(changes)
118
+ end
119
+ end
120
+
121
+ end
122
+ end
@@ -0,0 +1,2 @@
1
+ class ApiError < ApplicationError
2
+ end
@@ -0,0 +1,2 @@
1
+ class ApiErrorAlert < ApiErrorLog
2
+ end
@@ -0,0 +1,2 @@
1
+ class ApiErrorLog < ApiError
2
+ end
@@ -0,0 +1,15 @@
1
+ class ApiRequestFailure < ApiError
2
+
3
+ def initialize(subject, tags, response, data = {})
4
+ super(subject, tags, data.merge({
5
+ api_response: {
6
+ status: response.code + ' ' + response.message,
7
+ type: response.content_type,
8
+ length: response.content_length,
9
+ body: response.body.force_encoding('UTF-8'),
10
+
11
+ },
12
+ }))
13
+ end
14
+
15
+ end
@@ -0,0 +1,2 @@
1
+ class ApiRequestFailureAlert < ApiRequestFailureLog
2
+ end
@@ -0,0 +1,2 @@
1
+ class ApiRequestFailureLog < ApiRequestFailure
2
+ end
@@ -0,0 +1,28 @@
1
+ class ApplicationError < StandardError
2
+
3
+ attr_reader :tags, :data
4
+
5
+
6
+ def initialize(subject, tags = '', data = {})
7
+ super(subject)
8
+ @tags = tags
9
+ @data = data
10
+
11
+ puts "#{'-'*10}\n#{@data}\n#{'-'*10}" if Rails.env.development?
12
+
13
+ Log.on_raise(self, caller(2))
14
+ end
15
+
16
+
17
+ # для логирования при бросании и в дефолтном обработчике
18
+ def with_log?
19
+ self.class.name.end_with?('Log', 'Alert')
20
+ end
21
+
22
+
23
+ # для логирования при бросании и в дефолтном обработчике
24
+ def with_alert?
25
+ self.class.name.end_with?('Alert')
26
+ end
27
+
28
+ end
@@ -0,0 +1,2 @@
1
+ class LogicError < ApplicationError
2
+ end
@@ -0,0 +1,2 @@
1
+ class LogicErrorAlert < LogicErrorLog
2
+ end
@@ -0,0 +1,2 @@
1
+ class LogicErrorLog < LogicError
2
+ end
@@ -0,0 +1,153 @@
1
+ require 'config'
2
+
3
+ module Log
4
+
5
+ # error - ошибки
6
+ # crit - исключения
7
+ # emerg - неперехваченные исключения
8
+ SEVERITIES = %i(debug info notice warn error crit alert emerg)
9
+ FACILITIES = %i(request lib auth user product order line_item delivery odkl email direct_mail page exception)
10
+
11
+ ROBOT_UA_FRAGMENTS = /AhrefsBot|bingbot|DotBot|Googlebot|Mail.RU_Bot|MJ12bot|msnbot|SputnikBot|updown_tester|Web-Monitoring|WebMasterAid|YaDirectFetcher|YandexBot/
12
+
13
+
14
+ def self.start_request(current_user, request, params, session, do_log_request)
15
+ Tracer::Client.start_request(current_user, request, params, session)
16
+
17
+ info('HTTP запрос', 'http_request') if do_log_request
18
+
19
+ Thread.current[:request_tags] = %w(robot) if request.headers['User-Agent'] =~ ROBOT_UA_FRAGMENTS
20
+ end
21
+
22
+ def self.end_request
23
+ Thread.current[:request_tags] = nil
24
+ Tracer::Client.end_request
25
+ end
26
+
27
+
28
+ # Можно вызывать в сокращённой форме:
29
+ # Log.debug('Сообщение')
30
+ # Log.debug({a: 2, b: 5})
31
+ # Log.debug(any_object)
32
+ def self.debug(subject = '', tags = '', data = {})
33
+ if Hash === subject
34
+ # передан только хэш с данными
35
+ message(:debug, subject.inspect[0...40], '', subject, caller)
36
+ elsif String === subject
37
+ # передан только subject
38
+ message(:debug, subject, tags, data, caller)
39
+ else
40
+ # переданы некие другие данные
41
+ message(:debug, subject.inspect[0...40], '', {debug: subject}, caller)
42
+ end
43
+ end
44
+
45
+
46
+ %i(info warn error).each do |base_method|
47
+ instance_eval <<-CODE, __FILE__, __LINE__ + 1
48
+ def #{base_method}(subject, tags = '', data = {})
49
+ message(:#{base_method}, subject, tags, data, caller)
50
+ end
51
+
52
+ def #{base_method}_with_alert(subject, tags = '', data = {})
53
+ message(:#{base_method}, subject, tags, data.merge(with_alert: true), caller)
54
+ end
55
+ CODE
56
+ end
57
+
58
+
59
+ def self.exception(exception, subject, tags = '', data = {})
60
+ exception_message(exception, :crit, subject, tags, data, exception.backtrace)
61
+ exception
62
+ end
63
+
64
+
65
+ def self.exception_with_alert(exception, subject, tags = '', data = {})
66
+ exception(exception, subject, tags, data.merge(with_alert: true))
67
+ end
68
+
69
+
70
+ def self.on_raise(exception, backtrace)
71
+ if exception.with_log?
72
+ exception_message(exception, :warn, '', 'raise', {with_alert: exception.with_alert?}, backtrace)
73
+ end
74
+ end
75
+
76
+
77
+ def self.unhandled(exception)
78
+ if exception.with_log? && !exception.logged?
79
+ exception_message(exception, :emerg, '', 'unhandled', {with_alert: exception.with_alert?}, exception.backtrace)
80
+ end
81
+ end
82
+
83
+
84
+ private
85
+
86
+
87
+ def self.message(severity, subject, tags, data, backtrace)
88
+ return unless log?(severity)
89
+
90
+ tags = (Thread.current[:request_tags] || []) + tags.split(' ')
91
+
92
+ data = {data: data} unless Hash === data
93
+
94
+ return if data.key?(:exception) && data[:exception][:class] == 'ActiveRecord::RecordNotFound' && tags == %w(robot)
95
+
96
+ error_hash = {
97
+ severity: severity,
98
+ tags: tags,
99
+ message: subject,
100
+ backtrace: get_backtrace(backtrace).first(10)
101
+ }
102
+
103
+ if data.key?(:exception)
104
+ error_hash[:exception_message] = data[:exception][:message].strip
105
+ error_hash[:type] = data[:exception][:class]
106
+ end
107
+
108
+ Tracer::Client.log(
109
+ errors: [error_hash],
110
+ data: data.except(:exception, :with_alert),
111
+ with_alert: data[:with_alert],
112
+ )
113
+ end
114
+
115
+
116
+ def self.exception_message(exception, severity, subject, tags, data, backtrace)
117
+ tags = (tags + ' ' + exception.tags).strip if exception.respond_to?(:tags)
118
+ data.merge!(exception.data.except(:with_alert)) if exception.respond_to?(:data)
119
+ data.merge!(exception: {
120
+ class: exception.class.name,
121
+ message: exception.message
122
+ })
123
+
124
+ message(severity, subject, tags, data, backtrace)
125
+ exception.mark_logged
126
+ end
127
+
128
+
129
+ def self.log?(severity)
130
+ Settings.log.severity_level.nil? || enabled_severity?(severity, Settings.log.severity_level)
131
+ end
132
+
133
+ def self.enabled_severity?(message_severity, configured_severity)
134
+ message_index = SEVERITIES.index(message_severity)
135
+ configured_index = SEVERITIES.index(configured_severity.to_sym)
136
+ message_index.nil? || configured_index.nil? || message_index >= configured_index
137
+ end
138
+
139
+ def self.get_backtrace(backtrace)
140
+ locations = Rails.backtrace_cleaner.clean(backtrace || [])
141
+
142
+ locations.map do |location|
143
+ if location =~ /\A(.*):(\d+):\s*(?:in `(.*)')\z/
144
+ {
145
+ file: $~[1],
146
+ line: $~[2],
147
+ function: $~[3],
148
+ }
149
+ end
150
+ end.compact
151
+ end
152
+
153
+ end
@@ -0,0 +1,36 @@
1
+ require 'config'
2
+
3
+ module Tracer
4
+ module Server
5
+
6
+ def self.log(notice_hash)
7
+ send("http://#{Settings.tracer.host}:#{Settings.tracer.port}/api/v3/projects/#{Settings.tracer.project}/notices?api_key=#{Settings.tracer.api_key}", notice_hash)
8
+ end
9
+
10
+
11
+ def self.log_changes(changes_hash)
12
+ Rails.logger.debug "Log change: #{changes_hash.inspect}"
13
+ send("http://#{Settings.tracer.host}:#{Settings.tracer.port}/api/v3/projects/#{Settings.tracer.project}/changes?api_key=#{Settings.tracer.api_key}", changes_hash)
14
+ end
15
+
16
+
17
+ private
18
+
19
+
20
+ def self.send(url, data)
21
+ uri = URI.parse(url)
22
+
23
+ Net::HTTP.start(uri.host, uri.port, read_timeout: 20) do |http|
24
+ http.request_post(uri.path + '?' + uri.query, JSON.dump(data), 'Content-Type' => 'text/xml; charset=utf-8') do |response|
25
+ return true if Net::HTTPNoContent === response
26
+ Rails.logger.error "Tracer request url: #{url}"
27
+ Rails.logger.error "Tracer response #{response.inspect}: #{response.body.inspect}"
28
+ end
29
+ end
30
+ rescue Exception => e
31
+ Rails.logger.error "Tracer request url: #{url}"
32
+ Rails.logger.error "Tracer exception #{e.inspect}: #{e.message}"
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module TracerClient
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tracer_client/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'tracer_client'
8
+ spec.version = TracerClient::VERSION
9
+ spec.authors = ['Serge Galanin']
10
+ spec.email = ['s.galanin@gmail.com']
11
+
12
+ spec.summary = %q{Tracer API}
13
+ spec.description = %q{Log errors and objects changes to Tracer.}
14
+ spec.homepage = "https://github.com/galanin/tracer_client"
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'config', '~> 1.0'
23
+ spec.add_dependency 'rails', '~> 4.2'
24
+ spec.add_dependency 'sucker_punch', '~> 1.5'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.10'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tracer_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Serge Galanin
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-08-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: config
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sucker_punch
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.5'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.10'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.10'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ description: Log errors and objects changes to Tracer.
84
+ email:
85
+ - s.galanin@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".idea/.name"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - bin/console
97
+ - bin/setup
98
+ - lib/tracer_client.rb
99
+ - lib/tracer_client/changes.rb
100
+ - lib/tracer_client/client.rb
101
+ - lib/tracer_client/errors/api_error.rb
102
+ - lib/tracer_client/errors/api_error_alert.rb
103
+ - lib/tracer_client/errors/api_error_log.rb
104
+ - lib/tracer_client/errors/api_request_failure.rb
105
+ - lib/tracer_client/errors/api_request_failure_alert.rb
106
+ - lib/tracer_client/errors/api_request_failure_log.rb
107
+ - lib/tracer_client/errors/application_error.rb
108
+ - lib/tracer_client/errors/logic_error.rb
109
+ - lib/tracer_client/errors/logic_error_alert.rb
110
+ - lib/tracer_client/errors/logic_error_log.rb
111
+ - lib/tracer_client/log.rb
112
+ - lib/tracer_client/server.rb
113
+ - lib/tracer_client/version.rb
114
+ - tracer_client.gemspec
115
+ homepage: https://github.com/galanin/tracer_client
116
+ licenses:
117
+ - MIT
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 2.4.8
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: Tracer API
139
+ test_files: []