flog_ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6d3b3da22d214f61a1580ace6ed446bce8b9dcc9
4
+ data.tar.gz: 25457d30e980c0c3800fad7b8be99cbbcca3a1a7
5
+ SHA512:
6
+ metadata.gz: 222bb9bcf2d3f7f006f67cb00cab86fb0d476d95f5b6d106a8a48259dce76fed3d8139557746cdd51ade99a9a2d6c7e612c576e693cdc9ac71e60008287a52fe
7
+ data.tar.gz: 8b874f91d68ac1865477fddbf539689b13c1953add11b19515d9e92c3e59177dcc094e7c65a9cb76d90dc5fb666b32529a2634910d38419685752abe73632f3a
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.3
5
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Ruijian Cao
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,60 @@
1
+ # Make log and consume business info easily in your rails application!
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'flog_ruby'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install flog_ruby
18
+
19
+ ## Usage
20
+
21
+ ### Get and use flogger
22
+
23
+ `flogger = Flog.get(:api)`
24
+
25
+ Here `api` is a business log group.
26
+
27
+ log your business info as your normal logger, but in better hash format.
28
+
29
+ ```ruby
30
+ flogger.info :project_visit, user_id: 123, project_id: 234, extra: {data: 'other context info.'}
31
+ ```
32
+
33
+ ### Environment and Rsyslog support
34
+
35
+ In development environment, flog write log into `log/flog/*.log` by default.
36
+
37
+ In other environment, you can configure it use rsyslog mechanism to send info to remote logger service!
38
+
39
+ ```bash
40
+ SYSLOG_ORIGIN: log entry point origin source
41
+ SYSLOG_FACILITY: rsyslog facility, default: local0
42
+ FLOG_LEVEL: logger level, default: debug
43
+ FLOG_NOT_SYSLOG: force not use rsyslog, use multi-log files
44
+ ```
45
+
46
+ ## Development
47
+
48
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
49
+
50
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
51
+
52
+ ## Contributing
53
+
54
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/flog_ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
55
+
56
+
57
+ ## License
58
+
59
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
60
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "flog_ruby"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'flog_ruby/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "flog_ruby"
8
+ spec.version = FlogRuby::VERSION
9
+ spec.authors = ["Ruijian Cao"]
10
+ spec.email = ["cao7113@hotmail.com"]
11
+
12
+ spec.summary = %q(Make log and inspect business info easily.)
13
+ spec.description = spec.summary
14
+ spec.homepage = "https://github.com/cao7113/flog_ruby"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.12"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec", "~> 3.0"
25
+ end
@@ -0,0 +1,7 @@
1
+ require "flog_ruby/version"
2
+ require "flog_ruby/logger_factory"
3
+
4
+ module FlogRuby
5
+ end
6
+
7
+ Flog = FlogRuby::LoggerFactory
@@ -0,0 +1,256 @@
1
+ require 'logger'
2
+ require 'pathname'
3
+ require 'fileutils'
4
+ require 'syslog/logger'
5
+
6
+ module FlogRuby
7
+ module Floggable
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ attr_accessor :group
12
+
13
+ ::Logger::Severity.constants.map(&:downcase).each do |level|
14
+ alias_method "raw_#{level}", level
15
+
16
+ define_method level do |tag, opts = {}|
17
+ flog(level, tag, opts)
18
+ end
19
+ end
20
+
21
+ def flog(level, tag, opts = {})
22
+ attrs = (opts || {}).with_indifferent_access
23
+ extra = attrs.delete(:extra) || {}
24
+
25
+ opt_tag = attrs.delete(:tag)
26
+ if opt_tag
27
+ extra[:msg] ||= tag
28
+ tag = opt_tag
29
+ end
30
+
31
+ # resource
32
+ resource = attrs.delete :resource
33
+ if resource
34
+ attrs[:resource_type] ||= resource.class.name
35
+ attrs[:resource_id] ||= resource&.id
36
+ end
37
+
38
+ # distinct_id
39
+ if attrs[:distinct_id].nil?
40
+ attrs[:distinct_id] = attrs[:user_id] ? attrs[:user_id] : attrs[:client_ip]
41
+ end
42
+
43
+ # role
44
+ uid = attrs[:user_id]
45
+ attrs[:role] = Flog.user_klass.find_by(id: uid)&.role if attrs[:role].nil? && uid
46
+
47
+ # error
48
+ err = extra.delete :error
49
+ extra[:backtrace] = err.backtrace.first(10).join('; ') if err && err.is_a?(Exception)
50
+
51
+ # 添加来源信息origin
52
+ origin = ENV.fetch('SYSLOG_ORIGIN', group)
53
+
54
+ body = {origin: origin, properties: attrs, extra: extra}.to_json.to_s
55
+ blk = lambda { body }
56
+ clevel = ::Logger.const_get(level.upcase)
57
+ stag = [group, tag].compact.join('_')
58
+ add(clevel, nil, stag, &blk)
59
+ #send "raw_#{level}", nil, &blk
60
+ end
61
+ end
62
+ end
63
+
64
+ # 写文件方式
65
+ class Flogger < Logger
66
+ include Floggable
67
+
68
+ attr_accessor :log_path
69
+
70
+ def initialize(logpath, shift_age = 0, shift_size = 1_048_576)
71
+ if logpath
72
+ if logpath.is_a?(Pathname)
73
+ logpath.dirname.mkpath
74
+ @log_path = logpath
75
+ elsif logpath.is_a?(IO)
76
+ @log_path = nil
77
+ else
78
+ raise "Invalid flog! #{logpath.inspect}"
79
+ end
80
+ else
81
+ raise "Invalid flog! #{logpath.inspect}"
82
+ end
83
+ super(logpath, shift_age, shift_size)
84
+ end
85
+
86
+ def logdev
87
+ instance_variable_get('@logdev')
88
+ end
89
+
90
+ def logdev2
91
+ logdev.try(:dev)
92
+ end
93
+
94
+ # Deprecated!
95
+ def method_missing(mthd, *margs, &_blk)
96
+ self.class.class_eval do
97
+ define_method mthd do |*args|
98
+ opts = args.extract_options! || {}
99
+ level = opts.delete(:level) || :info
100
+ send(level, mthd, opts)
101
+ end
102
+ end
103
+ send(mthd, *margs)
104
+ end
105
+
106
+ class Formatter < ::Logger::Formatter
107
+ def call(severity, time, progname, msg)
108
+ format = "%s, [%s] %s: %s\n".freeze
109
+ format % [severity[0..0], format_datetime(time), progname, msg2str(msg)]
110
+ end
111
+
112
+ private
113
+
114
+ def format_datetime(time)
115
+ #raw: time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ".freeze)
116
+ #Time.zone.now.iso8601(3) #=> "2016-12-06T13:04:01.703+08:00"
117
+ (time || Time.zone.now).iso8601(3) # 需要毫秒
118
+ end
119
+ end
120
+ end
121
+
122
+ # 走Syslog转发机制
123
+ class Syslogger < Syslog::Logger
124
+ include Floggable
125
+
126
+ def initialize(program_name = nil, facility = nil)
127
+ program_name = program_name.to_s
128
+
129
+ fac = (ENV['SYSLOG_FACILITY'] || 'local0').upcase
130
+ log_fac = "LOG_#{fac}"
131
+ facility ||= Syslog.const_get(log_fac)
132
+
133
+ super(program_name, facility)
134
+ end
135
+
136
+ def add(severity, message = nil, progname = nil, &block)
137
+ severity ||= ::Logger::UNKNOWN
138
+ progname ||= group
139
+ @level <= severity and
140
+ @@syslog.log((LEVEL_MAP[severity] | @facility), '%s', formatter.call(severity, Time.zone.now, progname, (message || block.call)))
141
+ true
142
+ end
143
+
144
+ class Formatter < ::Syslog::Logger::Formatter
145
+ def call(severity, time, progname, msg)
146
+ format = "%s, [%s] %s: %s\n".freeze
147
+ sev_str = format_severity(severity)
148
+ format % [sev_str[0..0], format_datetime(time), progname, clean(msg)]
149
+ end
150
+
151
+ private
152
+
153
+ # Clean up messages so they're nice and pretty.
154
+ def clean(message)
155
+ message = message.to_s.strip
156
+ message.gsub!(/\e\[[0-9;]*m/, '') # remove useless ansi color codes
157
+ message
158
+ end
159
+
160
+ # Severity label for logging (max 5 chars).
161
+ SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY).each(&:freeze).freeze
162
+
163
+ def format_severity(severity)
164
+ SEV_LABEL[severity] || 'ANY'
165
+ end
166
+
167
+ def format_datetime(time)
168
+ #(time || Time.zone.now).to_s(:iso8601)
169
+ #Time.zone.now.iso8601(3) #=> "2016-12-06T13:04:01.703+08:00"
170
+ (time || Time.zone.now).iso8601(3) # 需要毫秒
171
+ end
172
+ end
173
+ end
174
+
175
+ class LoggerFactory
176
+ cattr_accessor :root, :loggers, :mloggers, :user_klass
177
+ self.root = Pathname.new('log').join('flog')
178
+ self.loggers = {}
179
+ self.mloggers = {}
180
+
181
+ class << self
182
+ def user_klass
183
+ @user_klass ||= ::User
184
+ end
185
+
186
+ # e.g. api, core, default: to STDOUT
187
+ def get(biz_name = :stdout, level = nil)
188
+ return Flogger.new(STDOUT) if biz_name.nil? || biz_name == :stdout
189
+
190
+ biz_name = biz_name.to_sym
191
+ findit = loggers[biz_name]
192
+ return findit if findit
193
+
194
+ level ||= default_level
195
+ if syslog?
196
+ logger = Syslogger.new(biz_name)
197
+ logger.formatter = Syslogger::Formatter.new
198
+ logger.level = level
199
+ else
200
+ log_path = root.join("#{biz_name}.log")
201
+ logger = Flogger.new(log_path, 3, 10_240_000) #10M
202
+ logger.formatter = Flogger::Formatter.new
203
+ logger.level = level
204
+ logger.logdev2.sync = true
205
+ end
206
+
207
+ logger.group = biz_name
208
+ loggers[biz_name] = logger
209
+ end
210
+
211
+ def default_level
212
+ if ENV['FLOG_LEVEL']
213
+ l = ENV['FLOG_LEVEL'].upcase
214
+ return Logger::Severity.const_get(l)
215
+ end
216
+ Logger::DEBUG
217
+ end
218
+
219
+ # just temp monitor log in: log/xx.log
220
+ def mget(biz_name = :stdout, level = Logger::DEBUG)
221
+ return Flogger.new(STDOUT) if biz_name.nil? || biz_name == :stdout
222
+
223
+ biz_name = biz_name.to_sym
224
+ findit = mloggers[biz_name]
225
+ return findit if findit
226
+
227
+ # different path!!!
228
+ log_path = Pathname.new('log').join("#{biz_name}.log")
229
+ logger = Flogger.new(log_path, 3, 10_240_000) #10M
230
+
231
+ logger.formatter = Flogger::Formatter.new
232
+ logger.level = level
233
+ logger.logdev2.sync = true
234
+ mloggers[biz_name] = logger
235
+ end
236
+
237
+ # 获取有轮滚的logger
238
+ def lget(filepath, opts = {})
239
+ ::Logger.new(filepath, 3, 10_240_000)
240
+ end
241
+
242
+ def syslog?
243
+ return false if ENV['FLOG_NOT_SYSLOG']
244
+ Rails.env.production? || Rails.env.staging? ||
245
+ File.exist?('tmp/flog_using_syslog')
246
+ end
247
+
248
+ def tail(log_file, lines = nil)
249
+ return [] if log_file.blank?
250
+ lines = lines.to_i
251
+ lines = 10 if lines < 10
252
+ `tail -n #{lines} #{log_file}`.to_s.split("\n").reverse
253
+ end
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,3 @@
1
+ module FlogRuby
2
+ VERSION = "0.1.0".freeze
3
+ end
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env bash
2
+ #Rsyslog client configuration!
3
+ set -e
4
+
5
+ [ -d /etc/rsyslog.d ] || { echo No found rsyslog && exit; }
6
+
7
+ flog_conf=/etc/rsyslog.d/forward_flog.conf
8
+ flog_server=${SYSLOG_SERVER:-log.logserver.ip}
9
+ if [ -n "$SYSLOG_PORT" ];then
10
+ flog_port=$SYSLOG_PORT
11
+ else
12
+ if [ "$RAILS_ENV" = 'staging' ];then
13
+ # 将测试环境的和正式的区分开
14
+ flog_port=1524
15
+ else
16
+ flog_port=1514
17
+ fi
18
+ fi
19
+ flog_facility=${SYSLOG_FACILITY:-local0}
20
+
21
+ mv /etc/rsyslog.d /etc/rsyslog.d.bak
22
+ mkdir -p /etc/rsyslog.d
23
+
24
+ # use tcp protocol
25
+ rule="$flog_facility.* @@$flog_server:$flog_port"
26
+ echo $rule > $flog_conf
27
+ echo config rsyslog: update rule $rule into $flog_conf
28
+
29
+ service rsyslog start
30
+ echo ==rsyslog has started
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flog_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ruijian Cao
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-12-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: Make log and inspect business info easily.
56
+ email:
57
+ - cao7113@hotmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - bin/console
70
+ - bin/setup
71
+ - flog_ruby.gemspec
72
+ - lib/flog_ruby.rb
73
+ - lib/flog_ruby/logger_factory.rb
74
+ - lib/flog_ruby/version.rb
75
+ - sh/boot-syslog.sh
76
+ homepage: https://github.com/cao7113/flog_ruby
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.5.2
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Make log and inspect business info easily.
100
+ test_files: []