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
@@ -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