newrelic_sphinx 0.0.0
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.
- checksums.yaml +15 -0
- data/Rakefile +32 -0
- data/VERSION +1 -0
- data/bin/sphinx_agent +54 -0
- data/lib/newrelic_sphinx/agent.rb +158 -0
- data/newrelic_sphinx.gemspec +41 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -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=
|
data/Rakefile
ADDED
@@ -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
|
data/bin/sphinx_agent
ADDED
@@ -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: []
|