fluentd-server 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.env +5 -0
- data/.gitignore +17 -0
- data/.travis.yml +5 -0
- data/API.md +21 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +9 -0
- data/Procfile +1 -0
- data/README.md +127 -0
- data/Rakefile +26 -0
- data/bench/bench.rb +83 -0
- data/bench/result.md +17 -0
- data/bin/fluentd-server +7 -0
- data/config.ru +15 -0
- data/config/unicorn.conf +20 -0
- data/db/migrate/20140512203133_create_posts.rb +14 -0
- data/db/schema.rb +25 -0
- data/fluentd-server.gemspec +43 -0
- data/lib/fluentd_server.rb +1 -0
- data/lib/fluentd_server/cli.rb +64 -0
- data/lib/fluentd_server/config.rb +27 -0
- data/lib/fluentd_server/decorator.rb +21 -0
- data/lib/fluentd_server/environments.rb +34 -0
- data/lib/fluentd_server/logger.rb +90 -0
- data/lib/fluentd_server/model.rb +10 -0
- data/lib/fluentd_server/version.rb +3 -0
- data/lib/fluentd_server/web.rb +101 -0
- data/lib/fluentd_server/web_helper.rb +91 -0
- data/public/css/bootstrap.min.css +7 -0
- data/public/fonts/glyphicons-halflings-regular.eot +0 -0
- data/public/fonts/glyphicons-halflings-regular.svg +229 -0
- data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/public/fonts/glyphicons-halflings-regular.woff +0 -0
- data/public/js/bootstrap.min.js +7 -0
- data/public/js/jquery-1.10.2.min.js +6 -0
- data/public/js/jquery-1.10.2.min.map +0 -0
- data/public/js/jquery.storageapi.min.js +2 -0
- data/spec/api_spec.rb +42 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/web_helper_spec.rb +27 -0
- data/spec/web_spec.rb +55 -0
- data/views/_navbar.slim +15 -0
- data/views/layout.slim +22 -0
- data/views/posts/create.slim +19 -0
- data/views/posts/edit.slim +23 -0
- data/views/posts/index.slim +9 -0
- 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,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
|