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
@@ -0,0 +1 @@
1
+ require "fluentd_server/version"
@@ -0,0 +1,64 @@
1
+ require "fileutils"
2
+ require "dotenv"
3
+ require "thor"
4
+ require 'fluentd_server'
5
+
6
+ class FluentdServer::CLI < Thor
7
+ BASE_DIR = File.join(Dir.pwd, "fluentd-server")
8
+ DATA_DIR = File.join(BASE_DIR, "data")
9
+ LOG_DIR = File.join(BASE_DIR, "log")
10
+ LOG_FILE = File.join(LOG_DIR, "application.log")
11
+ ENV_FILE = File.join(BASE_DIR, ".env")
12
+ PROCFILE = File.join(BASE_DIR, "Procfile")
13
+ CONFIGRU_FILE = File.join(BASE_DIR, "config.ru")
14
+ DB_DIR = File.join(BASE_DIR, "db")
15
+ CONFIG_DIR= File.join(BASE_DIR, "config")
16
+
17
+ DEFAULT_DOTENV =<<-EOS
18
+ PORT=5126
19
+ HOST=0.0.0.0
20
+ DATABASE_URL=sqlite3:#{DATA_DIR}/fluentd_server.db
21
+ LOG_PATH=#{LOG_FILE}
22
+ LOG_LEVEL=warn
23
+ EOS
24
+
25
+ DEFAULT_PROCFILE =<<-EOS
26
+ web: unicorn -E production -p $PORT -o $HOST -c config/unicorn.conf
27
+ EOS
28
+
29
+ default_command :start
30
+
31
+ desc "new", "Creates fluentd-server resource directory"
32
+ def new
33
+ FileUtils.mkdir_p(LOG_DIR)
34
+ File.write ENV_FILE, DEFAULT_DOTENV
35
+ File.write PROCFILE, DEFAULT_PROCFILE
36
+ FileUtils.cp(File.expand_path("../../../config.ru", __FILE__), CONFIGRU_FILE)
37
+ FileUtils.cp_r(File.expand_path("../../../db", __FILE__), DB_DIR)
38
+ FileUtils.cp_r(File.expand_path("../../../config", __FILE__), CONFIG_DIR)
39
+ puts 'fluentd-server new finished.'
40
+ end
41
+
42
+ desc "init", "Creates database schema"
43
+ def init
44
+ require 'fluentd_server/environments'
45
+ require 'rake'
46
+ require 'sinatra/activerecord/rake'
47
+ Rake::Task['db:migrate'].invoke
48
+ puts 'fluentd-server init finished.'
49
+ end
50
+
51
+ desc "start", "Sartup fluentd_server"
52
+ def start
53
+ Dotenv.load
54
+ require "foreman/cli"
55
+ Foreman::CLI.new.invoke(:start, [], {})
56
+ end
57
+
58
+ no_tasks do
59
+ def abort(msg)
60
+ $stderr.puts msg
61
+ exit 1
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,27 @@
1
+ require 'sinatra'
2
+ require 'sinatra/activerecord'
3
+ require 'fluentd_server'
4
+ require 'dotenv'
5
+ Dotenv.load
6
+
7
+ module FluentdServer::Config
8
+ def self.database_url
9
+ ENV.fetch('DATABASE_URL', 'sqlite3:data/fluentd_server.db')
10
+ end
11
+
12
+ def self.log_path
13
+ ENV.fetch('LOG_PATH', 'STDOUT')
14
+ end
15
+
16
+ def self.log_level
17
+ ENV.fetch('LOG_LEVEL', 'debug')
18
+ end
19
+
20
+ def self.log_shift_age
21
+ ENV.fetch('LOG_SHIFT_AGE', '0')
22
+ end
23
+
24
+ def self.log_shift_size
25
+ ENV.fetch('LOG_SHIFT_SIZE', '1048576')
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ require 'sinatra/decorator'
2
+
3
+ class PostDecorator < Sinatra::Decorator::Base
4
+ include Rack::Utils
5
+
6
+ def success_message
7
+ 'Success!'
8
+ end
9
+
10
+ def error_message
11
+ message = 'Failure! '
12
+ message += self.errors.map {|key, msg| escape_html("`#{key}` #{msg}") }.join('. ')
13
+ message
14
+ end
15
+
16
+ def render_body(locals)
17
+ namespace = OpenStruct.new(locals)
18
+ ERB.new(self.body, nil, "-").result(namespace.instance_eval { binding })
19
+ end
20
+ end
21
+
@@ -0,0 +1,34 @@
1
+ require 'sinatra'
2
+ require 'sinatra/activerecord'
3
+ require 'fluentd_server/config'
4
+ require 'fluentd_server/logger'
5
+
6
+ configure do
7
+ set :show_exceptions, true
8
+ ActiveRecord::Base.logger = FluentdServer.logger
9
+ I18n.enforce_available_locales = false
10
+ end
11
+
12
+ configure :production, :development do
13
+ if FluentdServer::Config.database_url.start_with?('sqlite')
14
+ set :database, FluentdServer::Config.database_url
15
+ else
16
+ # DATABASE_URL => "postgres://randuser:randpass@randhost:randport/randdb" on heroku
17
+ db = URI.parse(FluentdServer::Config.database_url)
18
+ ActiveRecord::Base.establish_connection(
19
+ :adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
20
+ :host => db.host,
21
+ :username => db.user,
22
+ :password => db.password,
23
+ :database => db.path[1..-1],
24
+ :encoding => 'utf8'
25
+ )
26
+ end
27
+ end
28
+
29
+ configure :test do
30
+ ActiveRecord::Base.establish_connection(
31
+ :adapter => 'sqlite3',
32
+ :database => ':memory'
33
+ )
34
+ end
@@ -0,0 +1,90 @@
1
+ require 'logger'
2
+ require 'fluentd_server'
3
+ require "fluentd_server/config"
4
+
5
+ module FluentdServer
6
+ module Logger
7
+ def self.included(klass)
8
+ # To define logger *class* method
9
+ klass.extend(self)
10
+ end
11
+
12
+ # for test
13
+ def logger=(logger)
14
+ FluentdServer.logger = logger
15
+ end
16
+
17
+ def logger
18
+ FluentdServer.logger
19
+ end
20
+ end
21
+
22
+ # for test
23
+ def self.logger=(logger)
24
+ @logger = logger
25
+ end
26
+
27
+ def self.logger
28
+ return @logger if @logger
29
+
30
+ log_path = FluentdServer::Logger::Config.log_path
31
+ log_level = FluentdServer::Logger::Config.log_level
32
+ # NOTE: Please note that ruby 2.0.0's Logger has a problem on log rotation.
33
+ # Update to ruby 2.1.0. See https://github.com/ruby/ruby/pull/428 for details.
34
+ log_shift_age = FluentdServer::Logger::Config.log_shift_age
35
+ log_shift_size = FluentdServer::Logger::Config.log_shift_size
36
+ @logger = ::Logger.new(log_path, log_shift_age, log_shift_size)
37
+ @logger.level = log_level
38
+ @logger
39
+ end
40
+
41
+ class Logger::Config
42
+ def self.log_path(log_path = FluentdServer::Config.log_path)
43
+ case log_path
44
+ when 'STDOUT'
45
+ $stdout
46
+ when 'STDERR'
47
+ $stderr
48
+ else
49
+ log_path
50
+ end
51
+ end
52
+
53
+ def self.log_level(log_level = FluentdServer::Config.log_level)
54
+ case log_level
55
+ when 'debug'
56
+ ::Logger::DEBUG
57
+ when 'info'
58
+ ::Logger::INFO
59
+ when 'warn'
60
+ ::Logger::WARN
61
+ when 'error'
62
+ ::Logger::ERROR
63
+ when 'fatal'
64
+ ::Logger::FATAL
65
+ else
66
+ raise ArgumentError, "invalid log_level #{log_level}"
67
+ end
68
+ end
69
+
70
+ def self.log_shift_age(log_shift_age = FluentdServer::Config.log_shift_age)
71
+ case log_shift_age
72
+ when /\d+/
73
+ log_shift_age.to_i
74
+ when 'daily'
75
+ log_shift_age
76
+ when 'weekly'
77
+ log_shift_age
78
+ when 'monthly'
79
+ log_shift_age
80
+ else
81
+ raise ArgumentError, "invalid log_shift_age #{log_shift_age}"
82
+ end
83
+ end
84
+
85
+ def self.log_shift_size(log_shift_size = FluentdServer::Config.log_shift_size)
86
+ log_shift_size.to_i
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,10 @@
1
+ require 'sinatra/activerecord'
2
+ require 'sinatra/decorator'
3
+ require 'fluentd_server/environments'
4
+
5
+ class Post < ActiveRecord::Base
6
+ include Sinatra::Decorator::Decoratable
7
+
8
+ validates :name, presence: true
9
+ validates :body, presence: true
10
+ end
@@ -0,0 +1,3 @@
1
+ module FluentdServer
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,101 @@
1
+ require 'sinatra'
2
+ require 'sinatra/flash'
3
+ require 'sinatra/redirect_with_flash'
4
+ require 'slim'
5
+
6
+ require 'fluentd_server'
7
+ require 'fluentd_server/config'
8
+ require 'fluentd_server/environments'
9
+ require 'fluentd_server/model'
10
+ require 'fluentd_server/decorator'
11
+ require 'fluentd_server/logger'
12
+ require 'fluentd_server/web_helper'
13
+
14
+ class FluentdServer::Web < Sinatra::Base
15
+ include FluentdServer::Logger
16
+ helpers FluentdServer::WebHelper
17
+
18
+ set :dump_errors, true
19
+ set :public_folder, File.join(__dir__, '..', '..', 'public')
20
+ set :views, File.join(__dir__, '..', '..', 'views')
21
+
22
+ enable :sessions
23
+ register Sinatra::Flash
24
+ helpers Sinatra::RedirectWithFlash
25
+ register Sinatra::ActiveRecordExtension
26
+
27
+ # get ALL posts
28
+ get "/" do
29
+ @posts = Post.order("name ASC")
30
+ slim :"posts/index"
31
+ end
32
+
33
+ # create new post
34
+ get "/posts/create" do
35
+ @tab = 'create'
36
+ @title = 'Create'
37
+ @post = Post.new
38
+ slim :"posts/create"
39
+ end
40
+
41
+ post "/posts" do
42
+ @post = Post.new(params[:post])
43
+ if @post.save
44
+ redirect "posts/#{@post.id}/edit", :notice => @post.decorate.success_message
45
+ else
46
+ redirect "posts/create", :error => @post.decorate.error_message
47
+ end
48
+ end
49
+
50
+ # edit post
51
+ get "/posts/:id/edit" do
52
+ @title = 'Edit'
53
+ @post = Post.find(params[:id])
54
+ return 404 unless @post
55
+ slim :"posts/edit"
56
+ end
57
+
58
+ post "/posts/:id" do
59
+ @post = Post.find(params[:id])
60
+ return 404 unless @post
61
+ if @post.update(params[:post])
62
+ redirect "/posts/#{@post.id}/edit", :notice => @post.decorate.success_message
63
+ else
64
+ redirect "/posts/#{@post.id}/edit", :error => @post.decorate.error_message
65
+ end
66
+ end
67
+
68
+ # delete post
69
+ get "/posts/:name/delete" do
70
+ @post = Post.find_by(name: params[:name])
71
+ if @post.destroy
72
+ redirect "/", :notice => @post.decorate.success_message
73
+ else
74
+ redirect "/", :error => @post.decorate.error_message
75
+ end
76
+ end
77
+
78
+ # get ALL posts in json
79
+ get "/json/list" do
80
+ @posts = Post.order("id ASC")
81
+ content_type :json
82
+ @posts.to_json
83
+ end
84
+
85
+ # get post in json
86
+ get "/json/:name" do
87
+ @post = Post.find_by(name: params[:name])
88
+ return 404 unless @post
89
+ content_type :json
90
+ @post.to_json
91
+ end
92
+
93
+ # render api
94
+ get "/api/:name" do
95
+ @post = Post.find_by(name: params[:name])
96
+ return 404 unless @post
97
+ query_params = parse_query(request.query_string)
98
+ content_type :text
99
+ @post.decorate.render_body(query_params)
100
+ end
101
+ end
@@ -0,0 +1,91 @@
1
+ require 'cgi'
2
+ require 'fluentd_server'
3
+
4
+ module FluentdServer::WebHelper
5
+ include Rack::Utils
6
+ alias_method :h, :escape_html
7
+
8
+ # override RackUtil.parse_query
9
+ # @param qs query string
10
+ # @param d delimiter
11
+ # @return
12
+ def parse_query(qs, d=nil)
13
+ params = {}
14
+ (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
15
+ k, v = p.split('=', 2).map { |x| unescape(x) }
16
+ if k.ends_with?('[]')
17
+ k1 = k[0..-3]
18
+ if params[k1] and params[k1].class == Array
19
+ params[k1] << v
20
+ else
21
+ params[k1] = [v]
22
+ end
23
+ elsif k.ends_with?(']') and md = k.match(/^([^\[]+)\[([^\]]+)\]$/)
24
+ k1, k2 = md[1], md[2]
25
+ if params[k1] and params[k1].class == Hash
26
+ params[k1][k2] = v
27
+ else
28
+ params[k1] = { k2 => v }
29
+ end
30
+ else
31
+ params[k] = v
32
+ end
33
+ end
34
+ params
35
+ end
36
+
37
+ def url_for(url_fragment, mode=nil, options = nil)
38
+ if mode.is_a? Hash
39
+ options = mode
40
+ mode = nil
41
+ end
42
+
43
+ if mode.nil?
44
+ mode = :path_only
45
+ end
46
+
47
+ mode = mode.to_sym unless mode.is_a? Symbol
48
+ optstring = nil
49
+
50
+ if options.is_a? Hash
51
+ optstring = '?' + options.map { |k,v| "#{k}=#{URI.escape(v.to_s, /[^#{URI::PATTERN::UNRESERVED}]/)}" }.join('&')
52
+ end
53
+
54
+ case mode
55
+ when :path_only
56
+ base = request.script_name
57
+ when :full
58
+ scheme = request.scheme
59
+ if (scheme == 'http' && request.port == 80 ||
60
+ scheme == 'https' && request.port == 443)
61
+ port = ""
62
+ else
63
+ port = ":#{request.port}"
64
+ end
65
+ base = "#{scheme}://#{request.host}#{port}#{request.script_name}"
66
+ else
67
+ raise TypeError, "Unknown url_for mode #{mode.inspect}"
68
+ end
69
+ "#{base}#{url_fragment}#{optstring}"
70
+ end
71
+
72
+ def escape_url(str)
73
+ CGI.escape(str)
74
+ end
75
+
76
+ def title
77
+ @title || 'Welcome'
78
+ end
79
+
80
+ def tab
81
+ @tab || 'welcome'
82
+ end
83
+
84
+ def active(_tab)
85
+ if tab == _tab
86
+ 'active'
87
+ else
88
+ ''
89
+ end
90
+ end
91
+ end