fluentd-server 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.env +5 -0
  3. data/.gitignore +17 -0
  4. data/.travis.yml +5 -0
  5. data/API.md +21 -0
  6. data/CHANGELOG.md +3 -0
  7. data/Gemfile +9 -0
  8. data/Procfile +1 -0
  9. data/README.md +127 -0
  10. data/Rakefile +26 -0
  11. data/bench/bench.rb +83 -0
  12. data/bench/result.md +17 -0
  13. data/bin/fluentd-server +7 -0
  14. data/config.ru +15 -0
  15. data/config/unicorn.conf +20 -0
  16. data/db/migrate/20140512203133_create_posts.rb +14 -0
  17. data/db/schema.rb +25 -0
  18. data/fluentd-server.gemspec +43 -0
  19. data/lib/fluentd_server.rb +1 -0
  20. data/lib/fluentd_server/cli.rb +64 -0
  21. data/lib/fluentd_server/config.rb +27 -0
  22. data/lib/fluentd_server/decorator.rb +21 -0
  23. data/lib/fluentd_server/environments.rb +34 -0
  24. data/lib/fluentd_server/logger.rb +90 -0
  25. data/lib/fluentd_server/model.rb +10 -0
  26. data/lib/fluentd_server/version.rb +3 -0
  27. data/lib/fluentd_server/web.rb +101 -0
  28. data/lib/fluentd_server/web_helper.rb +91 -0
  29. data/public/css/bootstrap.min.css +7 -0
  30. data/public/fonts/glyphicons-halflings-regular.eot +0 -0
  31. data/public/fonts/glyphicons-halflings-regular.svg +229 -0
  32. data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  33. data/public/fonts/glyphicons-halflings-regular.woff +0 -0
  34. data/public/js/bootstrap.min.js +7 -0
  35. data/public/js/jquery-1.10.2.min.js +6 -0
  36. data/public/js/jquery-1.10.2.min.map +0 -0
  37. data/public/js/jquery.storageapi.min.js +2 -0
  38. data/spec/api_spec.rb +42 -0
  39. data/spec/spec_helper.rb +14 -0
  40. data/spec/web_helper_spec.rb +27 -0
  41. data/spec/web_spec.rb +55 -0
  42. data/views/_navbar.slim +15 -0
  43. data/views/layout.slim +22 -0
  44. data/views/posts/create.slim +19 -0
  45. data/views/posts/edit.slim +23 -0
  46. data/views/posts/index.slim +9 -0
  47. metadata +363 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 23543f023f2b14f82abde08cceba1337e730c494
