fluentd-server 0.1.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.
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