Skip to content
This repository has been archived by the owner on Oct 24, 2023. It is now read-only.

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
PatrickTulskie committed Apr 30, 2013
0 parents commit 9e0b2b6
Show file tree
Hide file tree
Showing 18 changed files with 400 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
*.gem
*.rbc
.bundle
.config
.yardoc
Gemfile.lock
InstalledFiles
_yardoc
coverage
doc/
lib/bundler/man
pkg
rdoc
spec/reports
test/tmp
test/version_tmp
tmp
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source 'https://rubygems.org'

# Specify your gem's dependencies in elastic_board.gemspec
gemspec
22 changes: 22 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Copyright (c) 2013 Patrick Tulskie

MIT License

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ElasticBoard

TODO: Write a gem description

## Installation

Add this line to your application's Gemfile:

gem 'elastic_board'

And then execute:

$ bundle

Or install it yourself as:

$ gem install elastic_board

## Usage

TODO: Write usage instructions here

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
1 change: 1 addition & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require "bundler/gem_tasks"
8 changes: 8 additions & 0 deletions config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require "bundler/setup"
require "sinatra"
require "rubberband"
require "elastic_board"

map '/elasticboard' do
run ElasticBoard::Application.new(:connection => ElasticSearch.new("localhost:9200"))
end
24 changes: 24 additions & 0 deletions elastic_board.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# -*- encoding: utf-8 -*-
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'elastic_board/version'

Gem::Specification.new do |gem|
gem.name = "elastic_board"
gem.version = ElasticBoard::VERSION
gem.authors = ["Patrick Tulskie"]
gem.email = ["patricktulskie@gmail.com"]
gem.description = %q{Status board rack middleware for ElasticSearch}
gem.summary = %q{Simple ElasticSearch status board middleware for rack applictions}
gem.homepage = ""

gem.files = `git ls-files`.split($/)
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
gem.require_paths = ["lib"]

gem.add_dependency("sinatra")
gem.add_dependency("rubberband")

gem.add_development_dependency("shotgun")
end
66 changes: 66 additions & 0 deletions lib/elastic_board.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require "elastic_board/summary"

module ElasticBoard

class Application < Sinatra::Base

# Setup paths for public and views
dir = File.dirname(File.expand_path(__FILE__))
set :views, "#{dir}/elastic_board/views"
set (respond_to?(:public_folder) ? :public_folder : :public), "#{dir}/elastic_board/public"

# Connection to ElasticSearch
attr_accessor :connection

# Initializer Override to get options
def initialize(options = { })
self.connection = options[:connection]
super
end

# ===================
# = Sinatra Helpers =
# ===================

helpers do
def path_prefix
request.env['SCRIPT_NAME']
end

def url_path(*path_parts)
[path_prefix, path_parts].join('/').squeeze('/')
end

def script_tag(*path_parts)
%(<script src="#{url_path(%w(js) + path_parts)}"></script>)
end

def stylesheet_tag(*path_parts)
%(<link href="#{url_path(%w(css) + path_parts)}" rel="stylesheet">)
end

def header_badge(summary)
case summary.cluster_status
when 'green'
{ :class => 'badge-success', :message => 'All Systems Go' }
when 'yellow'
{ :class => 'badge-warning', :message => 'Having Some Problems' }
when 'red'
{ :class => 'badge-important', :message => 'Everything is in Flames' }
end
end
end

# ==================
# = Sinatra Routes =
# ==================

get '/' do
@summary = ElasticBoard::Summary.new(self.connection)

erb :index
end

end

end
9 changes: 9 additions & 0 deletions lib/elastic_board/public/css/bootstrap-responsive.min.css

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions lib/elastic_board/public/css/bootstrap.min.css

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions lib/elastic_board/public/css/elastic_board.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
table.summary_table {
font-size: 1.5em;
line-height: 1.3em;
}

table.summary_table tr td {
padding-left: 15px;
}

