From 556cf8114e8610655e7a7b0ef1dd61ed724161c9 Mon Sep 17 00:00:00 2001 From: Ken Jibiki Date: Mon, 15 Sep 2014 19:43:30 -0700 Subject: [PATCH] Initial commit of the codes --- Gemfile | 4 + LICENSE | 2 +- README.md | 48 +++++++++++- config/template_newrelic_plugin.yml | 31 ++++++++ newrelic_redis_agent | 111 ++++++++++++++++++++++++++++ 5 files changed, 192 insertions(+), 4 deletions(-) create mode 100755 Gemfile create mode 100755 config/template_newrelic_plugin.yml create mode 100755 newrelic_redis_agent diff --git a/Gemfile b/Gemfile new file mode 100755 index 0000000..1694cf1 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source "http://rubygems.org" +gem "dante" +gem "newrelic_plugin" +gem "redis" diff --git a/LICENSE b/LICENSE index 44bfe64..b99f79a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Ken J. +Copyright (c) 2014 kenjij Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8b8cb58..ddaa7f2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,46 @@ -newrelic_redis_plugin -===================== +# newrelic_redis_plugin -New Relic plugin for Redis +New Relic plugin for Redis in Ruby. + +Unlike other plugins, it's simple and dedicated for Redis. Most of the statistics are available and built to run as a daemon with PID file and logging. + +## Spec + +Tested with: +- Ruby 2.0.0 +- Gem: dante 0.2.0 + +## Installation + +1. Download the latest [release](https://github.com/kenjij/newrelic_redis_plugin/releases) +2. Extract to the location you want to run the agent from +3. Copy `config/template_newrelic_plugin.yml` to `config/newrelic_plugin.yml` +4. Edit `config/newrelic_plugin.yml` and replace "YOUR_LICENSE_KEY_HERE" with your New Relic license key + +## Usage + +Simply do `./newrelic_redis_agent` to run in the foreground. Other command line options are: + +- `-d` – Run as daemon +- `-c FILE` – Designate a config file + +## Config Options + +Few configuration options are available in `config/newrelic_plugin.yml`. + +- `instance_name` – Name of the instance that will be listed in New Relic; default: "HOSTNAME:PORT" +- `url` – Your Redis server; use "redis://127.0.0.1:6379" as default +- `database` – the database in which to lookup 'total keys'; use "db0" as default + +### Example +``` yaml +agents: + redis: + instance_name: MyRedisServer + url: redis://127.0.0.1:6379 + database: db0 +``` + +## License + +[MIT](http://opensource.org/licenses/MIT) diff --git a/config/template_newrelic_plugin.yml b/config/template_newrelic_plugin.yml new file mode 100755 index 0000000..d72e027 --- /dev/null +++ b/config/template_newrelic_plugin.yml @@ -0,0 +1,31 @@ +# Please make sure to update the license_key information with the license key for your New Relic +# account. +# +# +newrelic: + # + # Update with your New Relic account license key: + # + license_key: 'YOUR_LICENSE_KEY_HERE' + # + # Set to '1' for verbose output, remove for normal output. + # All output goes to stdout/stderr. + # + # verbose: 1 + + # Proxy configuration: + #proxy: + # address: localhost + # port: 8080 + # user: nil + # password: nil + +# +# Agent Configuration: +# +agents: + # this is where configuration for agents belongs + redis: + #instance_name: MyRedisServer + url: redis://127.0.0.1:6379 + database: db0 diff --git a/newrelic_redis_agent b/newrelic_redis_agent new file mode 100755 index 0000000..bb4a09f --- /dev/null +++ b/newrelic_redis_agent @@ -0,0 +1,111 @@ +#! /usr/bin/env ruby + +require "rubygems" +require "bundler/setup" +require "dante" +require "newrelic_plugin" +require "redis" + +pid_path = File.expand_path("../run/newrelic_redis_agent.pid", __FILE__) +log_path = File.expand_path("../log/newrelic_redis_agent.log", __FILE__) + +runner = Dante::Runner.new('newrelic_redis_agent', :pid_path => pid_path, :log_path => log_path) +runner.description = 'New Relic plugin agent for Redis' +runner.with_options do |opts| + opts.on('-c', '--config FILE', String, 'Specify configuration file') do |config| + options[:config_path] = config + end +end + +runner.execute do |opts| + $redisplugin_config_path = opts[:config_path] + + module RedisAgent + + class Agent < NewRelic::Plugin::Agent::Base + + agent_guid "net.kenjij.newrelicplugin.redis" + agent_version "1.0.0" + agent_config_options :instance_name, :url, :database + agent_human_labels('Redis') do + if instance_name == nil + host = Socket.gethostname().sub(/\..*/, '') + uri = URI.parse("#{url}") + "#{host}:#{uri.port}" + else + "#{instance_name}" + end + end + + def setup_metrics + @redis = Redis.new(:url => url) + @last_values = {} + @redis_info = nil + end + + def poll_cycle + begin + @redis_info = @redis.info + info = @redis_info + rescue Exception => e + puts e.message + return nil + end + report_metric "Memory/Used", "bytes", info['used_memory'].to_i + report_metric "Memory/RSS", "bytes", info['used_memory_rss'].to_i + report_metric "Memory/Lua", "bytes", info['used_memory_lua'].to_i + report_metric "Memory/Peak", "bytes", info['used_memory_peak'].to_i + report_metric "CPU/System", "seconds", info['used_cpu_sys'].to_i + report_metric "CPU/User", "seconds", info['used_cpu_sys'].to_i + report_metric "CPU/Child System", "seconds", info['used_cpu_sys_children'].to_i + report_metric "CPU/Child User", "seconds", info['used_cpu_sys_children'].to_i + report_metric "RDB Unsaved Changes", "changes", info['rdb_changes_since_last_save'].to_i + report_metric "RDB Save Time", "seconds", info['rdb_last_bgsave_time_sec'].to_i + report_metric "Connection/Clients", "connections", info['connected_clients'].to_i + report_metric "Connection/Slaves", "connections", info['connected_slaves'].to_i + report_metric "ConnectionRate/Received", "connections", last_metric('total_connections_received') + report_metric "ConnectionRate/Rejected", "connections", last_metric('rejected_connections') + report_metric "Commands Processed", "commands", last_metric('total_commands_processed') + report_metric "KeyspaceRate/Hits", "keys", last_metric('keyspace_hits') + report_metric "KeyspaceRate/Misses", "keys", last_metric('keyspace_misses') + report_metric "Expired Keys", "keys", last_metric('expired_keys') + report_metric "Evicted Keys", "keys", last_metric('evicted_keys') + dbstat = info[database] if database + if dbstat + begin + h = Hash[dbstat.split(/,/).each.collect{|s|s.split('=')}] + report_metric "Database/Total Keys", "keys", h['keys'].to_i + report_metric "Database/Expiring Keys", "keys", h['expires'].to_i + rescue Exception => e + puts e.message + end + end + @redis_info = nil + end + + private + + def last_metric(key) + return nil if @redis_info.nil? || @redis_info[key].nil? + current_value = @redis_info[key].to_i + if @last_values[key].nil? + metric = 0 + else + metric = current_value - @last_values[key] + metric = 0 if metric < 0 + end + @last_values[key] = current_value + return metric + end + + end + + if $redisplugin_config_path + NewRelic::Plugin::Config.config_file = $redisplugin_config_path + end + NewRelic::Plugin::Setup.install_agent :redis, RedisAgent + NewRelic::Plugin::Run.setup_and_run + + end + +end