4
+ data.tar.gz: bb43d8d9a3686cc3e1cba3da52bf532438ba1cc9
5
+ SHA512:
6
+ metadata.gz: b430c589ae0aaa6f102d36c98a61dc6230510ea590f528922f26d30a3e4b1511b07b323d7107b82ed417c00fab6734cb657ff7e4ceca60ef771d9a0766a0be64
7
+ data.tar.gz: 512e455f5e280674c272a992c8ea676323e207c7693eb597d460a9a6d3c88135b394d21b95872724a28c13f340d53538e5832f982b34132cf34644bc1dde0376
data/.env ADDED
@@ -0,0 +1,5 @@
1
+ PORT=5126
2
+ HOST=0.0.0.0
3
+ # DATABASE_URL=sqlite3:data/fluentd_server.db
4
+ # LOG_PATH=log/application.log
5
+ # LOG_LEVEL=warn
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ /*.gem
2
+ ~*
3
+ #*
4
+ *~
5
+ .bundle
6
+ Gemfile.lock
7
+ .rbenv-version
8
+ vendor
9
+ doc/*
10
+ tmp/*
11
+ coverage
12
+ .yardoc
13
+ .ruby-version
14
+ pkg/*
15
+ data/*
16
+ log/*
17
+ fluentd-server/*
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - 2.0.0
3
+ - 2.1
4
+ gemfile:
5
+ - Gemfile
data/API.md ADDED
@@ -0,0 +1,21 @@
1
+ ## API
2
+
3
+ ### GET /api/:name
4
+
5
+ Get the contents of Fluentd config whose name is :name.
6
+ Query parameters are replaced with variables in erb.
7
+
8
+ Supported query parameter formats are:
9
+
10
+ * var=value
11
+
12
+ * The variable `var` is replaced with its value in erb.
13
+
14
+ * var[]=value1&var[]=value2
15
+
16
+ * Array. The variable `var[idx]` such as `var[0]` and `var[1]` is replaced with its value in erb.
17
+
18
+ * var[key1]=value1&var[key2]=value2
19
+
20
+ * Hash. The variable `var[key]` such as `var['key1']` and `var['key2']` is replaced with its value in erb.
21
+
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # 0.1.0
2
+
3
+ First version
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+ gem 'sqlite3'
5
+
6
+ group :development, :test do
7
+ gem 'coveralls', :require => false
8
+ gem 'parallel'
9
+ end
data/Procfile ADDED
@@ -0,0 +1 @@
1
+ web: bundle exec unicorn -E production -p $PORT -o $HOST -c config/unicorn.conf
data/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # Fluentd Server
2
+
3
+ [![Build Status](https://secure.travis-ci.org/sonots/fluentd-server.png?branch=master)](http://travis-ci.org/sonots/fluentd-server)
4
+ [![Coverage Status](https://coveralls.io/repos/sonots/fluentd-server/badge.png?branch=master)](https://coveralls.io/r/sonots/fluentd-server?branch=master)
5
+
6
+ A Fluentd config distribution server
7
+
8
+ Demo: [http://fluentd-server.herokuapp.com](http://fluentd-server.herokuapp.com)
9
+
10
+ ## What You Can Do
11
+
12
+ With Fluentd Server, you can manage fluentd configuration files centrally with `erb`.
13
+
14
+ For example, you may create a config post whose name is `worker` as:
15
+
16
+ ```
17
+ <source>
18
+ type forward
19
+ port <%= port %>
20
+ </source>
21
+
22
+ <match **>
23
+ type stdout
24
+ </match>
25
+ ```
26
+
27
+ Then you can download the config via an API whose uri is like `/api/worker?port=24224` where its query parameters are replaced with variables in the erb.
28
+ The downloaded contents should become as follows:
29
+
30
+ ```
31
+ <source>
32
+ type forward
33
+ port 24224
34
+ </source>
35
+
36
+ <match **>
37
+ type stdout
38
+ </match>
39
+ ```
40
+
41
+ ## How to Use
42
+
43
+ The `include` directive of fluentd config supports `http`, so write just one line on your fluentd.conf as:
44
+
45
+ ```
46
+ # /etc/fluentd.conf
47
+ include http://fqdn.to.fluentd-server/api/:name?port=24224
48
+ ```
49
+
50
+ where :name is the name of your config post, so that it will download the real configuration from the Fluentd Server.
51
+
52
+ ## Installation
53
+
54
+ Prerequisites
55
+
56
+ * SQLite
57
+ * Ruby 2.0 or later
58
+
59
+ ### From Gem package
60
+
61
+ Easy steps on installation with gem and SQLite.
62
+
63
+ ```bash
64
+ $ gem install fluentd-server
65
+ $ gem install sqlite3
66
+ $ fluentd-server new
67
+ $ cd fluentd-server
68
+ $ fluentd-server init # creates database scheme on SQLite
69
+ $ fluentd-server start
70
+ ```
71
+
72
+ Then see `http://localhost:5126/`.
73
+
74
+ ### From Git repository
75
+
76
+ Install from git repository.
77
+
78
+ ```bash
79
+ $ git clone https://github.com/sonots/fluentd-server.git
80
+ $ cd fluentd-server
81
+ $ bundle
82
+ $ bundle exec fluentd-server init # creates database scheme on SQLite
83
+ $ bundle exec fluentd-server start
84
+ ```
85
+
86
+ Then see `http://localhost:5126/`.
87
+
88
+ ## Configuration
89
+
90
+ To configure fluentd-server, edit the `.env` file in the project root directory.
91
+
92
+ The default configuration is as follows:
93
+
94
+ ```
95
+ PORT=5126
96
+ HOST=0.0.0.0
97
+ # DATABASE_URL=sqlite3:data/fluentd_server.db
98
+ # LOG_PATH=log/application.log
99
+ # LOG_LEVEL=warn
100
+ ```
101
+
102
+ ## HTTP API
103
+
104
+ See [API.md](API.md).
105
+
106
+ ## ToDo
107
+
108
+ * Local file storage
109
+
110
+ * Saving and loading conf from localfiles rather than DB would be nice because it makes possible to manage conf with git
111
+ * Fluentd Server should cache them on memory, and refresh caches by detecting files are updated
112
+
113
+ ## ChangeLog
114
+
115
+ See [CHANGELOG.md](CHANGELOG.md) for details.
116
+
117
+ ## Contributing
118
+
119
+ 1. Fork it
120
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
121
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
122
+ 4. Push to the branch (`git push origin my-new-feature`)
123
+ 5. Create new [Pull Request](../../pull/new/master)
124
+
125
+ ## Copyright
126
+
127
+ Copyright (c) 2014 Naotoshi Seo. See [LICENSE](LICENSE) for details.
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.rspec_opts = ["-c", "-f progress"] # '--format specdoc'
6
+ t.pattern = 'spec/**/*_spec.rb'
7
+ end
8
+
9
+ lib = File.expand_path('../lib', __FILE__)
10
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
11
+ require 'dotenv/tasks'
12
+ require 'fluentd_server/config'
13
+
14
+ require 'sinatra/activerecord/rake'
15
+
16
+ task :console => :dotenv do
17
+ require "fluentd_server"
18
+ require 'irb'
19
+ # require 'irb/completion'
20
+ ARGV.clear
21
+ IRB.start
22
+ end
23
+ task :c => :console
24
+
25
+ task :test => :spec
26
+ task :default => :spec
data/bench/bench.rb ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'parallel'
4
+ require 'net/http'
5
+
6
+ def main
7
+ requests = 20000 # number of requests to perform
8
+ concurrency = 126 # number of multiple requests to make
9
+ name = 'worker'
10
+ puts "requests = #{requests}"
11
+ puts "concurrency = #{concurrency}"
12
+
13
+ client = Client.new("http://localhost:5126")
14
+
15
+ duration = elapsed_time do
16
+ Parallel.each_with_index([name]*requests, :in_processes => concurrency) do |name, i|
17
+ puts "processing #{i}" if i % 1000 == 0
18
+ res = client.get(name)
19
+ puts 'error' unless res.code == '200'
20
+ end
21
+ end
22
+
23
+ req_per_sec = ( duration > 0 ) ? requests/duration : 0
24
+ puts "req/sec = #{req_per_sec}"
25
+ end
26
+
27
+ def elapsed_time(&block)
28
+ s = Time.now
29
+ yield
30
+ Time.now - s
31
+ end
32
+
33
+ class Client
34
+ attr_reader :base_uri
35
+ attr_reader :host
36
+ attr_reader :port
37
+ attr_accessor :debug_dev
38
+ attr_accessor :open_timeout
39
+ attr_accessor :read_timeout
40
+ attr_accessor :verify_ssl
41
+ attr_accessor :keepalive
42
+
43
+ def initialize(base_uri = 'http://127.0.0.1:5126', opts = {})
44
+ @base_uri = base_uri
45
+
46
+ URI.parse(base_uri).tap {|uri|
47
+ @host = uri.host
48
+ @port = uri.port
49
+ @use_ssl = uri.scheme == 'https'
50
+ }
51
+ @debug_dev = opts['debug_dev'] # IO object such as STDOUT
52
+ @open_timeout = opts['open_timeout'] # 60
53
+ @read_timeout = opts['read_timeout'] # 60
54
+ @verify_ssl = opts['verify_ssl']
55
+ @keepalive = opts['keepalive']
56
+ end
57
+
58
+ def http_connection
59
+ Net::HTTP.new(@host, @port).tap {|http|
60
+ http.use_ssl = @use_ssl
61
+ http.open_timeout = @open_timeout if @open_timeout
62
+ http.read_timeout = @read_timeout if @read_timeout
63
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @verify_ssl
64
+ http.set_debug_output(@debug_dev) if @debug_dev
65
+ }
66
+ end
67
+
68
+ def get_request(path, extheader = {})
69
+ Net::HTTP::Get.new(path).tap {|req|
70
+ req['Host'] = @host
71
+ req['Connection'] = 'Keep-Alive' if @keepalive
72
+ extheader.each {|key, value| req[key] = value }
73
+ }
74
+ end
75
+
76
+ def get(name)
77
+ path = "/api/#{name}"
78
+ req = get_request(path)
79
+ @res = http_connection.start {|http| http.request(req) }
80
+ end
81
+ end
82
+
83
+ main
data/bench/result.md ADDED
@@ -0,0 +1,17 @@
1
+ The conf body as followings, would be too small to evaluate:
2
+
3
+ ```
4
+ <source>
5
+ type forward
6
+ port <%= port %>
7
+ </source>
8
+ ```
9
+
10
+ | # of requests | concurrency | server | # of workers | req/sec |
11
+ |---------------|-------------|---------|--------------|---------|
12
+ |20000 |126 | unicorn | 1 |865.07 |
13
+ |20000 |126 | unicorn | 12 |4116.78 |
14
+ |20000 |126 | puma | 1 |634.20|
15
+ |20000 |126 | puma | 12 |3765.66 |
16
+
17
+ Let's use unicorn
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path("../../lib", __FILE__)
4
+
5
+ require "fluentd_server/cli"
6
+
7
+ FluentdServer::CLI.start
data/config.ru ADDED
@@ -0,0 +1,15 @@
1
+ require "rubygems"
2
+ require "sinatra"
3
+ require "fluentd_server"
4
+ require "fluentd_server/web"
5
+
6
+ ## Unicorn self-process killer
7
+ #require 'unicorn/worker_killer'
8
+ #
9
+ ## Max requests per worker
10
+ #use Unicorn::WorkerKiller::MaxRequests, 3072, 4096
11
+ #
12
+ ## Max memory size (RSS) per worker
13
+ #use Unicorn::WorkerKiller::Oom, (192*(1024**2)), (256*(1024**2))
14
+
15
+ run FluentdServer::Web
@@ -0,0 +1,20 @@
1
+ worker_processes 1
2
+ # timeout 6000
3
+ # preload_app true
4
+
5
+ GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true
6
+
7
+ before_fork do |server, worker|
8
+ defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
9
+
10
+ old_pid = "#{server.config[:pid]}.oldbin"
11
+ if old_pid != server.pid
12
+ begin
13
+ sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
14
+ Process.kill(sig, File.read(old_pid).to_i)
15
+ rescue Errno::ENOENT, Errno::ESRCH
16
+ end
17
+ end
18
+
19
+ sleep 1
20
+ end
@@ -0,0 +1,14 @@
1
+ class CreatePosts < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :posts do |t|
4
+ t.string :name
5
+ t.text :body
6
+ t.timestamps
7
+ end
8
+ add_index :posts, :name, length: 255, unique: true # explicit length is required for MySQL
9
+ end
10
+
11
+ def self.down
12
+ drop_table :posts
13
+ end
14
+ end
data/db/schema.rb ADDED
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended that you check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(version: 20140512203133) do
15
+
16
+ create_table "posts", force: true do |t|
17
+ t.string "name"
18
+ t.text "body"
19
+ t.datetime "created_at"
20
+ t.datetime "updated_at"
21
+ end
22
+
23
+ add_index "posts", ["name"], name: "index_posts_on_name", unique: true
24
+
25
+ end
@@ -0,0 +1,43 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fluentd_server/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fluentd-server"
8
+ spec.version = FluentdServer::VERSION
9
+ spec.authors = ["Naotoshi Seo"]
10
+ spec.email = ["sonots@gmail.com"]
11
+ spec.description = %q{Fluentd config distribution server}
12
+ spec.summary = spec.description
13
+ spec.homepage = "https://github.com/sonots/fluentd-server"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "capybara"
24
+ spec.add_development_dependency "pry"
25
+ spec.add_development_dependency "pry-nav"
26
+ spec.add_development_dependency "rake"
27
+
28
+ spec.add_runtime_dependency "dotenv"
29
+ spec.add_runtime_dependency "foreman"
30
+ spec.add_runtime_dependency "thor"
31
+
32
+ spec.add_runtime_dependency "sinatra"
33
+ spec.add_runtime_dependency "activerecord"
34
+ spec.add_runtime_dependency "sinatra-contrib"
35
+ spec.add_runtime_dependency "sinatra-activerecord"
36
+ spec.add_runtime_dependency 'sinatra-flash'
37
+ spec.add_runtime_dependency 'sinatra-redirect-with-flash'
38
+ spec.add_runtime_dependency 'sinatra-decorator'
39
+ spec.add_runtime_dependency 'slim'
40
+ spec.add_runtime_dependency "unicorn"
41
+ spec.add_runtime_dependency "unicorn-worker-killer"
42
+ # spec.add_runtime_dependency 'sqlite3'
43
+ end