div.well-top {
height: 120px;
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions lib/elastic_board/public/js/bootstrap.min.js

Large diffs are not rendered by default.

97 changes: 97 additions & 0 deletions lib/elastic_board/summary.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
module ElasticBoard
class Summary

attr_accessor :connection

def initialize(*servers)
if servers.first.is_a?(ElasticSearch::Client)
self.connection = servers.first
else
self.connection = ElasticSearch.new(servers)
end
end

# ===================
# = State Functions =
# ===================

def cluster_state
@cluster_state ||= self.connection.cluster_state
end

# ==================
# = Node Functions =
# ==================

def nodes_info
@nodes_info ||= self.connection.nodes_info
end

def nodes
nodes = [ ]
nodes_info['nodes'].each do |key, node_details|
nodes << {
:name => node_details['name'],
:address => extract_ip_from_address(node_details['transport_address'])
}
end

return nodes
end

# ===================
# = Index Functions =
# ===================

def index_status
@index_status ||= self.connection.index_status
end

def indices
index_status['indices']
end

# ====================
# = Health Functions =
# ====================

def cluster_health
@cluster_health ||= self.connection.cluster_health
end

def cluster_name
cluster_health['cluster_name']
end

def cluster_status
cluster_health['status']
end

def number_of_nodes
cluster_health['number_of_nodes']
end

def active_shards
cluster_health['active_shards']
end

def active_primary_shards
cluster_health['active_primary_shards']
end

def number_of_nodes
cluster_health['number_of_nodes']
end

def unassigned_shards
cluster_health['unassigned_shards']
end

private

def extract_ip_from_address(address)
address.match(/\s*\[\/(.*)\]/)[1]
end

end
end
3 changes: 3 additions & 0 deletions lib/elastic_board/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module ElasticBoard
VERSION = "0.0.1"
end
64 changes: 64 additions & 0 deletions lib/elastic_board/views/index.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="#">ElasticBoard - <%= @summary.cluster_name %></a>
<span class="badge <%= header_badge(@summary)[:class] %>" style="margin-top:11px;"><%= header_badge(@summary)[:message] %></span>
</div>
</div>
</div>

<div class="container">

<!-- Example row of columns -->
<div class="row">
<div class="span6">
<h2>Cluster Health <span class="badge badge-<%= @summary.nodes_info['ok'] ? 'success' : 'important' %>"><%= @summary.nodes_info['ok'] ? 'Healthy' : 'Problem' %></span></h2>
<div class="well well-top">
<table class="summary_table">
<tr><td style="font-weight: bold">Number of Nodes</td><td><%= @summary.number_of_nodes %></td></tr>
<tr><td style="font-weight: bold">Active Shards</td><td><%= @summary.active_shards %></td></tr>
<tr><td style="font-weight: bold">Active Primary Shards</td><td><%= @summary.active_primary_shards %></td></tr>
<tr><td style="font-weight: bold">Unassigned Shards</td><td><%= @summary.unassigned_shards %></td></tr>
</table>
</div>
</div>
<div class="span6">
<h2>Nodes in Cluster</h2>
<div class="well well-top">
<table class="summary_table">
<% @summary.nodes.each do |node| %>
<tr><td style="font-weight: bold"><%= node[:name] %></td><td><%= node[:address] %></td></tr>
<% end %>
</table>
</div>
</div>
</div>

<!-- Main hero unit for a primary marketing message or call to action -->
<div class="container">
<h2>Indexes</h2>
<div class="well">
<table class="summary_table">
<tr>
<td><span style="font-weight: bold">Index Name</span></td>
<td><span style="font-weight: bold">Records</span></td>
<td><span style="font-weight: bold">Size</span></td>
</tr>
<% @summary.indices.each do |index_name, details| %>
<tr>
<td><%= index_name %></td>
<td><%= details['docs']['num_docs'] %></td>
<td><%= details['index']['size'] %></td>
</tr>
<% end %>
</table>
</div>
</div>

<hr>

<footer>
<p>&copy; ElasticBoard 2013</p>
</footer>

</div> <!-- /container -->
29 changes: 29 additions & 0 deletions lib/elastic_board/views/layout.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ElasticBoard - Status Board for ElasticSearch</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">

<%= stylesheet_tag 'bootstrap.min.css' %>
<%= stylesheet_tag 'elastic_board.css' %>
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<%= stylesheet_tag 'bootstrap-responsive.min.css' %>

<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="/js/html5shiv.js"></script>
<![endif]-->
</head>

<body>
<%= yield %>
</body>
</html>

0 comments on commit 9e0b2b6

Please sign in to comment.