plextail 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Pat Allan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Plextail
2
+
3
+ Plextail tails a group of files, and passes them through to Heroku's Logplex.
4
+
5
+ ## Installation
6
+
7
+ It's a gem, so use it like you would any other gem - probably by putting it in your Gemfile:
8
+
9
+ gem 'plextail', '0.0.1'
10
+
11
+ ## Usage
12
+
13
+ Track some log files, and make sure both the Logplex token and process id are set:
14
+
15
+ Plextail.track("path", "to", "*.log") do |line|
16
+ line.token = '...'
17
+ line.process_id = 'daemon.1'
18
+ end
19
+
20
+ The line will be sent through to Heroku using the provided details. If you want to change the server, use the LOGPLEX_URI environment variable – otherwise, the default is https://east.logplex.io.
21
+
22
+ You can customise the following attributes on the yielded line object:
23
+
24
+ * `token` – the logplex token,
25
+ * `version` – the logplex version, which defaults to '<134>1',
26
+ * `timestamp` – the timestamp for the line, which defaults to the current time, in the following format: '%Y-%m-%dT%H:%M:%S.ms+00:00',
27
+ * `hostname` – host name of the log source (doesn't seem to impact Heroku's output),
28
+ * `process_id` – the source of the log file (e.g. web.1)
29
+ * `message_id` – defaults to '- -', and
30
+ * `message` – the remainder/core of the log line, which defaults to the entire raw line from the file.
31
+
32
+ The line also has two attributes available to help any custom logic you may involve in the processing: `file` (the file that has a new line appended) and `raw` (the raw line that has appeared in the file).
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create new Pull Request
41
+
42
+ ## Credits
43
+
44
+ Copyright (c) 2013, Plextail is developed and maintained by Pat Allan, and is released under the open MIT Licence.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,52 @@
1
+ class Plextail::Line
2
+ DEFAULTS = {
3
+ :version => '<134>1',
4
+ :hostname => `hostname`.strip,
5
+ :message_id => '- -'
6
+ }
7
+
8
+ attr_accessor :file, :raw, :token, :version, :timestamp, :hostname,
9
+ :process_id, :message_id, :message
10
+
11
+ def initialize(file, raw)
12
+ @file, @raw = file, raw
13
+ @version = DEFAULTS[:version]
14
+ @timestamp = current_timestamp
15
+ @hostname = DEFAULTS[:hostname]
16
+ @message_id = DEFAULTS[:message_id]
17
+ @message = raw.dup
18
+ end
19
+
20
+ def to_s
21
+ unless valid?
22
+ raise Plextail::InvalidLineError, "Missing #{missing_parts.join(', ')}"
23
+ end
24
+
25
+ string = parts.join(' ')
26
+
27
+ "#{string.bytes.to_a.length} #{string}"
28
+ end
29
+
30
+ def valid?
31
+ parts.all? { |part| part && part.length > 0 }
32
+ end
33
+
34
+ private
35
+
36
+ def current_timestamp
37
+ time = Time.now
38
+ fraction = (".%06i" % time.usec)[0, 7]
39
+ "#{time.strftime("%Y-%m-%dT%H:%M:%S")}#{fraction}+00:00"
40
+ end
41
+
42
+ def missing_parts
43
+ [
44
+ :version, :timestamp, :hostname, :token, :process_id, :message_id,
45
+ :message
46
+ ].select { |part| send(part).nil? || send(part).length == 0 }
47
+ end
48
+
49
+ def parts
50
+ [version, timestamp, hostname, token, process_id, message_id, message]
51
+ end
52
+ end
@@ -0,0 +1,46 @@
1
+ require 'pty'
2
+ require 'faraday'
3
+
4
+ class Plextail::Tracker
5
+ URL = ENV['LOGPLEX_URI'] || 'https://east.logplex.io'
6
+
7
+ def initialize(*glob)
8
+ @glob = File.join *glob
9
+ end
10
+
11
+ def pipe(&block)
12
+ file = Dir[glob].first
13
+ PTY.spawn("tail -f #{glob}") do |stdin, stdout, pid|
14
+ stdin.each do |string|
15
+ string.strip!
16
+ if string[/^==> (.+) <==$/]
17
+ file = $1
18
+ elsif string.length > 0
19
+ line = Plextail::Line.new file, string
20
+ block.call line
21
+ to_plex line
22
+ end
23
+ end
24
+ end
25
+ rescue PTY::ChildExited
26
+ puts "The child process exited!"
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :glob
32
+
33
+ def connection
34
+ @connection ||= Faraday.new(:url => URL) do |connection|
35
+ connection.use Faraday::Adapter::NetHttp
36
+ end
37
+ end
38
+
39
+ def to_plex(line)
40
+ connection.basic_auth 'token', line.token
41
+ connection.post('/logs', line.to_s) do |request|
42
+ request.headers['Content-Type'] = 'application/logplex-1'
43
+ request.headers['Content-Length'] = line.to_s.bytes.to_a.length.to_s
44
+ end
45
+ end
46
+ end
data/lib/plextail.rb ADDED
@@ -0,0 +1,11 @@
1
+ module Plextail
2
+ class InvalidLineError < StandardError
3
+ end
4
+
5
+ def self.track(*glob, &block)
6
+ Plextail::Tracker.new(*glob).pipe(&block)
7
+ end
8
+ end
9
+
10
+ require 'plextail/line'
11
+ require 'plextail/tracker'
data/plextail.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ Gem::Specification.new do |spec|
3
+ spec.name = 'plextail'
4
+ spec.version = '0.0.1'
5
+ spec.authors = ['Pat Allan']
6
+ spec.email = ['pat@freelancing-gods.com']
7
+ spec.summary = 'Pipes tailed files to Heroku Logplex'
8
+ spec.description = 'Takes tailed files in a single tail call and sends them through to Heroku Logplex with custom logplex tokens.'
9
+ spec.homepage = 'https://github.com/flying-sphinx/plextail'
10
+ spec.license = 'MIT'
11
+
12
+ spec.files = `git ls-files`.split($/)
13
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
14
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
15
+ spec.require_paths = ['lib']
16
+
17
+ spec.add_runtime_dependency 'faraday', '~> 0.8'
18
+
19
+ spec.add_development_dependency 'fakeweb', '~> 1.3.0'
20
+ spec.add_development_dependency 'fakeweb-matcher', '~> 1.2.2'
21
+ spec.add_development_dependency 'rake', '~> 10.0.4'
22
+ spec.add_development_dependency 'rspec', '~> 2.13.0'
23
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+ require 'tmpdir'
4
+ require 'timeout'
5
+ require 'fakeweb_matcher'
6
+
7
+ describe 'Plextail' do
8
+ let(:directory) { Dir.mktmpdir }
9
+
10
+ before :each do
11
+ FakeWeb.allow_net_connect = false
12
+
13
+ FakeWeb.register_uri :post, %r{east\.logplex\.io/logs}, :body => 'OK'
14
+
15
+ File.open(File.join(directory, 'data.log'), 'w') { |f| f.puts 'stuff' }
16
+ File.open(File.join(directory, 'error.log'), 'w') { |f| f.puts 'nonsense' }
17
+ end
18
+
19
+ after :each do
20
+ FileUtils.rm_rf directory
21
+ end
22
+
23
+ def track(&block)
24
+ begin
25
+ Timeout.timeout(0.1) do
26
+ Plextail.track(directory, "*.log", &block)
27
+ end
28
+ rescue Timeout::Error
29
+ #
30
+ end
31
+ end
32
+
33
+ it "passes each line through to Logplex" do
34
+ track do |line|
35
+ line.token = 'token'
36
+ line.process_id = 'spec'
37
+ end
38
+
39
+ FakeWeb.should have_requested(:post, %r{east\.logplex\.io/logs})
40
+ end
41
+
42
+ it "prompts with the correct file and line details" do
43
+ yielded_file, yielded_line = nil, nil
44
+
45
+ track do |line|
46
+ yielded_file, yielded_line = line.file, line.raw
47
+
48
+ line.token = 'token'
49
+ line.process_id = 'spec'
50
+ end
51
+
52
+ yielded_file.should == File.join(directory, 'error.log')
53
+ yielded_line.should == 'nonsense'
54
+ end
55
+
56
+ it "handles single files matching the glob" do
57
+ FileUtils.rm File.join(directory, 'error.log')
58
+ yielded_file, yielded_line = nil, nil
59
+
60
+ track do |line|
61
+ yielded_file, yielded_line = line.file, line.raw
62
+
63
+ line.token = 'token'
64
+ line.process_id = 'spec'
65
+ end
66
+
67
+ yielded_file.should == File.join(directory, 'data.log')
68
+ yielded_line.should == 'stuff'
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ require 'bundler'
2
+
3
+ Bundler.require :default, :development
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: plextail
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pat Allan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.8'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.8'
30
+ - !ruby/object:Gem::Dependency
31
+ name: fakeweb
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.3.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.3.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: fakeweb-matcher
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.2.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.2.2
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 10.0.4
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 10.0.4
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 2.13.0
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 2.13.0
94
+ description: Takes tailed files in a single tail call and sends them through to Heroku
95
+ Logplex with custom logplex tokens.
96
+ email:
97
+ - pat@freelancing-gods.com
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - Gemfile
104
+ - LICENSE.txt
105
+ - README.md
106
+ - Rakefile
107
+ - lib/plextail.rb
108
+ - lib/plextail/line.rb
109
+ - lib/plextail/tracker.rb
110
+ - plextail.gemspec
111
+ - spec/acceptance/plextail_spec.rb
112
+ - spec/spec_helper.rb
113
+ homepage: https://github.com/flying-sphinx/plextail
114
+ licenses:
115
+ - MIT
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ segments:
127
+ - 0
128
+ hash: -273195946337692726
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ segments:
136
+ - 0
137
+ hash: -273195946337692726
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 1.8.23
141
+ signing_key:
142
+ specification_version: 3
143
+ summary: Pipes tailed files to Heroku Logplex
144
+ test_files:
145
+ - spec/acceptance/plextail_spec.rb
146
+ - spec/spec_helper.rb