errplane 0.6.10 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -40,19 +40,37 @@ module Errplane
40
40
  @queue ||= MaxQueue.new(configuration.queue_maximum_depth)
41
41
  end
42
42
 
43
- def report(name, params = {}, async = true)
43
+ def report(name, params = {}, udp = false)
44
44
  unless configuration.ignored_reports.find{ |msg| /#{msg}/ =~ name }
45
- data = {
46
- :name => name.gsub(/\s+/, "_"),
47
- :timestamp => "now"
48
- }.merge(params)
49
-
50
- if async
51
- Errplane.queue.push(data)
52
- else
53
- Errplane.api.post(Errplane.process_line(data))
54
- end
45
+ data = generate_data(name, params)
46
+ udp ? Errplane.api.send(data) : Errplane.queue.push(data)
47
+ end
48
+ end
49
+
50
+ def rollup(name, params = {})
51
+ Errplane.api.send generate_data(name, params), "t"
52
+ end
53
+
54
+ def count(name, params = {})
55
+ Errplane.api.send generate_data(name, params), "c"
56
+ end
57
+
58
+ def generate_data(name, params)
59
+ point = {:v => params[:value] || 1}
60
+ point[:t] = params[:timestamp] unless params[:timestamp].nil?
61
+
62
+ if context = params[:context]
63
+ point[:c] = params[:context].is_a?(String) ? params[:context] : params[:context].to_json
64
+ end
65
+
66
+ if dimensions = params[:dimensions]
67
+ point[:d] = Hash[params[:dimensions].map {|k,v| [k.to_s, v.to_s]}]
55
68
  end
69
+
70
+ {
71
+ :n => name.gsub(/\s+/, "_"),
72
+ :p => [point]
73
+ }
56
74
  end
57
75
 
58
76
  def report_deployment(context = nil, async = false)
@@ -84,35 +102,35 @@ module Errplane
84
102
  yield_value
85
103
  end
86
104
 
87
- def transmit_unless_ignorable(e, env = {})
88
- transmit(e, env) unless ignorable_exception?(e)
105
+ def report_exception_unless_ignorable(e, env = {})
106
+ report_exception(e, env) unless ignorable_exception?(e)
89
107
  end
108
+ alias_method :transmit_unless_ignorable, :report_exception_unless_ignorable
90
109
 
91
- def transmit(e, env = {})
110
+ def report_exception(e, env = {})
92
111
  begin
93
112
  env = errplane_request_data if env.empty? && defined? errplane_request_data
94
113
  exception_presenter = ExceptionPresenter.new(e, env)
95
114
  log :info, "Exception: #{exception_presenter.to_json[0..512]}..."
96
115
 
97
116
  Errplane.queue.push({
98
- :name => exception_presenter.time_series_name,
99
- :context => exception_presenter
117
+ :n => "exceptions",
118
+ :p => [{
119
+ :v => 1,
120
+ :c => exception_presenter.context.to_json,
121
+ :d => exception_presenter.dimensions
122
+ }]
100
123
  })
101
124
  rescue => e
102
125
  log :info, "[Errplane] Something went terribly wrong. Exception failed to take off! #{e.class}: #{e.message}"
103
126
  end
104
127
  end
128
+ alias_method :transmit, :report_exception
105
129
 
106
130
  def current_timestamp
107
131
  Time.now.utc.to_i
108
132
  end
109
133
 
110
- def process_line(line)
111
- data = "#{line[:name]} #{line[:value] || 1} #{line[:timestamp] || "now"}"
112
- data = "#{data} #{Base64.strict_encode64(line[:context].to_json)}" if line[:context]
113
- data
114
- end
115
-
116
134
  def ignorable_exception?(e)
117
135
  configuration.ignore_current_environment? ||
118
136
  !!configuration.ignored_exception_messages.find{ |msg| /.*#{msg}.*/ =~ e.message } ||
@@ -4,6 +4,10 @@ module Errplane
4
4
 
5
5
  attr_reader :last_response
6
6
 
7
+ HTTPS_HOST = "w.apiv3.errplane.com"
8
+ UDP_HOST = "udp.apiv3.errplane.com"
9
+ UDP_PORT = 8126
10
+
7
11
  POST_RETRIES = 5
8
12
  READ_TIMEOUT = 3
9
13
  OPEN_TIMEOUT = 3
@@ -23,7 +27,7 @@ module Errplane
23
27
  log :debug, "POSTing to #{url}"
24
28
 
25
29
  response = begin
26
- https.post(url, data)
30
+ https.post(url, data.to_json)
27
31
  rescue *HTTP_ERRORS => e
28
32
  log :error, "HTTP error contacting API! #{e.class}: #{e.message}"
29
33
  retry_count -= 1
@@ -44,17 +48,31 @@ module Errplane
44
48
  @last_response = response
45
49
  end
46
50
 
51
+ def send(data, operator="r")
52
+ udp = UDPSocket.new
53
+
54
+ packet = {
55
+ :d => Errplane.configuration.database_name,
56
+ :a => Errplane.configuration.api_key.to_s,
57
+ :o => operator,
58
+ :w => [data]
59
+ }
60
+
61
+ log :debug, "Sending UDP Packet: #{packet.to_json}"
62
+
63
+ udp.send packet.to_json, 0, UDP_HOST, UDP_PORT
64
+ end
65
+
47
66
  private
48
67
  def url
49
68
  "/databases/" \
50
- + Errplane.configuration.application_id.to_s \
51
- + Errplane.configuration.environment.to_s \
69
+ + Errplane.configuration.database_name \
52
70
  + "/points?api_key=" \
53
71
  + Errplane.configuration.api_key.to_s
54
72
  end
55
73
 
56
74
  def initialize_secure_connection
57
- connection = Net::HTTP.new("apiv2.errplane.com", 443)
75
+ connection = Net::HTTP.new(HTTPS_HOST, 443)
58
76
  connection.use_ssl = true
59
77
  connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
60
78
  connection.read_timeout = READ_TIMEOUT
@@ -112,6 +112,10 @@ module Errplane
112
112
  @custom_exception_data_handler.call(black_box) if @custom_exception_data_handler
113
113
  end
114
114
 
115
+ def database_name
116
+ @application_id.to_s + @environment.to_s
117
+ end
118
+
115
119
  private
116
120
  def initialize_http_connection
117
121
  Net::HTTP.new(@app_host, "80")
@@ -31,8 +31,8 @@ module Errplane
31
31
  @environment_variables = ENV.to_hash || {}
32
32
  end
33
33
 
34
- def to_json
35
- payload = {
34
+ def context
35
+ c = {
36
36
  :time => Time.now.utc.to_i,
37
37
  :application_name => Errplane.configuration.application_name,
38
38
  :application_root => Errplane.configuration.application_root,
@@ -40,41 +40,29 @@ module Errplane
40
40
  :framework_version => Errplane.configuration.framework_version,
41
41
  :message => @exception.message,
42
42
  :backtrace => @backtrace,
43
- :exception_class => @exception.class.to_s,
44
43
  :language => "Ruby",
45
44
  :language_version => "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}",
46
45
  :reporter => reporter,
47
- :hostname => Socket.gethostname,
48
46
  :custom_data => @custom_data
49
47
  }
50
48
 
51
- payload[:environment_variables] = @environment_variables.reject do |k,v|
49
+ c[:environment_variables] = @environment_variables.reject do |k,v|
52
50
  Errplane.configuration.environment_variable_filters.any? { |filter| k =~ filter }
53
51
  end
54
52
 
55
53
  Errplane.configuration.add_custom_exception_data(self)
56
54
 
57
- payload[:request_data] = request_data if @controller || @action || !@params.blank?
58
- payload[:hash] = calculate_hash
59
- payload.to_json
60
- end
61
-
62
- def calculate_hash
63
- if hash
64
- hash
65
- elsif Errplane.configuration.aggregated_exception_classes.include?(@exception.class.to_s)
66
- Digest::SHA1.hexdigest(@exception.class.to_s)
67
- else
68
- Digest::SHA1.hexdigest(@exception.class.to_s + @backtrace.first.to_s)
69
- end
70
- end
71
-
72
- def time_series_name
73
- "exceptions/" + calculate_hash
55
+ c[:request_data] = request_data if @controller || @action || !@params.blank?
56
+ c
74
57
  end
75
58
 
76
- def context
77
- Base64.strict_encode64(to_json)
59
+ def dimensions
60
+ d = {
61
+ :Class => @exception.class.to_s,
62
+ :class => @exception.class.to_s,
63
+ :method => "#{@controller}##{@action}",
64
+ :server => Socket.gethostname
65
+ }
78
66
  end
79
67
 
80
68
  def reporter
@@ -1,3 +1,3 @@
1
1
  module Errplane
2
- VERSION = "0.6.10"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -5,22 +5,18 @@ require "base64"
5
5
 
6
6
  module Errplane
7
7
  class Worker
8
- MAX_POST_LINES = 200
8
+ MAX_POST_POINTS = 200
9
9
  MAX_TIME_SERIES_NAME_LENGTH = 255
10
10
 
11
11
  class << self
12
12
  include Errplane::Logger
13
13
 
14
- def indent_lines(lines, num)
15
- lines.split("\n").map {|line| (" " * num) + line[0..64]}.join("\n")
16
- end
17
-
18
14
  def post_data(data)
19
15
  if Errplane.configuration.ignore_current_environment?
20
16
  log :debug, "Current environment is ignored, skipping POST."
21
17
  return false
22
18
  else
23
- log :debug, "POSTing data:\n#{indent_lines(data, 13)}"
19
+ log :debug, "POSTing data:\n#{data}"
24
20
  begin
25
21
  Errplane.api.post(data)
26
22
  rescue => e
@@ -63,23 +59,23 @@ module Errplane
63
59
  begin
64
60
  data = []
65
61
 
66
- while data.size < MAX_POST_LINES && !Errplane.queue.empty?
67
- n = Errplane.queue.pop(true) rescue next;
68
- log :debug, "Found data in the queue! (#{n[:name]})"
62
+ while data.size < MAX_POST_POINTS && !Errplane.queue.empty?
63
+ p = Errplane.queue.pop(true) rescue next;
64
+ log :debug, "Found data in the queue! (#{p[:n]})"
69
65
 
70
66
  begin
71
- if n[:name].split("|").any?{|x| x.length > MAX_TIME_SERIES_NAME_LENGTH}
72
- log :error, "Time series name too long! Discarding data for: #{n[:name]}"
67
+ if p[:n].size > MAX_TIME_SERIES_NAME_LENGTH
68
+ log :error, "Time series name too long! Discarding data for: #{p[:n]}"
73
69
  else
74
- data << Errplane.process_line(n)
70
+ data.push p
75
71
  end
76
72
  rescue => e
77
- log :info, "Instrumentation Error! #{e.inspect}"
73
+ log :info, "Instrumentation Error! #{e.inspect} #{e.backtrace.first}"
78
74
  end
79
75
  end
80
76
 
81
- post_data(data.join("\n")) unless data.empty?
82
- end while Errplane.queue.length > MAX_POST_LINES
77
+ post_data(data) unless data.empty?
78
+ end while Errplane.queue.length > MAX_POST_POINTS
83
79
  end
84
80
  end
85
81
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: errplane
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.10
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-15 00:00:00.000000000 Z
12
+ date: 2013-07-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &70115497526500 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70115497526500
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: bundler
27
- requirement: &70115497525700 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: 1.0.0
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70115497525700
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.0
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: fakeweb
38
- requirement: &70115497524960 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70115497524960
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: guard
49
- requirement: &70115497524280 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70115497524280
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: guard-rspec
60
- requirement: &70115497523800 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: '0'
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *70115497523800
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: rake
71
- requirement: &70115497523300 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ! '>='
@@ -76,10 +101,15 @@ dependencies:
76
101
  version: '0'
77
102
  type: :development
78
103
  prerelease: false
79
- version_requirements: *70115497523300
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
80
110
  - !ruby/object:Gem::Dependency
81
111
  name: rdoc
82
- requirement: &70115497522800 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
83
113
  none: false
84
114
  requirements:
85
115
  - - ! '>='
@@ -87,10 +117,15 @@ dependencies:
87
117
  version: '0'
88
118
  type: :development
89
119
  prerelease: false
90
- version_requirements: *70115497522800
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
91
126
  - !ruby/object:Gem::Dependency
92
127
  name: rspec
93
- requirement: &70115497522320 !ruby/object:Gem::Requirement
128
+ requirement: !ruby/object:Gem::Requirement
94
129
  none: false
95
130
  requirements:
96
131
  - - ! '>='
@@ -98,10 +133,15 @@ dependencies:
98
133
  version: '0'
99
134
  type: :development
100
135
  prerelease: false
101
- version_requirements: *70115497522320
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
102
142
  - !ruby/object:Gem::Dependency
103
143
  name: tzinfo
104
- requirement: &70115497521840 !ruby/object:Gem::Requirement
144
+ requirement: !ruby/object:Gem::Requirement
105
145
  none: false
106
146
  requirements:
107
147
  - - ! '>='
@@ -109,7 +149,12 @@ dependencies:
109
149
  version: '0'
110
150
  type: :development
111
151
  prerelease: false
112
- version_requirements: *70115497521840
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
113
158
  description: This gem provides implements instrumentation with Errplane for Rails
114
159
  2.3.x and 3.x applications.
115
160
  email:
@@ -204,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
204
249
  version: '0'
205
250
  requirements: []
206
251
  rubyforge_project: errplane
207
- rubygems_version: 1.8.15
252
+ rubygems_version: 1.8.24
208
253
  signing_key:
209
254
  specification_version: 3
210
255
  summary: Rails-based instrumentation library for Errplane.