genki-newrelic_rpm 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. data/CHANGELOG +316 -0
  2. data/LICENSE +37 -0
  3. data/Manifest +156 -0
  4. data/README.md +138 -0
  5. data/Rakefile +22 -0
  6. data/bin/mongrel_rpm +33 -0
  7. data/bin/newrelic_cmd +4 -0
  8. data/cert/cacert.pem +34 -0
  9. data/genki-newrelic_rpm.gemspec +32 -0
  10. data/init.rb +38 -0
  11. data/install.rb +37 -0
  12. data/lib/new_relic/agent.rb +280 -0
  13. data/lib/new_relic/agent/agent.rb +627 -0
  14. data/lib/new_relic/agent/chained_call.rb +13 -0
  15. data/lib/new_relic/agent/collection_helper.rb +61 -0
  16. data/lib/new_relic/agent/error_collector.rb +125 -0
  17. data/lib/new_relic/agent/instrumentation/active_merchant.rb +18 -0
  18. data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +83 -0
  19. data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -0
  20. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +368 -0
  21. data/lib/new_relic/agent/instrumentation/data_mapper.rb +90 -0
  22. data/lib/new_relic/agent/instrumentation/dispatcher_instrumentation.rb +132 -0
  23. data/lib/new_relic/agent/instrumentation/memcache.rb +21 -0
  24. data/lib/new_relic/agent/instrumentation/merb/controller.rb +26 -0
  25. data/lib/new_relic/agent/instrumentation/merb/dispatcher.rb +13 -0
  26. data/lib/new_relic/agent/instrumentation/merb/errors.rb +8 -0
  27. data/lib/new_relic/agent/instrumentation/net.rb +12 -0
  28. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +20 -0
  29. data/lib/new_relic/agent/instrumentation/rack.rb +77 -0
  30. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +59 -0
  31. data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +27 -0
  32. data/lib/new_relic/agent/instrumentation/rails/dispatcher.rb +38 -0
  33. data/lib/new_relic/agent/instrumentation/rails/errors.rb +27 -0
  34. data/lib/new_relic/agent/instrumentation/sinatra.rb +39 -0
  35. data/lib/new_relic/agent/method_tracer.rb +277 -0
  36. data/lib/new_relic/agent/patch_const_missing.rb +125 -0
  37. data/lib/new_relic/agent/sampler.rb +12 -0
  38. data/lib/new_relic/agent/samplers/cpu_sampler.rb +49 -0
  39. data/lib/new_relic/agent/samplers/memory_sampler.rb +137 -0
  40. data/lib/new_relic/agent/samplers/mongrel_sampler.rb +22 -0
  41. data/lib/new_relic/agent/shim_agent.rb +21 -0
  42. data/lib/new_relic/agent/stats_engine.rb +24 -0
  43. data/lib/new_relic/agent/stats_engine/metric_stats.rb +111 -0
  44. data/lib/new_relic/agent/stats_engine/samplers.rb +71 -0
  45. data/lib/new_relic/agent/stats_engine/transactions.rb +155 -0
  46. data/lib/new_relic/agent/transaction_sampler.rb +319 -0
  47. data/lib/new_relic/agent/worker_loop.rb +118 -0
  48. data/lib/new_relic/commands/deployments.rb +145 -0
  49. data/lib/new_relic/commands/new_relic_commands.rb +30 -0
  50. data/lib/new_relic/control.rb +436 -0
  51. data/lib/new_relic/control/external.rb +13 -0
  52. data/lib/new_relic/control/merb.rb +22 -0
  53. data/lib/new_relic/control/rails.rb +143 -0
  54. data/lib/new_relic/control/ruby.rb +34 -0
  55. data/lib/new_relic/control/sinatra.rb +14 -0
  56. data/lib/new_relic/histogram.rb +89 -0
  57. data/lib/new_relic/local_environment.rb +285 -0
  58. data/lib/new_relic/merbtasks.rb +6 -0
  59. data/lib/new_relic/metric_data.rb +44 -0
  60. data/lib/new_relic/metric_parser.rb +120 -0
  61. data/lib/new_relic/metric_parser/action_mailer.rb +9 -0
  62. data/lib/new_relic/metric_parser/active_merchant.rb +26 -0
  63. data/lib/new_relic/metric_parser/active_record.rb +25 -0
  64. data/lib/new_relic/metric_parser/controller.rb +54 -0
  65. data/lib/new_relic/metric_parser/controller_cpu.rb +38 -0
  66. data/lib/new_relic/metric_parser/errors.rb +6 -0
  67. data/lib/new_relic/metric_parser/external.rb +50 -0
  68. data/lib/new_relic/metric_parser/mem_cache.rb +12 -0
  69. data/lib/new_relic/metric_parser/view.rb +61 -0
  70. data/lib/new_relic/metric_parser/web_frontend.rb +14 -0
  71. data/lib/new_relic/metric_parser/web_service.rb +9 -0
  72. data/lib/new_relic/metric_spec.rb +52 -0
  73. data/lib/new_relic/metrics.rb +7 -0
  74. data/lib/new_relic/noticed_error.rb +25 -0
  75. data/lib/new_relic/rack/metric_app.rb +56 -0
  76. data/lib/new_relic/rack/newrelic.ru +25 -0
  77. data/lib/new_relic/rack/newrelic.yml +25 -0
  78. data/lib/new_relic/rack_app.rb +5 -0
  79. data/lib/new_relic/recipes.rb +82 -0
  80. data/lib/new_relic/stats.rb +360 -0
  81. data/lib/new_relic/transaction_analysis.rb +121 -0
  82. data/lib/new_relic/transaction_sample.rb +583 -0
  83. data/lib/new_relic/version.rb +54 -0
  84. data/lib/new_relic_api.rb +315 -0
  85. data/lib/newrelic_rpm.rb +40 -0
  86. data/lib/tasks/all.rb +4 -0
  87. data/lib/tasks/install.rake +7 -0
  88. data/lib/tasks/tests.rake +13 -0
  89. data/newrelic.yml +214 -0
  90. data/recipes/newrelic.rb +6 -0
  91. data/test/active_record_fixtures.rb +55 -0
  92. data/test/config/newrelic.yml +46 -0
  93. data/test/config/test_control.rb +39 -0
  94. data/test/new_relic/agent/active_record_instrumentation_test.rb +234 -0
  95. data/test/new_relic/agent/agent_controller_test.rb +107 -0
  96. data/test/new_relic/agent/agent_test.rb +117 -0
  97. data/test/new_relic/agent/agent_test_controller.rb +44 -0
  98. data/test/new_relic/agent/classloader_patch_test.rb +56 -0
  99. data/test/new_relic/agent/collection_helper_test.rb +118 -0
  100. data/test/new_relic/agent/dispatcher_instrumentation_test.rb +76 -0
  101. data/test/new_relic/agent/error_collector_test.rb +155 -0
  102. data/test/new_relic/agent/method_tracer_test.rb +335 -0
  103. data/test/new_relic/agent/metric_data_test.rb +56 -0
  104. data/test/new_relic/agent/mock_ar_connection.rb +40 -0
  105. data/test/new_relic/agent/mock_scope_listener.rb +23 -0
  106. data/test/new_relic/agent/net_instrumentation_test.rb +51 -0
  107. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +79 -0
  108. data/test/new_relic/agent/stats_engine/samplers_test.rb +78 -0
  109. data/test/new_relic/agent/stats_engine/stats_engine_test.rb +177 -0
  110. data/test/new_relic/agent/task_instrumentation_test.rb +67 -0
  111. data/test/new_relic/agent/testable_agent.rb +13 -0
  112. data/test/new_relic/agent/transaction_sample_builder_test.rb +195 -0
  113. data/test/new_relic/agent/transaction_sample_test.rb +146 -0
  114. data/test/new_relic/agent/transaction_sampler_test.rb +387 -0
  115. data/test/new_relic/agent/worker_loop_test.rb +103 -0
  116. data/test/new_relic/control_test.rb +94 -0
  117. data/test/new_relic/deployments_api_test.rb +68 -0
  118. data/test/new_relic/environment_test.rb +75 -0
  119. data/test/new_relic/metric_parser_test.rb +172 -0
  120. data/test/new_relic/metric_spec_test.rb +177 -0
  121. data/test/new_relic/shim_agent_test.rb +9 -0
  122. data/test/new_relic/stats_test.rb +291 -0
  123. data/test/new_relic/version_number_test.rb +74 -0
  124. data/test/test_helper.rb +38 -0
  125. data/test/ui/newrelic_controller_test.rb +14 -0
  126. data/test/ui/newrelic_helper_test.rb +53 -0
  127. data/ui/controllers/newrelic_controller.rb +214 -0
  128. data/ui/helpers/google_pie_chart.rb +55 -0
  129. data/ui/helpers/newrelic_helper.rb +314 -0
  130. data/ui/views/layouts/newrelic_default.rhtml +47 -0
  131. data/ui/views/newrelic/_explain_plans.rhtml +27 -0
  132. data/ui/views/newrelic/_sample.rhtml +15 -0
  133. data/ui/views/newrelic/_segment.rhtml +28 -0
  134. data/ui/views/newrelic/_segment_limit_message.rhtml +1 -0
  135. data/ui/views/newrelic/_segment_row.rhtml +14 -0
  136. data/ui/views/newrelic/_show_sample_detail.rhtml +24 -0
  137. data/ui/views/newrelic/_show_sample_sql.rhtml +20 -0
  138. data/ui/views/newrelic/_show_sample_summary.rhtml +3 -0
  139. data/ui/views/newrelic/_sql_row.rhtml +11 -0
  140. data/ui/views/newrelic/_stack_trace.rhtml +30 -0
  141. data/ui/views/newrelic/_table.rhtml +12 -0
  142. data/ui/views/newrelic/explain_sql.rhtml +42 -0
  143. data/ui/views/newrelic/images/arrow-close.png +0 -0
  144. data/ui/views/newrelic/images/arrow-open.png +0 -0
  145. data/ui/views/newrelic/images/blue_bar.gif +0 -0
  146. data/ui/views/newrelic/images/file_icon.png +0 -0
  147. data/ui/views/newrelic/images/gray_bar.gif +0 -0
  148. data/ui/views/newrelic/images/new_relic_rpm_desktop.gif +0 -0
  149. data/ui/views/newrelic/images/textmate.png +0 -0
  150. data/ui/views/newrelic/index.rhtml +45 -0
  151. data/ui/views/newrelic/javascript/prototype-scriptaculous.js +7288 -0
  152. data/ui/views/newrelic/javascript/transaction_sample.js +107 -0
  153. data/ui/views/newrelic/sample_not_found.rhtml +2 -0
  154. data/ui/views/newrelic/show_sample.rhtml +77 -0
  155. data/ui/views/newrelic/show_source.rhtml +3 -0
  156. data/ui/views/newrelic/stylesheets/style.css +433 -0
  157. data/ui/views/newrelic/threads.rhtml +52 -0
  158. metadata +327 -0
