logglier 0.0.2 → 0.0.3

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.
data/README.md CHANGED
@@ -7,18 +7,43 @@ Posts Logger messages to Loggly using the HTTP API.
7
7
  Usage
8
8
  -----
9
9
 
10
- require 'logglier'
10
+ require 'logglier'
11
11
 
12
- log = Logglier.new(<INPUT URL>)
12
+ log = Logglier.new(<INPUT URL>)
13
13
 
14
- log.info("hello from logglier")
14
+ log.info("hello from logglier")
15
+
16
+
17
+ ### With Rails
18
+
19
+ config/environments/production.rb
20
+
21
+ RailsApplication::Application.configure do
22
+ config.logger = Logglier.new(<INPUT URL>)
23
+ end
24
+
25
+
26
+ Input URLs
27
+ -------
28
+
29
+ ### HTTP Inputs
30
+ Logglier.new('https://logs.loggly.com/inputs/<id>')
31
+
32
+ The id is provided by loggly, look at the input's details page
33
+
34
+ ### Syslog UDP Inputs
35
+
36
+ Logglier.new('udp://<hostname>:<port>/<facility>')
37
+
38
+ The facility is optional and defaults to 16 (local0) if none is
39
+ specified.
15
40
 
16
41
 
17
42
  TODO
18
43
  -----
19
44
 
45
+ * key=value Loggly stuff.
20
46
  * Alternative https implementations (Typheous, Excon, etc). May be
21
47
  faster?
22
- * Option to use Syslog (via UDP and/or TCP) inputs. Possibly faster than
23
- the https inputs.
48
+ * Option to use Syslog TCP inputs. Possibly faster than the https inputs.
24
49
  * Do logging in a seperate thread. Is this useful? Too complex?
@@ -0,0 +1,42 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+
4
+ module Logglier
5
+
6
+ module Client
7
+
8
+ class HTTP
9
+ include Logglier::Client::InstanceMethods
10
+
11
+ attr_reader :input_uri, :http
12
+
13
+ def initialize(opts={})
14
+ setup_input_uri(opts)
15
+
16
+ @http = Net::HTTP.new(@input_uri.host, @input_uri.port)
17
+ if @input_uri.scheme == 'https'
18
+ @http.use_ssl = true
19
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
20
+ end
21
+
22
+ @http.read_timeout = opts[:read_timeout] || 2
23
+ @http.open_timeout = opts[:open_timeout] || 2
24
+ end
25
+
26
+ # Required by Logger::LogDevice
27
+ def write(message)
28
+ begin
29
+ @http.start { @http.request_post(@input_uri.path, message) }
30
+ rescue TimeoutError => e
31
+ $stderr.puts "WARNING: TimeoutError posting message: #{message}"
32
+ end
33
+ end
34
+
35
+ # Required by Logger::LogDevice
36
+ def close
37
+ nil
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,94 @@
1
+ require 'socket'
2
+ require 'uri'
3
+ require 'pp'
4
+
5
+ module Logglier
6
+
7
+ module Client
8
+
9
+ class Syslog
10
+ include Logglier::Client::InstanceMethods
11
+
12
+ attr_reader :input_uri, :facility
13
+
14
+ def initialize(opts={})
15
+ setup_input_uri(opts)
16
+ @syslog = UDPSocket.new()
17
+ @syslog.connect(@input_uri.host, @input_uri.port)
18
+
19
+ unless @input_uri.path.empty?
20
+ @facility = @input_uri.path.split('/')[1]
21
+ if @facility and @facility.to_i <= 23 && @facility.to_i >= 0
22
+ @facility = @facility.to_i
23
+ else
24
+ raise Logglier::UnknownFacility.new(@facility.to_s)
25
+ end
26
+ else
27
+ @facility = 16
28
+ end
29
+
30
+ @hostname = Socket.gethostname.split('.').first
31
+ end
32
+
33
+ # Required by Logger::LogDevice
34
+ def write(message)
35
+ begin
36
+ pp message
37
+ @syslog.send(message,0)
38
+ rescue TimeoutError => e
39
+ $stderr.puts "WARNING: TimeoutError posting message: #{message}"
40
+ end
41
+ end
42
+
43
+ # Required by Logger::LogDevice
44
+ def close
45
+ @syslog.close
46
+ end
47
+
48
+ # Specifies the date/time format for this client
49
+ def datetime_format
50
+ "%b %e %H:%M:%S"
51
+ end
52
+
53
+ # Syslog specific PRI calculation.
54
+ # See RFC3164 4.1.1
55
+ def pri(severity)
56
+ @facility + case severity
57
+ when "FATAL"
58
+ 0
59
+ when "ERROR"
60
+ 3
61
+ when "WARN"
62
+ 4
63
+ when "INFO"
64
+ 6
65
+ when "DEBUG"
66
+ 7
67
+ end
68
+ end
69
+
70
+ # Generate a syslog compat message
71
+ # See RFC3164 4.1.1 - 4.1.3
72
+ def formatter
73
+ proc do |severity, datetime, progname, msg|
74
+ message = "<#{pri(severity)}>#{datetime.strftime(datetime_format)} #{@hostname} "
75
+ if progname
76
+ message << "#{progname}: "
77
+ else
78
+ message << "#{$0}: "
79
+ end
80
+ message << "severity=#{severity},"
81
+ case msg
82
+ when Hash
83
+ msg.inject(message) {|m,v| m << "#{v[0]}=#{v[1]}" }
84
+ when String
85
+ message << msg
86
+ else
87
+ message << msg.inspect
88
+ end
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+ end
@@ -1,47 +1,47 @@
1
- require 'net/https'
2
- require 'uri'
3
-
4
1
  module Logglier
