logfmt 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis-ci.yml +6 -0
- data/Gemfile +3 -0
- data/Rakefile +6 -0
- data/lib/logfmt/parser.rb +42 -0
- data/lib/logfmt/version.rb +3 -0
- data/lib/logfmt.rb +2 -0
- data/logfmt.gemspec +23 -0
- data/spec/logfmt/parser_spec.rb +69 -0
- data/spec/spec_helper.rb +17 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 71bca5314e35a8e30c555b09231fd32ddef95503
|
4
|
+
data.tar.gz: a1e7abc78f3cb2a97ab3c2278e76b9f88861fdb4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8890f4c1f6ea9f08c63429c4ca48746a9d56a57d64cecb9181c30795255e27b345a394f21c16bbe37e600692f3a4e49caa46f10f4f05b457d50cd169a9cae4f8
|
7
|
+
data.tar.gz: f3d70fc871a656525b8d866c02f30140d6550d662c3ad3d009bd180a22846aa1b6c3d3bff63cfbc5a814b5357c9a82a259aa29d792160c74de8216301199b41c
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis-ci.yml
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "parslet"
|
2
|
+
|
3
|
+
module Logfmt
|
4
|
+
class Parser < Parslet::Parser
|
5
|
+
rule(:ident_byte) { match("[^ \t\r\n\f\"=]") }
|
6
|
+
rule(:string_byte) { match("[^\"\\\\]") }
|
7
|
+
rule(:garbage) { match("[ \t\r\n\f\"=]").repeat }
|
8
|
+
rule(:ident) { ident_byte >> ident_byte.repeat }
|
9
|
+
rule(:key) { ident }
|
10
|
+
rule(:value) {
|
11
|
+
(ident.as(:value) | (str('"') >> (string_byte | str('\\') >> str('"')).repeat.as(:value) >> str('"')))
|
12
|
+
}
|
13
|
+
rule(:pair) {
|
14
|
+
(key.as(:key) >> str('=') >> value) |
|
15
|
+
(key.as(:key) >> str('=')) | key.as(:key)
|
16
|
+
}
|
17
|
+
rule(:message) { (garbage >> pair.as(:pair)).repeat.as(:message) >> garbage }
|
18
|
+
root(:message)
|
19
|
+
end
|
20
|
+
|
21
|
+
class Transformer < Parslet::Transform
|
22
|
+
class Pair < Struct.new(:key, :val); end
|
23
|
+
|
24
|
+
rule(:message => subtree(:ob)) {
|
25
|
+
(ob.is_a?(Array) ? ob : [ ob ]).inject({}) { |h, p| h[p.key] = p.val; h }
|
26
|
+
}
|
27
|
+
rule(:pair => { :key => simple(:key), :value => simple(:val) }) {
|
28
|
+
Pair.new(key.to_sym, val.to_s)
|
29
|
+
}
|
30
|
+
rule(:pair => { :key => simple(:key) }) {
|
31
|
+
Pair.new(key.to_sym, true)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.parse(logs)
|
36
|
+
parser = Parser.new
|
37
|
+
transformer = Transformer.new
|
38
|
+
|
39
|
+
tree = parser.parse(logs)
|
40
|
+
transformer.apply(tree)
|
41
|
+
end
|
42
|
+
end
|
data/lib/logfmt.rb
ADDED
data/logfmt.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'logfmt/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "logfmt"
|
8
|
+
gem.version = Logfmt::VERSION
|
9
|
+
gem.authors = ["Timothée Peignier"]
|
10
|
+
gem.email = ["timothee.peignier@tryphon.org"]
|
11
|
+
gem.description = %q{Parse log lines in the logfmt style.}
|
12
|
+
gem.summary = %q{Parse logfmt messages.}
|
13
|
+
gem.homepage = "https://github.com/cyberdelia/logfmt-ruby"
|
14
|
+
gem.license = 'MIT'
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
gem.add_dependency "parslet"
|
21
|
+
gem.add_development_dependency "rspec"
|
22
|
+
gem.add_development_dependency "rake"
|
23
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'logfmt/parser'
|
3
|
+
|
4
|
+
describe Logfmt::Parser do
|
5
|
+
it 'parse empty log line' do
|
6
|
+
data = Logfmt.parse("")
|
7
|
+
expect(data).to eq({})
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'parse whitespace only log line' do
|
11
|
+
data = Logfmt.parse("\t")
|
12
|
+
expect(data).to eq({})
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'parse key without value' do
|
16
|
+
data = Logfmt.parse("key")
|
17
|
+
expect(data).to eq({:key => true})
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'parse key without value and whitespace' do
|
21
|
+
data = Logfmt.parse(" key ")
|
22
|
+
expect(data).to eq({:key => true})
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'parse multiple single keys' do
|
26
|
+
data = Logfmt.parse("key1 key2")
|
27
|
+
expect(data).to eq({:key1 => true, :key2 => true})
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'parse unquoted value' do
|
31
|
+
data = Logfmt.parse("key=value")
|
32
|
+
expect(data).to eq({:key => "value"})
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'parse pairs' do
|
36
|
+
data = Logfmt.parse("key1=value1 key2=value2")
|
37
|
+
expect(data).to eq({:key1 => "value1", :key2 => "value2"})
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'parse mixed single/non-single pairs' do
|
41
|
+
data = Logfmt.parse("key1=value1 key2")
|
42
|
+
expect(data).to eq({:key1 => "value1", :key2 => true})
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'parse mixed pairs whatever the order' do
|
46
|
+
data = Logfmt.parse("key1 key2=value2")
|
47
|
+
expect(data).to eq({:key1 => true, :key2 => "value2"})
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'parse quoted value' do
|
51
|
+
data = Logfmt.parse('key="quoted value"')
|
52
|
+
expect(data).to eq({:key => "quoted value"})
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'parse escaped quote value' do
|
56
|
+
data = Logfmt.parse('key="quoted \" value"')
|
57
|
+
expect(data).to eq({:key => 'quoted " value'})
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'parse mixed pairs' do
|
61
|
+
data = Logfmt.parse('key1="quoted \" value" key2 key3=value3')
|
62
|
+
expect(data).to eq({:key1 => 'quoted " value', :key2 => true, :key3 => "value3"})
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'parse mixed characters pairs' do
|
66
|
+
data = Logfmt.parse('foo=bar a=14 baz="hello kitty" cool%story=bro f %^asdf')
|
67
|
+
expect(data).to eq({:foo => "bar", :a => "14", :baz => "hello kitty", :"cool%story" => "bro", :f => true, :"%^asdf" => true})
|
68
|
+
end
|
69
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: logfmt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Timothée Peignier
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-05-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: parslet
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Parse log lines in the logfmt style.
|
56
|
+
email:
|
57
|
+
- timothee.peignier@tryphon.org
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- .rspec
|
64
|
+
- .travis-ci.yml
|
65
|
+
- Gemfile
|
66
|
+
- Rakefile
|
67
|
+
- lib/logfmt.rb
|
68
|
+
- lib/logfmt/parser.rb
|
69
|
+
- lib/logfmt/version.rb
|
70
|
+
- logfmt.gemspec
|
71
|
+
- spec/logfmt/parser_spec.rb
|
72
|
+
- spec/spec_helper.rb
|
73
|
+
homepage: https://github.com/cyberdelia/logfmt-ruby
|
74
|
+
licenses:
|
75
|
+
- MIT
|
76
|
+
metadata: {}
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 2.0.0
|
94
|
+
signing_key:
|
95
|
+
specification_version: 4
|
96
|
+
summary: Parse logfmt messages.
|
97
|
+
test_files:
|
98
|
+
- spec/logfmt/parser_spec.rb
|
99
|
+
- spec/spec_helper.rb
|