@@ -0,0 +1,6 @@
1
+ namespace :newrelic do
2
+ desc "Install the developer mode newrelic.yml file"
3
+ task :default do
4
+ load File.expand_path(File.join(__FILE__,"..","..","install.rb"))
5
+ end
6
+ end
@@ -0,0 +1,44 @@
1
+ module NewRelic
2
+ class MetricData
3
+ attr_accessor :metric_spec
4
+ attr_accessor :metric_id
5
+ attr_accessor :stats
6
+
7
+ def initialize(metric_spec, stats, metric_id)
8
+ @metric_spec = metric_spec
9
+ self.stats = stats
10
+ self.metric_id = metric_id
11
+ end
12
+
13
+ def eql?(o)
14
+ (metric_spec.eql? o.metric_spec) && (stats.eql? o.stats)
15
+ end
16
+
17
+ def original_spec
18
+ @original_spec || @metric_spec
19
+ end
20
+ def metric_spec
21
+ @metric_spec
22
+ end
23
+ def metric_spec= new_spec
24
+ @original_spec = @metric_spec if @metric_spec
25
+ @metric_spec = new_spec
26
+ end
27
+
28
+ def hash
29
+ metric_spec.hash ^ stats.hash
30
+ end
31
+
32
+ def to_json(*a)
33
+ {'metric_spec' => metric_spec,
34
+ 'stats' => stats,
35
+ 'metric_id' => metric_id
36
+ }.to_json(*a)
37
+ end
38
+
39
+ def to_s
40
+ "#{metric_spec.name}(#{metric_spec.scope}): #{stats}" if metric_spec
41
+ "#{metric_id}: #{stats}" if metric_spec.nil?
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,120 @@
1
+ module NewRelic
2
+ # Metric parsing logic mixin. Given a metric name (attribute called "name"), provide a set of accessors
3
+ # that enable inspection of the metric. A metric has 2 or more segments, each separated
4
+ # by the '/' character. The metric's category is specified by its first segment. Following
5
+ # are the set of categories currently supported by NewRelic's default metric set:
6
+ #
7
+ # * Controller
8
+ # * ActiveRecord
9
+ # * Rails
10
+ # * WebService
11
+ # * View
12
+ # * Database
13
+ # * Custom
14
+ #
15
+ # Based on the category of the metric, specific parsing logic is defined in the source files
16
+ # countained in the "metric_parsers" sub directory local to this file.
17
+ #
18
+
19
+ class MetricParser
20
+
21
+ SEPARATOR = '/' unless defined? SEPARATOR
22
+ attr_reader :name
23
+
24
+ # Load in the parsers classes in the plugin:
25
+ Dir[File.join(File.dirname(__FILE__), "metric_parser", "*.rb")].each { | file | require file }
26
+
27
+ # return a string that is parsable via the Metric parser APIs
28
+ def self.for_metric_named(s)
29
+ category = (s =~ /^([^\/]*)/) && $1
30
+ parser_class = self
31
+ if category
32
+ parser_class = NewRelic::MetricParser.const_get(category) if (NewRelic::MetricParser.const_defined?(category) rescue nil)
33
+ end
34
+ parser_class.new s
35
+ end
36
+
37
+ def self.parse(s)
38
+ for_metric_named(s)
39
+ end
40
+
41
+ def method_missing(method_name, *args)
42
+ return false if method_name.to_s =~ /^is_.*\?/
43
+ super
44
+ end
45
+ # The short name for the metric is defined as all of the segments
46
+ # of the metric name except for its first (its domain).
47
+ def short_name
48
+ if segments.empty?
49
+ ''
50
+ elsif segments.length == 1
51
+ segments[0]
52
+ else
53
+ segments[1..-1].join(SEPARATOR)
54
+ end
55
+ end
56
+
57
+ def pie_chart_label
58
+ developer_name
59
+ end
60
+
61
+ def developer_name
62
+ short_name
63
+ end
64
+
65
+ def tooltip_name
66
+ short_name
67
+ end
68
+
69
+ def apdex_metric_path
70
+ "Apdex/#{segments[1..-1].join('/')}"
71
+ end
72
+
73
+ # A short name for legends in the graphs
74
+ def legend_name
75
+ short_name
76
+ end
77
+
78
+ # Return the name of another metric if the current
79
+ # metric is really add-on data for another metric.
80
+ def base_metric_name
81
+ nil
82
+ end
83
+
84
+ def category
85
+ segments[0]
86
+ end
87
+
88
+ def segments
89
+ return [] if !name
90
+ @segments ||= name.split(SEPARATOR).freeze
91
+ end
92
+
93
+ # --
94
+ # These accessors are used to allow chart to use a specific segment in the metric
95
+ # name for label construction as a zero-arg accessor
96
+ # ++
97
+ def segment_0; segments[0]; end
98
+ def segment_1; segments[1]; end
99
+ def segment_2; segments[2]; end
100
+ def segment_3; segments[3]; end
101
+ def segment_4; segments[4]; end
102
+ def last_segment; segments.last; end
103
+
104
+ # This is the suffix used for call rate or throughput. By default, it's cpm
105
+ # but things like controller actions will override to use something like 'rpm'
106
+ # for requests per minute
107
+ def call_rate_suffix
108
+ 'cpm'
109
+ end
110
+
111
+ def url
112
+ ''
113
+ end
114
+
115
+ def initialize(name)
116
+ @name = name
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,9 @@
1
+ class NewRelic::MetricParser::ActionMailer < NewRelic::MetricParser
2
+
3
+ def is_action_mailer?; true; end
4
+
5
+ def short_name
6
+ "ActionMailer - #{segments[1]}"
7
+ end
8
+
9
+ end
@@ -0,0 +1,26 @@
1
+ class NewRelic::MetricParser::ActiveMerchant < NewRelic::MetricParser
2
+
3
+ def is_active_merchant?; true; end
4
+
5
+ def is_active_merchant_gateway?
6
+ segments[1] == 'gateway'
7
+ end
8
+
9
+ def is_active_merchant_operation?
10
+ segments[1] == 'operation'
11
+ end
12
+
13
+ def gateway_name
14
+ # ends in "Gateway" - trim that off
15
+ segments[2][0..-8].titleize
16
+ end
17
+
18
+ def operation_name
19
+ segments[2]
20
+ end
21
+
22
+ def short_name
23
+ segments[2]
24
+ end
25
+
26
+ end
@@ -0,0 +1,25 @@
1
+ class NewRelic::MetricParser::ActiveRecord < NewRelic::MetricParser
2
+ def is_active_record? ; true; end
3
+
4
+ def model_class
5
+ return segments[1]
6
+ end
7
+
8
+ def legend_name
9
+ if name == 'ActiveRecord/all'
10
+ 'Database'
11
+ else
12
+ super
13
+ end
14
+ end
15
+ def tooltip_name
16
+ if name == 'ActiveRecord/all'
17
+ 'all SQL execution'
18
+ else
19
+ super
20
+ end
21
+ end
22
+ def developer_name
23
+ "#{model_class}##{segments.last}"
24
+ end
25
+ end
@@ -0,0 +1,54 @@
1
+ class NewRelic::MetricParser::Controller < NewRelic::MetricParser
2
+
3
+ def is_controller?
4
+ true
5
+ end
6
+
7
+ # If the controller name segments look like a file path, convert it to the controller
8
+ # class name. If it begins with a capital letter, assume it's already a class name
9
+ def controller_name
10
+ path = segments[1..-2].join('/')
11
+ path < 'a' ? path : path.camelize+"Controller"
12
+ end
13
+
14
+ def action_name
15
+ if segments[-1] =~ /^\(other\)$/
16
+ '(template only)'
17
+ else
18
+ segments[-1]
19
+ end
20
+ end
21
+
22
+ def developer_name
23
+ "#{controller_name}##{action_name}"
24
+ end
25
+
26
+ # return the cpu measuring equivalent. It may be nil since this metric was not
27
+ # present in earlier versions of the agent.
28
+ def cpu_metric
29
+ Metric.lookup((["ControllerCPU"] + segments[1..-1]).join('/'), :create => false)
30
+ end
31
+
32
+ def short_name
33
+ # standard controller actions
34
+ if segments.length > 1
35
+ url
36
+ else
37
+ 'All Controller Actions'
38
+ end
39
+ end
40
+
41
+ def url
42
+ '/' + segments[1..-1].join('/')
43
+ end
44
+
45
+ # this is used to match transaction traces to controller actions.
46
+ # TT's don't have a preceding slash :P
47
+ def tt_path
48
+ segments[1..-1].join('/')
49
+ end
50
+
51
+ def call_rate_suffix
52
+ 'rpm'
53
+ end
54
+ end
@@ -0,0 +1,38 @@
1
+ class NewRelic::MetricParser::ControllerCPU < NewRelic::MetricParser
2
+
3
+ def is_controller_cpu?; true; end
4
+
5
+ def controller_name
6
+ segments[1..-2].join('/').camelize+"Controller"
7
+ end
8
+
9
+ def action_name
10
+ segments[-1]
11
+ end
12
+
13
+ def developer_name
14
+ "#{controller_name}##{action_name}"
15
+ end
16
+
17
+ def base_metric_name
18
+ "Controller/" + segments[1..-1].join('/')
19
+ end
20
+
21
+ def short_name
22
+ # standard controller actions
23
+ if segments.length > 1
24
+ url
25
+ else
26
+ 'All Controller Actions'
27
+ end
28
+ end
29
+
30
+ def url
31
+ '/' + segments[1..-1].join('/')
32
+ end
33
+
34
+ def call_rate_suffix
35
+ 'rpm'
36
+ end
37
+
38
+ end
@@ -0,0 +1,6 @@
1
+ class NewRelic::MetricParser::Errors < NewRelic::MetricParser
2
+ def is_error?; true; end
3
+ def short_name
4
+ segments[2..-1].join(NewRelic::MetricParser::SEPARATOR)
5
+ end
6
+ end
@@ -0,0 +1,50 @@
1
+ class NewRelic::MetricParser::External < NewRelic::MetricParser
2
+
3
+ def all?
4
+ host == 'all' || host == 'allWeb' || host == 'allOther'
5
+ end
6
+ def hosts_all?
7
+ library == 'all'
8
+ end
9
+ def host
10
+ segments[1]
11
+ end
12
+ def library
13
+ segments[2]
14
+ end
15
+ def operation
16
+ segments[3] && segments[3..-1].join("/")
17
+ end
18
+ def legend_name
19
+ case
20
+ when all?
21
+ "External Services"
22
+ when hosts_all?
23
+ "All #{host} calls"
24
+ else
25
+ developer_name
26
+ end
27
+ end
28
+ def tooltip_name
29
+ case
30
+ when all?
31
+ "calls to external systems"
32
+ when hosts_all?
33
+ "calls to #{host}"
34
+ else
35
+ "calls to #{developer_name}"
36
+ end
37
+ end
38
+ def developer_name
39
+ case
40
+ when all?
41
+ 'All External'
42
+ when hosts_all?
43
+ host
44
+ when operation
45
+ "#{library}[#{host}]: #{operation}"
46
+ else
47
+ "#{library}[#{host}]"
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ class NewRelic::MetricParser::MemCache < NewRelic::MetricParser
2
+ def is_memcache?; true; end
3
+
4
+ # for MemCache metrics, the short name is actually
5
+ # the full name
6
+ def short_name
7
+ name
8
+ end
9
+ def developer_name
10
+ "MemCache #{segments[1..-1].join '/'}"
11
+ end
12
+ end
@@ -0,0 +1,61 @@
1
+ class NewRelic::MetricParser::View < NewRelic::MetricParser
2
+ def is_view?; true; end
3
+
4
+ def is_render?
5
+ segments.last == "Rendering"
6
+ end
7
+ def is_compiler?
8
+ segments.last == "Compile"
9
+ end
10
+ def pie_chart_label
11
+ case segments.last
12
+ when "Rendering"
13
+ "#{file_name(segments[-2])} Template"
14
+ when "Partial"
15
+ "#{file_name(segments[-2])} Partial"
16
+ when ".rhtml Processing"
17
+ "ERB compilation"
18
+ else
19
+ segments[1..-1]
20
+ end
21
+ end
22
+ def template_label
23
+ case segments.last
24
+ when "Rendering"
25
+ "#{file_name(segments[1..-2].join(NewRelic::MetricParser::SEPARATOR))} Template"
26
+ when "Partial"
27
+ "#{file_name(segments[1..-2].join(NewRelic::MetricParser::SEPARATOR))} Partial"
28
+ when ".rhtml Processing"
29
+ "ERB compilation"
30
+ else
31
+ segments[1..-1].join("/")
32
+ end
33
+ end
34
+
35
+ def short_name
36
+ segments[1..-2].join(NewRelic::MetricParser::SEPARATOR)
37
+ end
38
+
39
+ def controller_name
40
+ template_label
41
+ end
42
+
43
+ def action_name
44
+ # Strip the extension
45
+ segments[-2].gsub(/\..*$/, "")
46
+ end
47
+
48
+ def developer_name
49
+ template_label
50
+ end
51
+
52
+ def url
53
+ '/' + file_name(segments[1..-2].join('/'))
54
+ end
55
+ private
56
+ def file_name(path)
57
+ label = path.gsub /\.html\.rhtml/, '.rhtml'
58
+ label = segments[1] if label.empty?
59
+ label
60
+ end
61
+ end