5
- class Client
6
-
7
- attr_reader :input_uri, :http
8
-
9
- def initialize(opts={})
10
- opts = { :input_url => opts } if opts.is_a?(String)
11
- @input_uri = opts[:input_url]
2
+ module Client
12
3
 
4
+ def self.new(opts={})
13
5
  if opts.nil? or opts.empty?
14
6
  raise InputURLRequired.new
15
7
  end
8
+
9
+ opts = { :input_url => opts } if opts.is_a?(String)
16
10
 
17
11
  begin
18
- @input_uri = URI.parse(@input_uri)
12
+ input_uri = URI.parse(opts[:input_url])
19
13
  rescue URI::InvalidURIError => e
20
- raise InputURLRequired.new("Invalid Input URL: #{@input_uri}")
14
+ raise InputURLRequired.new("Invalid Input URL: #{input_uri}")
21
15
  end
22
16
 
23
- @http = Net::HTTP.new(@input_uri.host, @input_uri.port)
24
- if @input_uri.scheme == 'https'
25
- @http.use_ssl = true
26
- @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
17
+ case input_uri.scheme
18
+ when 'http', 'https'
19
+ Logglier::Client::HTTP.new(opts)
20
+ when 'udp', 'tcp'
21
+ Logglier::Client::Syslog.new(opts)
22
+ else
23
+ raise Logglier::UnsupportedScheme.new("#{input_uri.scheme} is unsupported")
27
24
  end
28
-
29
- @http.read_timeout = opts[:read_timeout] || 2
30
- @http.open_timeout = opts[:open_timeout] || 2
25
+
31
26
  end
32
27
 
33
- # Required by Logger::LogDevice
34
- def write(message)
35
- begin
36
- @http.start { @http.request_post(@input_uri.path, message) }
37
- rescue TimeoutError => e
38
- $stderr.puts "WARNING: TimeoutError posting message: #{message}"
28
+ module InstanceMethods
29
+
30
+ def setup_input_uri(opts)
31
+ @input_uri = opts[:input_url]
32
+
33
+ begin
34
+ @input_uri = URI.parse(@input_uri)
35
+ rescue URI::InvalidURIError => e
36
+ raise InputURLRequired.new("Invalid Input URL: #{@input_uri}")
37
+ end
39
38
  end
40
- end
41
39
 
42
- # Required by Logger::LogDevice
43
- def close
44
- nil
45
40
  end
41
+
46
42
  end
47
43
  end
44
+
45
+ require File.join(File.dirname(__FILE__), 'client', 'http')
46
+ require File.join(File.dirname(__FILE__), 'client', 'syslog')
47
+
@@ -1,3 +1,3 @@
1
1
  module Logglier
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
data/lib/logglier.rb CHANGED
@@ -5,9 +5,22 @@ require 'logger'
5
5
  module Logglier
6
6
 
7
7
  class InputURLRequired < ArgumentError; end
8
+ class UnsupportedScheme < ArgumentError; end
9
+ class UnknownFacility < ArgumentError; end
8
10
 
9
11
  def self.new(opts={})
10
- Logger.new(Logglier::Client.new(opts))
12
+ client = Logglier::Client.new(opts)
13
+ logger = Logger.new(client)
14
+
15
+ if client.respond_to?(:formatter)
16
+ logger.formatter = client.formatter
17
+ end
18
+
19
+ if client.respond_to?(:datetime_format)
20
+ logger.datetime_format = client.datetime_format
21
+ end
22
+
23
+ logger
11
24
  end
12
25
 
13
26
  end
data/spec/client_spec.rb CHANGED
@@ -14,15 +14,38 @@ describe Logglier::Client do
14
14
 
15
15
  context "a single string param" do
16
16
 
17
- context "that is a valid uri" do
17
+ context "that is a valid http uri" do
18
18
 
19
- it "should return and instance of itself" do
19
+ it "should return an instance of the proper client" do
20
20
  log = Logglier::Client.new('http://localhost')
21
- log.should be_an_instance_of Logglier::Client
21
+ log.should be_an_instance_of Logglier::Client::HTTP
22
22
  end
23
23
 
24
24
  end
25
25
 
26
+ context "that is a valid udp uri" do
27
+
28
+ it "should return an instance of the proper client" do
29
+ log = Logglier::Client.new('udp://logs.loggly.com:42538')
30
+ log.should be_an_instance_of Logglier::Client::Syslog
31
+ end
32
+ end
33
+
34
+ context "that is a valid tcp uri" do
35
+
36
+ it "should return an instance of the proper client" do
37
+ log = Logglier::Client.new('tcp://logs.loggly.com:42538')
38
+ log.should be_an_instance_of Logglier::Client::Syslog
39
+ end
40
+ end
41
+
42
+ context "valid url with a scheme not supported" do
43
+
44
+ it "should raise an error" do
45
+ expect { Logglier::Client.new('foo://bar:1234') }.to raise_error Logglier::UnsupportedScheme
46
+ end
47
+ end
48
+
26
49
  context "that is NOT a valid uri" do
27
50
 
28
51
  it "should raise an error" do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logglier
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Edward Muller (aka freeformz)
@@ -66,6 +66,8 @@ files:
66
66
  - ./lib/logglier.rb
67
67
  - ./lib/logglier/client.rb
68
68
  - ./lib/logglier/version.rb
69
+ - ./lib/logglier/client/http.rb
70
+ - ./lib/logglier/client/syslog.rb
69
71
  - ./spec/client_spec.rb
70
72
  - ./spec/logglier_spec.rb
71
73
  - ./spec/spec_helper.rb