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.
@@ -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: []