smart_parser 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7c862e5efea46fdb350e38f6f9062cc23effb6266168987b8362839245dcc921
4
+ data.tar.gz: 1df7e38eda4d160d4bd79c48c5540b40540a711eecf12afcf693004991dc9f0a
5
+ SHA512:
6
+ metadata.gz: bf989652e214df38edcf2e25e6bfe38406471d9f6ca3da2e558d68498c62aa54ca45f5bdbc4623bed99a17a2912bcc544041c223a9e08cf786e8a1df9993495b
7
+ data.tar.gz: da06b601f51e421d0bd4fe6d43bb4f19010cd7b38d6ca4518eac4e1855d6d02d81553fca433c9a857e329bbfa50b4171584a44aa17469eb12858fae630702bf2
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,12 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ Exclude:
4
+ - bin/**/*
5
+ - exe/*
6
+ - Gemfile
7
+ DisplayCopNames: true
8
+ TargetRubyVersion: 2.7
9
+ SuggestExtensions: false
10
+
11
+ Metrics/BlockLength:
12
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ ruby "~> 2.7.2"
4
+
5
+ source 'https://rubygems.org'
6
+
7
+ # Specify your gem's dependencies in smart_parser.gemspec
8
+ gemspec
9
+
10
+ gem 'rake', '~> 12.0'
11
+ gem 'rspec', '~> 3.0'
12
+ gem 'terminal-table'
13
+
14
+ group :development do
15
+ gem 'rubocop'
16
+ end
17
+
18
+ group :test do
19
+ gem 'factory_bot'
20
+ gem 'simplecov'
21
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,83 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ smart_parser (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ activesupport (7.0.2.2)
10
+ concurrent-ruby (~> 1.0, >= 1.0.2)
11
+ i18n (>= 1.6, < 2)
12
+ minitest (>= 5.1)
13
+ tzinfo (~> 2.0)
14
+ ast (2.4.2)
15
+ concurrent-ruby (1.1.9)
16
+ diff-lcs (1.5.0)
17
+ docile (1.4.0)
18
+ factory_bot (6.2.0)
19
+ activesupport (>= 5.0.0)
20
+ i18n (1.10.0)
21
+ concurrent-ruby (~> 1.0)
22
+ minitest (5.15.0)
23
+ parallel (1.21.0)
24
+ parser (3.1.1.0)
25
+ ast (~> 2.4.1)
26
+ rainbow (3.1.1)
27
+ rake (12.3.3)
28
+ regexp_parser (2.2.1)
29
+ rexml (3.2.5)
30
+ rspec (3.11.0)
31
+ rspec-core (~> 3.11.0)
32
+ rspec-expectations (~> 3.11.0)
33
+ rspec-mocks (~> 3.11.0)
34
+ rspec-core (3.11.0)
35
+ rspec-support (~> 3.11.0)
36
+ rspec-expectations (3.11.0)
37
+ diff-lcs (>= 1.2.0, < 2.0)
38
+ rspec-support (~> 3.11.0)
39
+ rspec-mocks (3.11.0)
40
+ diff-lcs (>= 1.2.0, < 2.0)
41
+ rspec-support (~> 3.11.0)
42
+ rspec-support (3.11.0)
43
+ rubocop (1.25.1)
44
+ parallel (~> 1.10)
45
+ parser (>= 3.1.0.0)
46
+ rainbow (>= 2.2.2, < 4.0)
47
+ regexp_parser (>= 1.8, < 3.0)
48
+ rexml
49
+ rubocop-ast (>= 1.15.1, < 2.0)
50
+ ruby-progressbar (~> 1.7)
51
+ unicode-display_width (>= 1.4.0, < 3.0)
52
+ rubocop-ast (1.16.0)
53
+ parser (>= 3.1.1.0)
54
+ ruby-progressbar (1.11.0)
55
+ simplecov (0.21.2)
56
+ docile (~> 1.1)
57
+ simplecov-html (~> 0.11)
58
+ simplecov_json_formatter (~> 0.1)
59
+ simplecov-html (0.12.3)
60
+ simplecov_json_formatter (0.1.4)
61
+ terminal-table (3.0.2)
62
+ unicode-display_width (>= 1.1.1, < 3)
63
+ tzinfo (2.0.4)
64
+ concurrent-ruby (~> 1.0)
65
+ unicode-display_width (2.1.0)
66
+
67
+ PLATFORMS
68
+ ruby
69
+
70
+ DEPENDENCIES
71
+ factory_bot
72
+ rake (~> 12.0)
73
+ rspec (~> 3.0)
74
+ rubocop
75
+ simplecov
76
+ smart_parser!
77
+ terminal-table
78
+
79
+ RUBY VERSION
80
+ ruby 2.7.2p137
81
+
82
+ BUNDLED WITH
83
+ 2.1.4
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Joffily Ferreira
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.
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # SmartParser
2
+
3
+ This project aims to provide a _smart_ and easy way to parse any webserver log and print its results in a human-friendly format. It was designed with flexibility in mind. It makes it simple to change parts like Counters and Presenters.
4
+
5
+ ## Design decisions
6
+
7
+ ```ascii
8
+ ┌────────────────────────────┐
9
+ │ ├────┐
10
+ ┌──────┤ The User │ │
11
+ │ │ │ │
12
+ │ └─────────────▲──────────────┘ │
13
+ │ │ │
14
+ │ │ │
15
+ │ │ │
16
+ │ ┌──────────┴─────────┐ │
17
+ │ │ │ │
18
+ │ │ │ │
19
+ │ ┌─►│ Parser │◄─┐ │
20
+ │ │ │ │ │ │
21
+ │ │ │ │ │ │
22
+ │ │ └────────────────────┘ │ │
23
+ │ │ │ │
24
+ │ │ │ │
25
+ │ │ │ │
26
+ │ │ │ │
27
+ ▼ │ │ ▼
28
+ ┌────────┴───────────┐ ┌─────────┴──────────┐
29
+ │ │ │ │
30
+ │ │ │ │
31
+ │ Counter │ │ Presenter │
32
+ │ │ │ │
33
+ │ │ │ │
34
+ └────────────────────┘ └────────────────────┘
35
+
36
+ ```
37
+
38
+ The above diagram shows how the `Parser` can be used by the user. The `Parser` class requires two moving parts: A list of `Counter` and a `Presenter`. By default, the gem has two counters (`MostVisitedCounter` and `UniqVisitorsCounter`), and many presenters see [here](https://github.com/joffilyfe/smart_parser/tree/main/lib/smart_parser/presenters).
39
+
40
+ This design allows the user to change any required parts and create their parts. It's easier to create a new Counter or even a new Presenter, just following the signature for them.
41
+
42
+ The default counters use a `Hash` as a container for the parsed lines, it allows us to access the paths with an O(1) access time. Also, the output of counters returns the sorted array with results, it uses the Ruby Quicksort algorithm which in the worst case will do the sort with O(n^2) but on the avg, it sorts using the O(n log n) [not too bad].
43
+
44
+ Using the `Presenter` not coupled with the `Parser` or even the `Counter` allows us to implement new parsers easily, it should not take more than five minutes.
45
+
46
+ ## Installation
47
+
48
+ To use it in your application you should add this line to your Gemfile:
49
+
50
+ ```ruby
51
+ gem 'smart_parser'
52
+ ```
53
+
54
+ And then execute:
55
+
56
+ ```bash
57
+ $ bundle install
58
+ ```
59
+
60
+ Or, you can install it by yourself running this command:
61
+
62
+ ```bash
63
+ $ gem install smart_parser
64
+ ```
65
+
66
+ ## Usage
67
+
68
+ You have two ways to use this gem:
69
+ 1. As binary directly in your $PATH
70
+ 2. As library loaded into your project
71
+
72
+ ### Using as binary
73
+
74
+ Consider that you already installed the gem using the `gem install` method and installed it on your `lib` of the Ruby.
75
+
76
+ So, you can just run the following command:
77
+
78
+ ```shell
79
+ $ sparser webserver.log
80
+ ```
81
+
82
+ It includes a binary that has all Counters and Presenters and also includes additional options, to check run:
83
+
84
+ ```shell
85
+ $ sparser -h
86
+ ```
87
+
88
+ *Note*: You should take a look at the variety of `Presenters`. Try the `JSONL` for instance.
89
+
90
+ ### Using as library
91
+
92
+ This is the second way to use the gem. You can just require (`require 'smart_parser'`) and starts using the classes like:
93
+
94
+ ```ruby
95
+ parser = SmartParser::Parser.new(lines: ['/home 127.0.01'])
96
+ ```
97
+
98
+ To have more details about this use, please check the code of the binary included in the gem.
99
+
100
+ ## Contributing
101
+
102
+ Bug reports and pull requests are welcome on GitHub at https://github.com/joffilyfe/smart_parser.
103
+
104
+
105
+ ## License
106
+
107
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/exe/sparser ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require 'optparse'
6
+
7
+ if $PROGRAM_NAME == __FILE__
8
+ require_relative '../lib/smart_parser'
9
+ else
10
+ require 'smart_parser'
11
+ end
12
+ require 'benchmark'
13
+
14
+ USAGE = "Usage: sparser webserver.log [options]"
15
+
16
+ def parse_options
17
+ counters = {
18
+ mostvisited: SmartParser::Counters::MostVisitedCounter,
19
+ uniqvisitors: SmartParser::Counters::UniqVisitorsCounter
20
+ }
21
+ presenters = {
22
+ table: SmartParser::Presenters::TablePresenter,
23
+ line: SmartParser::Presenters::LinePresenter,
24
+ jsonl: SmartParser::Presenters::JSONLPresenter,
25
+ none: nil
26
+ }
27
+ options = {
28
+ counters: [SmartParser::Counters::MostVisitedCounter, SmartParser::Counters::UniqVisitorsCounter],
29
+ presenter: SmartParser::Presenters::TablePresenter,
30
+ benchmark: false
31
+ }
32
+
33
+ OptionParser.new do |opts|
34
+ opts.banner = USAGE
35
+ opts.on('-c', '--use c1,c2', Array, "Select available counters: (#{counters.keys.join(', ')})") do |selected|
36
+ unless selected.empty?
37
+ options[:counters] = selected.select { |c| counters.keys.include?(c.to_sym) }
38
+ options[:counters] = options[:counters].map { |c| counters[c.to_sym] }.flatten
39
+ end
40
+ end
41
+ opts.on('-p PRESENTER', '--presenter', presenters,
42
+ "Select the output presenter: (#{presenters.keys.join(', ')})") do |presenter|
43
+ options[:presenter] = presenter
44
+ end
45
+ opts.on('-b', '--benchmark', 'Print the benchmark for the script') do |bench|
46
+ options[:benchmark] = bench
47
+ end
48
+ end.parse!
49
+
50
+ options
51
+ end
52
+
53
+ def main
54
+ options = parse_options
55
+ logfile = File.open(ARGV[0] || abort(USAGE))
56
+
57
+ parser = SmartParser::Parser.new(
58
+ lines: logfile.readlines,
59
+ counters: options[:counters].map(&:new),
60
+ presenter: options[:presenter]
61
+ )
62
+
63
+ time = Benchmark.measure do
64
+ parser.parse!
65
+ end
66
+
67
+ parser.present
68
+ puts time if options[:benchmark]
69
+ rescue Errno::ENOENT
70
+ abort("File '#{ARGV[0]}' not found, please check if the path exists.")
71
+ rescue Errno::EISDIR
72
+ abort("The path '#{ARGV[0]}' is a directory, please use files only.")
73
+ rescue OptionParser::InvalidArgument, OptionParser::MissingArgument => e
74
+ abort(e.message)
75
+ end
76
+
77
+ main
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartParser
4
+ module Counters
5
+ # This is a super class which difines what other counters
6
+ # must implements. Every counter which inherance from this
7
+ # class will use the Hash as data container to store information
8
+ # about parsed lines.
9
+ #
10
+ # Every counter must implements the `to_a` method and it should
11
+ # return an array ordered from the most relevant to the least relevant.
12
+ #
13
+ class Counter
14
+ def initialize(container: {}, line_regex: SmartParser::LINE_REGEX)
15
+ @container = container
16
+ @line_regex = line_regex
17
+ end
18
+
19
+ def count(line)
20
+ raise NotImplementedError
21
+ end
22
+
23
+ # Returns an Array containing Arrays with two positions inside
24
+ def to_a
25
+ raise NotImplementedError
26
+ end
27
+
28
+ # Returns the description for the Counter
29
+ #
30
+ # @returns String
31
+ def description
32
+ raise NotImplementedError
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'counter'
4
+
5
+ module SmartParser
6
+ module Counters
7
+ # Count the most visited path
8
+ class MostVisitedCounter < Counter
9
+ # Parse the received line using the @line_regex and counts
10
+ # how many times the parsed `path` was received.
11
+ #
12
+ # @returns true - when the line was correctly parsed and counted
13
+ # @returns false - when the line does not matches with the line regex
14
+ def count(line)
15
+ match = @line_regex.match(line.strip)
16
+
17
+ return false if match.nil?
18
+
19
+ path = match[:path]
20
+
21
+ if @container[path].nil?
22
+ @container[path] = 1
23
+ else
24
+ @container[path] += 1
25
+ end
26
+
27
+ true
28
+ end
29
+
30
+ # Returns an Array ordered by the most accessed path to the least accessed one
31
+ #
32
+ # @returns Array
33
+ def to_a
34
+ @container.each.sort_by { |_k, v| v }.reverse.to_a
35
+ end
36
+
37
+ def description
38
+ 'Most visited'
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+ require_relative 'counter'
5
+
6
+ module SmartParser
7
+ module Counters
8
+ # Count the most visited path considering only uniq visitors
9
+ class UniqVisitorsCounter < Counter
10
+ # Parse the received line using the @line_regex and counts
11
+ # how many times the parsed `path` was received considering only unique
12
+ # visits.
13
+ #
14
+ # @returns true - when the line was correctly parsed and counted
15
+ # @returns false - when the line does not matches with the line regex
16
+ def count(line)
17
+ match = @line_regex.match(line.strip)
18
+
19
+ return false if match.nil?
20
+
21
+ path = match[:path]
22
+
23
+ @container[path] ||= Set.new
24
+ @container[path] << match[:address]
25
+
26
+ true
27
+ end
28
+
29
+ # Returns an Array ordered by the most accessed path to the least accessed one
30
+ #
31
+ # @returns Array
32
+ def to_a
33
+ @container.each.sort_by { |_k, v| v.size }.map { |k, v| [k, v.size] }.reverse
34
+ end
35
+
36
+ def description
37
+ 'Unique visitors'
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module SmartParser
6
+ module Presenters
7
+ # The JSONLPresenter implements a way to represent the output of the
8
+ # Counter.to_a as JSONL.
9
+ class JSONLPresenter
10
+ class << self
11
+ def present(rows, description)
12
+ output = String.new
13
+
14
+ rows.each do |line|
15
+ json = JSON.dump({ path: line[0], visits: line[1], description: description })
16
+ output << "#{json}\n"
17
+ end
18
+
19
+ output
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartParser
4
+ module Presenters
5
+ # The LinePresenter implements a way to represent the output of the
6
+ # Counter.to_a as a simple lines showing the number of visits.
7
+ # Every path + visits will be treat as a line for the output.
8
+ class LinePresenter
9
+ class << self
10
+ def present(rows, description)
11
+ output = String.new("#{description}\n")
12
+
13
+ rows.each do |line|
14
+ output << "#{line[0]} #{line[1]} visits\n"
15
+ end
16
+
17
+ output
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'terminal-table'
4
+
5
+ module SmartParser
6
+ module Presenters
7
+ # The TablePresenter implements a way to represent the output of the
8
+ # Counter.to_a using a Table compatible with terminals.
9
+ class TablePresenter
10
+ class << self
11
+ def present(rows, description)
12
+ Terminal::Table.new(title: description, headings: %w[Path Count], rows: rows).to_s
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartParser
4
+ VERSION = '0.0.1'
5
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'smart_parser/version'
4
+ require_relative 'smart_parser/counters/counter'
5
+ require_relative 'smart_parser/counters/most_visited_counter'
6
+ require_relative 'smart_parser/counters/uniq_visitors_counter'
7
+ require_relative 'smart_parser/presenters/line_presenter'
8
+ require_relative 'smart_parser/presenters/table_presenter'
9
+ require_relative 'smart_parser/presenters/jsonl_presenter'
10
+
11
+ module SmartParser
12
+ # Regex to search for data separeted by a space
13
+ LINE_REGEX = /(?<path>.*)\s+(?<address>.*)$/.freeze
14
+
15
+ # By defaul the MostVisitedCounter and UniqVisitorsCounter
16
+ # will be used to parse lines.
17
+ DEFAULT_COUNTERS = [
18
+ Counters::MostVisitedCounter,
19
+ Counters::UniqVisitorsCounter
20
+ ].freeze
21
+
22
+ # By default the LinePresenter will be used to display
23
+ # the results of the Parser.
24
+ DEFAULT_PRESENTER = Presenters::LinePresenter
25
+
26
+ # The Parser class join every piece of the gem and expose the
27
+ # results of the Counters and Presenters selected during its
28
+ # initialization.
29
+ #
30
+ # During the construction of a new Parse instance you must
31
+ # inject the lines that you want to parse. Also, you can select
32
+ # your own Counter and your own Presenter.
33
+ #
34
+ # ==== Attributes
35
+ # +lines+ - An Array containing strings to be parsed
36
+ # +counters+ - An Array containing zero or many Counter's.
37
+ # +presenter+ - A Presenter which will displays the parser result.
38
+ #
39
+ # ==== Examples
40
+ # # Creates a new Parser with only one Counter and with JSONLPresenter
41
+ # p = Parser.new(
42
+ # lines: ['/a 127.8.8.1'],
43
+ # counters: [SmartParser::Counters::UniqVisitorsCounter]
44
+ # presenter: SmartParser::Presenters::JSONLPresenter
45
+ # )
46
+ # # Now you should parse! and show your results
47
+ # p.parse!
48
+ # p.present
49
+ #
50
+ class Parser
51
+ attr_reader :lines
52
+ attr_accessor :presenter
53
+
54
+ def initialize(lines: [], counters: DEFAULT_COUNTERS, presenter: DEFAULT_PRESENTER)
55
+ @lines = lines
56
+ @counters = counters
57
+ @presenter = presenter
58
+ @parsed = false
59
+ end
60
+
61
+ # Verify all @lines and uses the defined counters to generate
62
+ # metrics about the log lines. It runs only once.
63
+ # If lines were parsed successfully it will returns true
64
+ # otherwise false.
65
+ #
66
+ # @returns bool
67
+ def parse!
68
+ return false if @counters.empty? || @lines.empty? || parsed?
69
+
70
+ @lines.each do |line|
71
+ @counters.each do |counter|
72
+ counter.count(line.strip)
73
+ end
74
+ end
75
+
76
+ parsed!
77
+
78
+ true
79
+ end
80
+
81
+ # Returns an Array containing data for every selected Counter.
82
+ #
83
+ # returns @array
84
+ def counters_results
85
+ @counters.map { |counter| { description: counter.description, data: counter.to_a } }
86
+ end
87
+
88
+ # Shows the parsed result using the selected Presenter.
89
+ # Note: the result will be displayed using the stdout
90
+ #
91
+ # @returns nil
92
+ def present
93
+ return if @presenter.nil?
94
+
95
+ @counters.each do |counter|
96
+ puts @presenter.present(counter.to_a, counter.description)
97
+ puts "\n"
98
+ end
99
+ end
100
+
101
+ # Checks if the parser already ran.
102
+ #
103
+ # @returns bool
104
+ def parsed?
105
+ @parsed
106
+ end
107
+
108
+ private
109
+
110
+ def parsed!
111
+ @parsed = true
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/smart_parser/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'smart_parser'
7
+ spec.version = SmartParser::VERSION
8
+ spec.authors = ['Joffily Ferreira']
9
+ spec.email = ['joffilyferreira@gmail.com']
10
+
11
+ spec.summary = 'Inspect yours webserver logs'
12
+ spec.description = 'This powerfull webserver log parser will help you count access through your routes'
13
+ spec.homepage = 'https://github.com/joffilyfe/smart_parser'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.7.2')
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = spec.homepage
19
+ spec.metadata['changelog_uri'] = spec.homepage
20
+ spec.metadata['rubygems_mfa_required'] = 'true'
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ # spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
+ end
28
+ spec.bindir = 'exe'
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ['lib']
31
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smart_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Joffily Ferreira
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-02-26 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: This powerfull webserver log parser will help you count access through
14
+ your routes
15
+ email:
16
+ - joffilyferreira@gmail.com
17
+ executables:
18
+ - sparser
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".gitignore"
23
+ - ".rspec"
24
+ - ".rubocop.yml"
25
+ - Gemfile
26
+ - Gemfile.lock
27
+ - LICENSE.txt
28
+ - README.md
29
+ - Rakefile
30
+ - exe/sparser
31
+ - lib/smart_parser.rb
32
+ - lib/smart_parser/counters/counter.rb
33
+ - lib/smart_parser/counters/most_visited_counter.rb
34
+ - lib/smart_parser/counters/uniq_visitors_counter.rb
35
+ - lib/smart_parser/presenters/jsonl_presenter.rb
36
+ - lib/smart_parser/presenters/line_presenter.rb
37
+ - lib/smart_parser/presenters/table_presenter.rb
38
+ - lib/smart_parser/version.rb
39
+ - smart_parser.gemspec
40
+ homepage: https://github.com/joffilyfe/smart_parser
41
+ licenses:
42
+ - MIT
43
+ metadata:
44
+ homepage_uri: https://github.com/joffilyfe/smart_parser
45
+ source_code_uri: https://github.com/joffilyfe/smart_parser
46
+ changelog_uri: https://github.com/joffilyfe/smart_parser
47
+ rubygems_mfa_required: 'true'
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 2.7.2
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.1.4
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Inspect yours webserver logs
67
+ test_files: []