logfmt 0.0.9 → 0.0.10
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 +4 -4
- data/.rspec +1 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +1 -1
- data/README.md +7 -4
- data/Rakefile +4 -2
- data/bench.rb +6 -4
- data/bin/bundle +114 -0
- data/bin/console +8 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/lib/logfmt/parser.rb +100 -94
- data/lib/logfmt/version.rb +3 -1
- data/lib/logfmt.rb +11 -2
- metadata +34 -19
- data/.github/workflows/gempush.yml +0 -24
- data/.github/workflows/ruby.yml +0 -19
- data/.gitignore +0 -19
- data/logfmt.gemspec +0 -22
- data/spec/logfmt/parser_spec.rb +0 -159
- data/spec/spec_helper.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d357083dac3dea75a9cd937ac2ba24b8cfff5c11f0656749a084cc16fb6cd4a
|
4
|
+
data.tar.gz: 97aad097b305ded6c753de8c233cd2317c12dcb9834fec52047ea799d842f8ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a140be6a60d67ca2f7eb8373689e7f246e7ffadae3fba22da5820992b38df1410a5faaabc0e37ab6e318434db0ba4973b4844e74e86f3e60ef9df19aff574c8
|
7
|
+
data.tar.gz: 9df321f5d270af2e288a6de8e2391d9a05159e680ae3bfa669751a92bd0e155e30d6fc86c55f246896c20d5d274e45b93878a5f365ebb0c652c94b52d53379a2
|
data/.rspec
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
|
5
|
+
|
6
|
+
## \[Unreleased\]
|
7
|
+
|
8
|
+
## [0.0.10] 2022-04-30
|
9
|
+
### Changed
|
10
|
+
- Autoload the `Logfmt::Parser` when it's used, in preparation for the coming `Logfmt::Logger` and friends.
|
11
|
+
Alternatively you can eager-load it into memory: `require "logfmt/parser"`.
|
12
|
+
|
13
|
+
### Added
|
14
|
+
- This CHANGELOG file.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
# Logfmt
|
2
2
|
|
3
|
-
Parse log lines
|
3
|
+
Parse log lines in the logfmt style:
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
```ruby
|
6
|
+
require "logfmt/parser"
|
7
|
+
|
8
|
+
Logfmt::Parser.parse('foo=bar a=14 baz="hello kitty" cool%story=bro f %^asdf')
|
9
|
+
#=> {"foo"=>"bar", "a"=>14, "baz"=>"hello kitty", "cool%story"=>"bro", "f"=>true, "%^asdf"=>true}
|
10
|
+
```
|
data/Rakefile
CHANGED
data/bench.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
4
|
+
|
5
|
+
require "benchmark"
|
6
|
+
require "logfmt"
|
5
7
|
|
6
8
|
N = 1_000
|
7
9
|
line = 'foo=bar a=14 baz="hello kitty" ƒ=2h3s cool%story=bro f %^asdf'
|
8
10
|
|
9
11
|
Benchmark.bm(20) do |x|
|
10
|
-
x.report(
|
12
|
+
x.report("char-by-char") do
|
11
13
|
N.times do
|
12
14
|
Logfmt.parse(line)
|
13
15
|
end
|
data/bin/bundle
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
bundler_version = nil
|
28
|
+
update_index = nil
|
29
|
+
ARGV.each_with_index do |a, i|
|
30
|
+
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
31
|
+
bundler_version = a
|
32
|
+
end
|
33
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
+
bundler_version = $1
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../../Gemfile", __FILE__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
lockfile_contents = File.read(lockfile)
|
59
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
+
Regexp.last_match(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
def bundler_requirement
|
64
|
+
@bundler_requirement ||=
|
65
|
+
env_var_version || cli_arg_version ||
|
66
|
+
bundler_requirement_for(lockfile_version)
|
67
|
+
end
|
68
|
+
|
69
|
+
def bundler_requirement_for(version)
|
70
|
+
return "#{Gem::Requirement.default}.a" unless version
|
71
|
+
|
72
|
+
bundler_gem_version = Gem::Version.new(version)
|
73
|
+
|
74
|
+
requirement = bundler_gem_version.approximate_recommendation
|
75
|
+
|
76
|
+
return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0")
|
77
|
+
|
78
|
+
requirement += ".a" if bundler_gem_version.prerelease?
|
79
|
+
|
80
|
+
requirement
|
81
|
+
end
|
82
|
+
|
83
|
+
def load_bundler!
|
84
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
85
|
+
|
86
|
+
activate_bundler
|
87
|
+
end
|
88
|
+
|
89
|
+
def activate_bundler
|
90
|
+
gem_error = activation_error_handling do
|
91
|
+
gem "bundler", bundler_requirement
|
92
|
+
end
|
93
|
+
return if gem_error.nil?
|
94
|
+
require_error = activation_error_handling do
|
95
|
+
require "bundler/version"
|
96
|
+
end
|
97
|
+
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
98
|
+
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
99
|
+
exit 42
|
100
|
+
end
|
101
|
+
|
102
|
+
def activation_error_handling
|
103
|
+
yield
|
104
|
+
nil
|
105
|
+
rescue StandardError, LoadError => e
|
106
|
+
e
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
m.load_bundler!
|
111
|
+
|
112
|
+
if m.invoked_as_script?
|
113
|
+
load Gem.bin_path("bundler", "bundle")
|
114
|
+
end
|
data/bin/console
ADDED
data/bin/rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rake", "rake")
|
data/bin/rspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rspec-core", "rspec")
|
data/lib/logfmt/parser.rb
CHANGED
@@ -1,112 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../logfmt"
|
4
|
+
|
1
5
|
module Logfmt
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
6
|
+
module Parser
|
7
|
+
GARBAGE = 0
|
8
|
+
KEY = 1
|
9
|
+
EQUAL = 2
|
10
|
+
IVALUE = 3
|
11
|
+
QVALUE = 4
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
|
13
|
+
def self.numeric?(s)
|
14
|
+
s.is_a?(Numeric) || s.to_s.match?(/\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\Z/)
|
15
|
+
end
|
11
16
|
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
def self.integer?(s)
|
18
|
+
s.is_a?(Integer) || s.to_s.match?(/\A[-+]?[0-9]+\Z/)
|
19
|
+
end
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
if state == KEY
|
32
|
-
if c > ' ' && c != '"' && c != '='
|
33
|
-
state = KEY
|
34
|
-
key << c
|
35
|
-
elsif c == '='
|
36
|
-
output[key.strip] = true
|
37
|
-
state = EQUAL
|
38
|
-
else
|
39
|
-
output[key.strip] = true
|
40
|
-
state = GARBAGE
|
41
|
-
end
|
42
|
-
output[key.strip] = true if i >= line.length
|
43
|
-
next
|
44
|
-
end
|
45
|
-
if state == EQUAL
|
46
|
-
if c > ' ' && c != '"' && c != '='
|
47
|
-
value = c
|
48
|
-
state = IVALUE
|
49
|
-
elsif c == '"'
|
50
|
-
value = ''
|
51
|
-
escaped = false
|
52
|
-
state = QVALUE
|
53
|
-
else
|
54
|
-
state = GARBAGE
|
21
|
+
def self.parse(line)
|
22
|
+
output = {}
|
23
|
+
key, value = +"", +""
|
24
|
+
escaped = false
|
25
|
+
state = GARBAGE
|
26
|
+
i = 0
|
27
|
+
line.each_char do |c|
|
28
|
+
i += 1
|
29
|
+
if state == GARBAGE
|
30
|
+
if c > " " && c != '"' && c != "="
|
31
|
+
key = c
|
32
|
+
state = KEY
|
33
|
+
end
|
34
|
+
next
|
55
35
|
end
|
56
|
-
if
|
57
|
-
if
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
36
|
+
if state == KEY
|
37
|
+
if c > " " && c != '"' && c != "="
|
38
|
+
state = KEY
|
39
|
+
key << c
|
40
|
+
elsif c == "="
|
41
|
+
output[key.strip] = true
|
42
|
+
state = EQUAL
|
43
|
+
else
|
44
|
+
output[key.strip] = true
|
45
|
+
state = GARBAGE
|
62
46
|
end
|
63
|
-
output[key.strip] =
|
47
|
+
output[key.strip] = true if i >= line.length
|
48
|
+
next
|
64
49
|
end
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
value =
|
71
|
-
|
72
|
-
|
73
|
-
|
50
|
+
if state == EQUAL
|
51
|
+
if c > " " && c != '"' && c != "="
|
52
|
+
value = c
|
53
|
+
state = IVALUE
|
54
|
+
elsif c == '"'
|
55
|
+
value = +""
|
56
|
+
escaped = false
|
57
|
+
state = QVALUE
|
58
|
+
else
|
59
|
+
state = GARBAGE
|
60
|
+
end
|
61
|
+
if i >= line.length
|
62
|
+
if integer?(value)
|
63
|
+
value = value.to_i
|
64
|
+
elsif numeric?(value)
|
65
|
+
fvalue = value.to_f
|
66
|
+
value = fvalue if fvalue.finite?
|
67
|
+
end
|
68
|
+
output[key.strip] = value || true
|
74
69
|
end
|
75
|
-
|
76
|
-
state = GARBAGE
|
77
|
-
else
|
78
|
-
value << c
|
70
|
+
next
|
79
71
|
end
|
80
|
-
if
|
81
|
-
if
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
72
|
+
if state == IVALUE
|
73
|
+
if !(c > " " && c != '"')
|
74
|
+
if integer?(value)
|
75
|
+
value = value.to_i
|
76
|
+
elsif numeric?(value)
|
77
|
+
fvalue = value.to_f
|
78
|
+
value = fvalue if fvalue.finite?
|
79
|
+
end
|
80
|
+
output[key.strip] = value
|
81
|
+
state = GARBAGE
|
82
|
+
else
|
83
|
+
value << c
|
86
84
|
end
|
87
|
-
|
85
|
+
if i >= line.length
|
86
|
+
if integer?(value)
|
87
|
+
value = value.to_i
|
88
|
+
elsif numeric?(value)
|
89
|
+
fvalue = value.to_f
|
90
|
+
value = fvalue if fvalue.finite?
|
91
|
+
end
|
92
|
+
output[key.strip] = value
|
93
|
+
end
|
94
|
+
next
|
88
95
|
end
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
96
|
+
if state == QVALUE
|
97
|
+
if c == "\\"
|
98
|
+
escaped = true
|
99
|
+
value << "\\"
|
100
|
+
elsif c == '"'
|
101
|
+
if escaped
|
102
|
+
escaped = false
|
103
|
+
value.chop! << c
|
104
|
+
next
|
105
|
+
end
|
106
|
+
output[key.strip] = value
|
107
|
+
state = GARBAGE
|
108
|
+
else
|
97
109
|
escaped = false
|
98
|
-
value
|
99
|
-
next
|
110
|
+
value << c
|
100
111
|
end
|
101
|
-
|
102
|
-
state = GARBAGE
|
103
|
-
else
|
104
|
-
escaped = false
|
105
|
-
value << c
|
112
|
+
next
|
106
113
|
end
|
107
|
-
next
|
108
114
|
end
|
115
|
+
output
|
109
116
|
end
|
110
|
-
output
|
111
117
|
end
|
112
118
|
end
|
data/lib/logfmt/version.rb
CHANGED
data/lib/logfmt.rb
CHANGED
metadata
CHANGED
@@ -1,43 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logfmt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Timothée Peignier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: pry-byebug
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '3.
|
19
|
+
version: '3.9'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '3.
|
26
|
+
version: '3.9'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '13.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '13.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'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
54
|
+
version: '3.0'
|
41
55
|
description: Parse log lines in the logfmt style.
|
42
56
|
email:
|
43
57
|
- timothee.peignier@tryphon.org
|
@@ -45,24 +59,27 @@ executables: []
|
|
45
59
|
extensions: []
|
46
60
|
extra_rdoc_files: []
|
47
61
|
files:
|
48
|
-
- ".github/workflows/gempush.yml"
|
49
|
-
- ".github/workflows/ruby.yml"
|
50
|
-
- ".gitignore"
|
51
62
|
- ".rspec"
|
63
|
+
- CHANGELOG.md
|
52
64
|
- Gemfile
|
53
65
|
- README.md
|
54
66
|
- Rakefile
|
55
67
|
- bench.rb
|
68
|
+
- bin/bundle
|
69
|
+
- bin/console
|
70
|
+
- bin/rake
|
71
|
+
- bin/rspec
|
56
72
|
- lib/logfmt.rb
|
57
73
|
- lib/logfmt/parser.rb
|
58
74
|
- lib/logfmt/version.rb
|
59
|
-
- logfmt.gemspec
|
60
|
-
- spec/logfmt/parser_spec.rb
|
61
|
-
- spec/spec_helper.rb
|
62
75
|
homepage: https://github.com/cyberdelia/logfmt-ruby
|
63
76
|
licenses:
|
64
77
|
- MIT
|
65
|
-
metadata:
|
78
|
+
metadata:
|
79
|
+
bug_tracker_uri: https://github.com/cyberdelia/logfmt-ruby/issues
|
80
|
+
changelog_uri: https://github.com/cyberdelia/logfmt-ruby/blog/master/CHANGELOG.md
|
81
|
+
documentation_uri: https://github.com/cyberdelia/logfmt-ruby
|
82
|
+
source_code_uri: https://github.com/cyberdelia/logfmt-ruby
|
66
83
|
post_install_message:
|
67
84
|
rdoc_options: []
|
68
85
|
require_paths:
|
@@ -71,17 +88,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
71
88
|
requirements:
|
72
89
|
- - ">="
|
73
90
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
91
|
+
version: 2.4.0
|
75
92
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
93
|
requirements:
|
77
94
|
- - ">="
|
78
95
|
- !ruby/object:Gem::Version
|
79
96
|
version: '0'
|
80
97
|
requirements: []
|
81
|
-
rubygems_version: 3.
|
98
|
+
rubygems_version: 3.3.7
|
82
99
|
signing_key:
|
83
100
|
specification_version: 4
|
84
101
|
summary: Parse logfmt messages.
|
85
|
-
test_files:
|
86
|
-
- spec/logfmt/parser_spec.rb
|
87
|
-
- spec/spec_helper.rb
|
102
|
+
test_files: []
|
@@ -1,24 +0,0 @@
|
|
1
|
-
name: Publish
|
2
|
-
on:
|
3
|
-
release:
|
4
|
-
types: [created]
|
5
|
-
jobs:
|
6
|
-
build:
|
7
|
-
name: Build + Publish
|
8
|
-
runs-on: ubuntu-latest
|
9
|
-
steps:
|
10
|
-
- uses: actions/checkout@master
|
11
|
-
- name: Set up Ruby 2.6
|
12
|
-
uses: actions/setup-ruby@v1
|
13
|
-
with:
|
14
|
-
version: 2.6.x
|
15
|
-
- name: Publish to RubyGems
|
16
|
-
run: |
|
17
|
-
mkdir -p $HOME/.gem
|
18
|
-
touch $HOME/.gem/credentials
|
19
|
-
chmod 0600 $HOME/.gem/credentials
|
20
|
-
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
21
|
-
gem build *.gemspec
|
22
|
-
gem push *.gem
|
23
|
-
env:
|
24
|
-
GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
|
data/.github/workflows/ruby.yml
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
name: CI
|
2
|
-
on: [push]
|
3
|
-
jobs:
|
4
|
-
build:
|
5
|
-
runs-on: ubuntu-latest
|
6
|
-
strategy:
|
7
|
-
matrix:
|
8
|
-
ruby: [ '2.4', '2.5', '2.6' ]
|
9
|
-
steps:
|
10
|
-
- uses: actions/checkout@v1
|
11
|
-
- name: Set up Ruby
|
12
|
-
uses: actions/setup-ruby@v1
|
13
|
-
with:
|
14
|
-
ruby-version: ${{ matrix.ruby }}
|
15
|
-
- name: Run tests
|
16
|
-
run: |
|
17
|
-
gem install bundler
|
18
|
-
bundle install --jobs 4 --retry 3
|
19
|
-
bundle exec rspec spec
|
data/.gitignore
DELETED
data/logfmt.gemspec
DELETED
@@ -1,22 +0,0 @@
|
|
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_development_dependency 'rspec', '~> 3.0'
|
21
|
-
gem.add_development_dependency 'rake', '~> 10.3'
|
22
|
-
end
|
data/spec/logfmt/parser_spec.rb
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'spec_helper'
|
3
|
-
require 'logfmt/parser'
|
4
|
-
|
5
|
-
describe Logfmt do
|
6
|
-
it 'parse empty log line' do
|
7
|
-
data = Logfmt.parse('')
|
8
|
-
expect(data).to eq({})
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'parse whitespace only log line' do
|
12
|
-
data = Logfmt.parse("\t")
|
13
|
-
expect(data).to eq({})
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'parse key without value' do
|
17
|
-
data = Logfmt.parse('key')
|
18
|
-
expect(data).to eq('key' => true)
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'parse key without value and whitespace' do
|
22
|
-
data = Logfmt.parse(' key ')
|
23
|
-
expect(data).to eq('key' => true)
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'parse multiple single keys' do
|
27
|
-
data = Logfmt.parse('key1 key2')
|
28
|
-
expect(data).to eq('key1' => true, 'key2' => true)
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'parse unquoted value' do
|
32
|
-
data = Logfmt.parse('key=value')
|
33
|
-
expect(data).to eq('key' => 'value')
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'parse pairs' do
|
37
|
-
data = Logfmt.parse('key1=value1 key2=value2')
|
38
|
-
expect(data).to eq('key1' => 'value1', 'key2' => 'value2')
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'parse mixed single/non-single pairs' do
|
42
|
-
data = Logfmt.parse('key1=value1 key2')
|
43
|
-
expect(data).to eq('key1' => 'value1', 'key2' => true)
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'parse mixed pairs whatever the order' do
|
47
|
-
data = Logfmt.parse('key1 key2=value2')
|
48
|
-
expect(data).to eq('key1' => true, 'key2' => 'value2')
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'parse quoted value' do
|
52
|
-
data = Logfmt.parse('key="quoted value"')
|
53
|
-
expect(data).to eq('key' => 'quoted value')
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'parse escaped quote value ' do
|
57
|
-
data = Logfmt.parse('key="quoted \" value" r="esc\t"')
|
58
|
-
expect(data).to eq('key' => 'quoted " value', 'r' => 'esc\t')
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'parse mixed pairs' do
|
62
|
-
data = Logfmt.parse('key1="quoted \" value" key2 key3=value3')
|
63
|
-
expect(data).to eq('key1' => 'quoted " value', 'key2' => true, 'key3' => 'value3')
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'parse mixed characters pairs' do
|
67
|
-
data = Logfmt.parse('foo=bar a=14 baz="hello kitty" ƒ=2h3s cool%story=bro f %^asdf')
|
68
|
-
expect(data).to eq('foo' => 'bar', 'a' => 14, 'baz' => 'hello kitty',
|
69
|
-
'ƒ' => '2h3s', 'cool%story' => 'bro', 'f' => true, '%^asdf' => true)
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'parse pair with empty quote' do
|
73
|
-
data = Logfmt.parse('key=""')
|
74
|
-
expect(data).to eq('key' => '')
|
75
|
-
end
|
76
|
-
|
77
|
-
# Currently, the value comes back as "true", which could mess up stats
|
78
|
-
# Really, only "true" should come back as "true"
|
79
|
-
# it 'parse 1 as integer type' do
|
80
|
-
# data = Logfmt.parse('key=1')
|
81
|
-
# expect(data['key'].class).to eq(Fixnum)
|
82
|
-
# end
|
83
|
-
|
84
|
-
it 'parse positive integer as integer type' do
|
85
|
-
data = Logfmt.parse('key=234')
|
86
|
-
expect(data['key']).to eq(234)
|
87
|
-
expect(data['key'].class).to eq(Fixnum)
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'parse negative integer as integer type' do
|
91
|
-
data = Logfmt.parse('key=-3428')
|
92
|
-
expect(data['key']).to eq(-3428)
|
93
|
-
expect(data['key'].class).to eq(Fixnum)
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'parse positive float as float type' do
|
97
|
-
data = Logfmt.parse('key=3.342')
|
98
|
-
expect(data['key']).to eq(3.342)
|
99
|
-
expect(data['key'].class).to eq(Float)
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'parse negative float as float type' do
|
103
|
-
data = Logfmt.parse('key=-0.9934')
|
104
|
-
expect(data['key']).to eq(-0.9934)
|
105
|
-
expect(data['key'].class).to eq(Float)
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'parse exponential float as float type' do
|
109
|
-
data = Logfmt.parse('key=2.342342342342344e+18')
|
110
|
-
expect(data['key']).to eq(2.342342342342344e+18)
|
111
|
-
expect(data['key'].class).to eq(Float)
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'parse long digit string with embedded e as string' do
|
115
|
-
data = Logfmt.parse('key=2342342342342344e1818')
|
116
|
-
expect(data['key'].class).to eq(String)
|
117
|
-
end
|
118
|
-
|
119
|
-
it 'parse quoted integer as string type' do
|
120
|
-
data = Logfmt.parse('key="234"')
|
121
|
-
expect(data['key'].class).to eq(String)
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'parse quoted float as string type' do
|
125
|
-
data = Logfmt.parse('key="3.14"')
|
126
|
-
expect(data['key'].class).to eq(String)
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'parse IP address as string type' do
|
130
|
-
data = Logfmt.parse('key=10.10.10.1')
|
131
|
-
expect(data['key'].class).to eq(String)
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'parse last as integer type' do
|
135
|
-
data = Logfmt.parse('key1=4 key2=9')
|
136
|
-
expect(data['key1']).to eq(4)
|
137
|
-
expect(data['key2']).to eq(9)
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'parse string containing quotes' do
|
141
|
-
data = Logfmt.parse('key1="{\"msg\": \"hello\tworld\"}"')
|
142
|
-
expect(data['key1']).to eq('{"msg": "hello\tworld"}')
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'parse value containing equal sign' do
|
146
|
-
query = 'position=44.80450799126121%2C33.58320759981871&uid=1'
|
147
|
-
data = Logfmt.parse("method=GET query=#{query} status=200")
|
148
|
-
expect(data).to eq(
|
149
|
-
'method' => 'GET',
|
150
|
-
'query' => query,
|
151
|
-
'status' => 200
|
152
|
-
)
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'parses integers correctly' do
|
156
|
-
data = Logfmt.parse('key=111 ')
|
157
|
-
expect(data['key']).to eq(111)
|
158
|
-
end
|
159
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,16 +0,0 @@
|
|
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.run_all_when_everything_filtered = true
|
9
|
-
config.filter_run :focus
|
10
|
-
|
11
|
-
# Run specs in random order to surface order dependencies. If you find an
|
12
|
-
# order dependency and want to debug it, you can fix the order by providing
|
13
|
-
# the seed, which is printed after each run.
|
14
|
-
# --seed 1234
|
15
|
-
config.order = 'random'
|
16
|
-
end
|