newrelic_sphinx 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ M2EzZWZiNTU0ZDNjNmNjYjkxODBhMjFlNjQ0N2E2ODBjOWQ1NDNjOQ==
5
+ data.tar.gz: !binary |-
6
+ ZjU4ZGFhZDU5MzM2ZjRiMmE3ZmQwMzdkZDUyMjc0NGQ0NTBhNzZjYQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NTg5YTBjYzQ2OWEzYzhjZGI1NjRiMzcxMWM0ODEyNWY5NzE1MGZmMjRmNGQz
10
+ MGE5MWJjZDk1YjA2YjMxYmY2YjllYTVlY2RjY2E5MzZjZWM3NTJjYjU4ZGM3
11
+ Nzk0NmRmNWQxYzhiNjJmMzliNGNiNGQwMGQ4MWU0N2ZkOWVmZmE=
12
+ data.tar.gz: !binary |-
13
+ NGE2OGI1NjA2M2ZlZWYzNmNlY2UyNDgwNjE4OGI0MWFjZDdmOTExNGI4YjQ0
14
+ NzJmOTYxMTdkMTlkMmVhOWY1MWMzZDZmMzJlOGU3M2I2ZGY4NmNjYTMyMmQz
15
+ M2ZhYWQ0ZTI4YWI5ZTZkNjg1NGFkMThhMWRhNTgwN2I2ZjI1MjE=
@@ -0,0 +1,32 @@
1
+ # -*- coding: utf-8 -*-
2
+ begin
3
+ require 'jeweler'
4
+ #require 'rubygems'
5
+ #gem :jeweler
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "newrelic_sphinx"
8
+ gemspec.summary = "newrelic_sphinx is a plugin for new relic, pushing stats about your Sphinx server."
9
+ gemspec.email = ["troels@knak-nielsen.dk"]
10
+ gemspec.homepage = "http://github.com/troelskn/newrelic_sphinx"
11
+ gemspec.description = gemspec.summary
12
+ gemspec.authors = ["Troels Knak-Nielsen"]
13
+ gemspec.license = 'MIT'
14
+ gemspec.add_dependency 'mysql2', ['~> 0.3.13']
15
+ gemspec.files.include 'lib/**/*.rb'
16
+ gemspec.files.include 'bin/**/*'
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError => err
20
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
21
+ p err
22
+ end
23
+
24
+ desc "Generates API documentation"
25
+ task :rdoc do
26
+ sh "rm -rf doc && rdoc lib"
27
+ end
28
+
29
+ task :default do
30
+ puts "Run `rake version:bump:patch release`"
31
+ end
32
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(File.dirname(__FILE__))))
3
+ require 'lib/newrelic_sphinx/agent'
4
+ require 'optparse'
5
+
6
+ options = {}
7
+ opt_parser = OptionParser.new do |opts|
8
+ opts.banner = "Usage: #{__FILE__} --license LICENSE [options]"
9
+
10
+ opts.on("--license LICENSE", "New Relic License key") do |license_key|
11
+ options[:license_key] = license_key
12
+ end
13
+
14
+ opts.on("--host [HOST]", "Sphinx hostname") do |host|
15
+ options[:host] = host
16
+ end
17
+
18
+ opts.on("--port [PORT]", Integer, "Sphinx port number") do |port|
19
+ options[:port] = port
20
+ end
21
+
22
+ opts.on("--username [USERNAME]", "Username to connect to Sphinx") do |username|
23
+ options[:username] = username
24
+ end
25
+
26
+ opts.on("--endpoint [ENDPOINT]", "URL endpoint to post data back to") do |endpoint|
27
+ options[:endpoint] = endpoint
28
+ end
29
+
30
+ opts.on("--frequenzy [FREQUENZY]", Integer, "Delay in sec. between each send") do |frequenzy|
31
+ options[:frequenzy] = frequenzy
32
+ end
33
+
34
+ opts.on("--hostname [HOSTNAME]", "Hostname to identify the machine with New Relic") do |hostname|
35
+ options[:hostname] = hostname
36
+ end
37
+
38
+ opts.on("--verbose", "Dump debug info to console") do
39
+ options[:verbose] = true
40
+ end
41
+
42
+ # No argument, shows at tail. This will print an options summary.
43
+ # Try it and see!
44
+ opts.on_tail("-h", "--help", "Show this message") do
45
+ puts opts
46
+ exit
47
+ end
48
+ end
49
+
50
+ opt_parser.parse! ARGV
51
+ raise "Missing license key" unless options[:license_key]
52
+
53
+ agent = NewrelicSphinx::Agent.new options
54
+ agent.run
@@ -0,0 +1,158 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'json'
4
+ require 'mysql2'
5
+
6
+ module NewrelicSphinx
7
+ class Metric
8
+ attr_reader :key, :name, :units, :mode, :last_value
9
+ attr_accessor :value
10
+
11
+ def initialize(key, name, units, mode = :plain)
12
+ @key, @name, @units, @mode = key, name, units, mode
13
+ @value = 0
14
+ @last_value = 0
15
+ end
16
+
17
+ def memorize
18
+ @last_value = value
19
+ end
20
+
21
+ def plain?
22
+ mode == :plain
23
+ end
24
+
25
+ def incremental?
26
+ mode == :incremental
27
+ end
28
+ end
29
+
30
+ class Agent
31
+ def initialize(configuration = {})
32
+ # If you use localhost, MySQL insists on a socket connection, but Sphinx
33
+ # requires a TCP connection. Using 127.0.0.1 fixes that.
34
+ address = configuration[:host] || '127.0.0.1'
35
+ address = '127.0.0.1' if address == 'localhost'
36
+
37
+ options = {
38
+ :host => address,
39
+ :port => configuration[:port] || 9306,
40
+ :username => "root",
41
+ :reconnect => true
42
+ }
43
+
44
+ @verbose = !! configuration[:verbose]
45
+ @client = Mysql2::Client.new(options)
46
+ @license_key = configuration[:license_key]
47
+ @host = configuration[:hostname] || `hostname`
48
+ @endpoint = configuration[:endpoint] || "https://platform-api.newrelic.com/platform/v1/metrics"
49
+ @frequenzy = configuration[:frequenzy] || 20
50
+ @component_name = 'Sphinx Stats'
51
+ @component_guid = 'com.github.troelskn.Sphinx'
52
+ @version = '0.0.1'
53
+ @metrics = []
54
+ @metrics << Metric.new("avg_query_wall", "avg/Avg Query Wall Time", "milisecond", :plain)
55
+ @metrics << Metric.new("queries", "general/Queries", "Queries/second", :incremental)
56
+ @metrics << Metric.new("connections", "general/Connections", "connections/second", :incremental)
57
+ @metrics << Metric.new("maxed_out", "error/Maxed out connections", "connections/second", :incremental)
58
+ @metrics << Metric.new("command_search", "commands/Command search", "command/second", :incremental)
59
+ @metrics << Metric.new("command_excerpt", "commands/Command excerpt", "command/second", :incremental)
60
+ @metrics << Metric.new("command_update", "commands/Command update", "command/second", :incremental)
61
+ @metrics << Metric.new("command_keywords", "commands/Command keywords", "command/second", :incremental)
62
+ @metrics << Metric.new("command_persist", "commands/Command persist", "command/second", :incremental)
63
+ @metrics << Metric.new("command_flushattrs", "commands/Command flushattrs", "command/second", :incremental)
64
+ end
65
+
66
+ def run
67
+ update_metrics
68
+ @last = Time.now
69
+ while true
70
+ execute
71
+ sleep 1
72
+ end
73
+ end
74
+
75
+ def execute
76
+ puts "*** execute" if @verbose
77
+ send_stats(build_metrics) if since_last > @frequenzy
78
+ end
79
+
80
+ def since_last
81
+ Time.now - @last
82
+ end
83
+
84
+ def send_stats(metrics)
85
+ puts "*** send_stats" if @verbose
86
+ data = {
87
+ 'agent' => {
88
+ 'host' => @host,
89
+ 'version' => @version,
90
+ },
91
+ 'components' => [
92
+ {
93
+ 'name' => @component_name,
94
+ 'guid' => @component_guid,
95
+ 'duration' => since_last.round,
96
+ 'metrics' => metrics
97
+ }
98
+ ]
99
+ }
100
+ uri = URI.parse(@endpoint)
101
+ request = Net::HTTP::Post.new(uri.request_uri)
102
+ request.body = JSON.pretty_generate(data)
103
+ request["Content-Type"] = "application/json"
104
+ request["Accept"] = "application/json"
105
+ request["X-License-Key"] = @license_key
106
+ http = Net::HTTP.new(uri.hostname, uri.port)
107
+ if uri.scheme == 'https'
108
+ http.use_ssl = true
109
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
110
+ end
111
+ http.set_debug_output $stderr if @verbose
112
+ response = http.start do |http|
113
+ http.request(request)
114
+ end
115
+ update_state if response.kind_of? Net::HTTPSuccess
116
+ end
117
+
118
+ def update_state
119
+ @last = Time.now
120
+ @metrics.each do |m|
121
+ m.memorize if m.incremental?
122
+ end
123
+ end
124
+
125
+ def update_metrics
126
+ data_source = {}
127
+ @client.query("show status").each do |row|
128
+ key = row.values[0]
129
+ value = row.values[1]
130
+ if value == "OFF"
131
+ data_source[key] = nil
132
+ elsif value =~ /^\d+$/
133
+ data_source[key] = value.to_i
134
+ else
135
+ data_source[key] = value.to_f
136
+ end
137
+ end
138
+ @metrics.each do |m|
139
+ m.value = data_source[m.key]
140
+ end
141
+ end
142
+
143
+ def build_metrics
144
+ update_metrics
145
+ struct = {}
146
+ @metrics.each do |m|
147
+ raise "Missing metric #{m.name}" if m.value.nil?
148
+ if m.incremental?
149
+ struct["Component/#{m.name}[#{m.units}]"] = m.value - m.last_value
150
+ else
151
+ struct["Component/#{m.name}[#{m.units}]"] = m.value
152
+ end
153
+ end
154
+ struct
155
+ end
156
+
157
+ end
158
+ end
@@ -0,0 +1,41 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "newrelic_sphinx"
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Troels Knak-Nielsen"]
12
+ s.date = "2013-10-01"
13
+ s.description = "newrelic_sphinx is a plugin for new relic, pushing stats about your Sphinx server."
14
+ s.email = ["troels@knak-nielsen.dk"]
15
+ s.executables = ["sphinx_agent"]
16
+ s.files = [
17
+ "Rakefile",
18
+ "VERSION",
19
+ "bin/sphinx_agent",
20
+ "lib/newrelic_sphinx/agent.rb",
21
+ "newrelic_sphinx.gemspec"
22
+ ]
23
+ s.homepage = "http://github.com/troelskn/newrelic_sphinx"
24
+ s.licenses = ["MIT"]
25
+ s.require_paths = ["lib"]
26
+ s.rubygems_version = "2.0.7"
27
+ s.summary = "newrelic_sphinx is a plugin for new relic, pushing stats about your Sphinx server."
28
+
29
+ if s.respond_to? :specification_version then
30
+ s.specification_version = 4
31
+
32
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
33
+ s.add_runtime_dependency(%q<mysql2>, ["~> 0.3.13"])
34
+ else
35
+ s.add_dependency(%q<mysql2>, ["~> 0.3.13"])
36
+ end
37
+ else
38
+ s.add_dependency(%q<mysql2>, ["~> 0.3.13"])
39
+ end
40
+ end
41
+
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: newrelic_sphinx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Troels Knak-Nielsen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mysql2
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.3.13
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.3.13
27
+ description: newrelic_sphinx is a plugin for new relic, pushing stats about your Sphinx
28
+ server.
29
+ email:
30
+ - troels@knak-nielsen.dk
31
+ executables:
32
+ - sphinx_agent
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - Rakefile
37
+ - VERSION
38
+ - bin/sphinx_agent
39
+ - lib/newrelic_sphinx/agent.rb
40
+ - newrelic_sphinx.gemspec
41
+ homepage: http://github.com/troelskn/newrelic_sphinx
42
+ licenses:
43
+ - MIT
44
+ metadata: {}
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project:
61
+ rubygems_version: 2.0.7
62
+ signing_key:
63
+ specification_version: 4
64
+ summary: newrelic_sphinx is a plugin for new relic, pushing stats about your Sphinx
65
+ server.
66
+ test_files: []