quake-log-parser 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +6 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +2 -0
- data/README.md +83 -3
- data/docker-compose.yaml +49 -0
- data/karafka.rb +46 -0
- data/lib/quake-log-parser/kafka_topic_consumer.rb +12 -0
- data/lib/quake-log-parser/kafka_topic_reader.rb +29 -0
- data/lib/quake-log-parser/version.rb +1 -1
- data/lib/quake-log-parser.rb +2 -0
- data/quake-log-parser.gemspec +3 -0
- metadata +48 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3432357346962f3de62da5245ba27d2ff6034ed78c7692d43999ad4fe13ecb7
|
4
|
+
data.tar.gz: 0d899c7d18cc5d7b45f54367bb5a301d05509ce3acc31272abf8ea886f2087dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 193f317ca950907029fe6b476f45cfad9a264e7390f3e298441b71f4908e799c3d4cb9e503b90b507bad5d72053e4e92335e9c43ae68cf3f3e1d1741d978bbda
|
7
|
+
data.tar.gz: b4b499bea6a19fb2948cf3467183fcd870825ef61ed7638464484c7a2ad54f2e9822be0b3205cfd773fc9b34e24db4548c914a2ea9436e46d1d61cd6296234c0
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
[![Maintainability](https://api.codeclimate.com/v1/badges/8bbcb90abf1f392d7e68/maintainability)](https://codeclimate.com/github/pedrofurtado/quake-log-parser/maintainability)
|
4
4
|
![CI](https://github.com/pedrofurtado/quake-log-parser/actions/workflows/ci.yml/badge.svg)
|
5
5
|
[![codecov](https://codecov.io/gh/pedrofurtado/quake-log-parser/graph/badge.svg?token=DUC0CORI0N)](https://codecov.io/gh/pedrofurtado/quake-log-parser)
|
6
|
-
[![Gem Version](https://badge.fury.io/rb/quake-log-parser.svg)](https://badge.fury.io/rb/quake-log-parser)
|
7
6
|
|
8
7
|
Ruby gem for quake log parsing.
|
9
8
|
|
@@ -23,7 +22,7 @@ Or install it yourself as:
|
|
23
22
|
|
24
23
|
gem install quake-log-parser
|
25
24
|
|
26
|
-
## Usage
|
25
|
+
## Usage - Log reader
|
27
26
|
|
28
27
|
```ruby
|
29
28
|
require 'quake-log-parser'
|
@@ -40,6 +39,87 @@ parser.read
|
|
40
39
|
puts JSON.pretty_generate(parser.results)
|
41
40
|
```
|
42
41
|
|
42
|
+
## Usage - Emulated Kafka topic reader
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
=begin
|
46
|
+
All kafka topic messages must have this structure:
|
47
|
+
|
48
|
+
{
|
49
|
+
"lines": [
|
50
|
+
"content of line 01 with slashs escaped",
|
51
|
+
"content of line 02 with slashs escaped",
|
52
|
+
"content of line 03 with slashs escaped",
|
53
|
+
"..."
|
54
|
+
]
|
55
|
+
}
|
56
|
+
|
57
|
+
Example of message (with slashs escaped):
|
58
|
+
|
59
|
+
{
|
60
|
+
"lines": [
|
61
|
+
"0:00 InitGame: \\sv_floodProtect\\1\\sv_maxPing\\0\\sv_minPing\\0\\sv_maxRate\\10000\\sv_minRate\\0\\sv_hostname\\Code Miner Server\\g_gametype\\0\\sv_privateClients\\2\\sv_maxclients\\16\\sv_allowDownload\\0\\dmflags\\0\fraglimit\\20\\timelimit\\15\\g_maxGameClients\\0\\capturelimit\\8\\version\\ioq3 1.36 linux-x86_64 Apr 12 2009\\protocol\\68\\mapname\\q3dm17\\gamename\baseq3\\g_needpass\\0",
|
62
|
+
"20:34 ClientUserinfoChanged: 2 n\\Isgalamido\\t\\0\\model\\xian/default\\hmodel\\xian/default\\g_redteam\\g_blueteam\\c1\\4\\c2\\5\\hc\\100\\w\\0\\l\\0\\tt\\0\\tl\\0",
|
63
|
+
"20:54 Kill: 1022 2 22: <world> killed Isgalamido by MOD_TRIGGER_HURT",
|
64
|
+
"21:51 ClientUserinfoChanged: 3 n\\Dono da Bola\\t\\0\\model\\sarge/krusade\\hmodel\\sarge/krusade\\g_redteam\\g_blueteam\\c1\\5\\c2\\5\\hc\\95\\w\\0\\l\\0\\tt\\0\\tl\\0",
|
65
|
+
"22:06 Kill: 2 3 7: Isgalamido killed Dono da Bola by MOD_ROCKET_SPLASH"
|
66
|
+
]
|
67
|
+
}
|
68
|
+
=end
|
69
|
+
|
70
|
+
require 'quake-log-parser'
|
71
|
+
require 'ostruct'
|
72
|
+
|
73
|
+
if defined?(Rails)
|
74
|
+
QuakeLogParser::Logger.logger = Rails.logger
|
75
|
+
else
|
76
|
+
QuakeLogParser::Logger.logger = Logger.new($stdout)
|
77
|
+
end
|
78
|
+
|
79
|
+
quake_log_lines = [
|
80
|
+
'content of line 01 with slashs escaped',
|
81
|
+
'content of line 02 with slashs escaped',
|
82
|
+
'content of line 03 with slashs escaped',
|
83
|
+
'...'
|
84
|
+
]
|
85
|
+
|
86
|
+
emulated_messages_from_kafka = [
|
87
|
+
OpenStruct.new(payload: { 'lines' => quake_log_lines })
|
88
|
+
]
|
89
|
+
|
90
|
+
parser = QuakeLogParser::KafkaTopicReader.new(emulated_messages_from_kafka)
|
91
|
+
parser.read
|
92
|
+
|
93
|
+
puts JSON.pretty_generate(parser.results)
|
94
|
+
```
|
95
|
+
|
96
|
+
## Usage - Kafka producer inside Karafka console
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
# Enter the Karafka console with the command below:
|
100
|
+
# docker-compose up --build -d (Wait Kafka components and Karafka consumer to be ready)
|
101
|
+
# docker container exec -it quake-log-parser_kafka_consumer_1 bundle exec karafka console
|
102
|
+
|
103
|
+
# Then, open a second terminal to see logs of Karafka consumer with the command below:
|
104
|
+
# docker container logs -f quake-log-parser_kafka_consumer_1 | grep -i 'quake'
|
105
|
+
|
106
|
+
# Then, run the commands below to produce a message to a Kafka topic:
|
107
|
+
|
108
|
+
topic_name = 'quake_log_parser_topic'
|
109
|
+
key = SecureRandom.uuid
|
110
|
+
payload = {
|
111
|
+
"lines" => [
|
112
|
+
"0:00 InitGame: \\sv_floodProtect\\1\\sv_maxPing\\0\\sv_minPing\\0\\sv_maxRate\\10000\\sv_minRate\\0\\sv_hostname\\Code Miner Server\\g_gametype\\0\\sv_privateClients\\2\\sv_maxclients\\16\\sv_allowDownload\\0\\dmflags\\0\fraglimit\\20\\timelimit\\15\\g_maxGameClients\\0\\capturelimit\\8\\version\\ioq3 1.36 linux-x86_64 Apr 12 2009\\protocol\\68\\mapname\\q3dm17\\gamename\baseq3\\g_needpass\\0",
|
113
|
+
"20:34 ClientUserinfoChanged: 2 n\\Isgalamido\\t\\0\\model\\xian/default\\hmodel\\xian/default\\g_redteam\\g_blueteam\\c1\\4\\c2\\5\\hc\\100\\w\\0\\l\\0\\tt\\0\\tl\\0",
|
114
|
+
"20:54 Kill: 1022 2 22: <world> killed Isgalamido by MOD_TRIGGER_HURT",
|
115
|
+
"21:51 ClientUserinfoChanged: 3 n\\Dono da Bola\\t\\0\\model\\sarge/krusade\\hmodel\\sarge/krusade\\g_redteam\\g_blueteam\\c1\\5\\c2\\5\\hc\\95\\w\\0\\l\\0\\tt\\0\\tl\\0",
|
116
|
+
"22:06 Kill: 2 3 7: Isgalamido killed Dono da Bola by MOD_ROCKET_SPLASH"
|
117
|
+
]
|
118
|
+
}
|
119
|
+
producer = Karafka.producer.produce_sync(topic: topic_name, payload: payload.to_json, key: key)
|
120
|
+
Karafka.logger.info("[QuakeLogParser::KafkaTopicProducer] send_sync topic=#{topic_name} key=#{key} offset=#{producer.offset} partition=#{producer.partition} payload=#{payload}")
|
121
|
+
```
|
122
|
+
|
43
123
|
## Execute tests/specs
|
44
124
|
|
45
125
|
To execute gem tests locally, use Docker with the commands below:
|
@@ -56,7 +136,7 @@ docker run --rm -v $(pwd):/app/ -it quake-log-parser_specs
|
|
56
136
|
|
57
137
|
# Or, if you want to run a example of usage of gem,
|
58
138
|
# you can run the command below.
|
59
|
-
docker run --rm -v $(pwd):/app/ -it quake-log-parser_specs ruby real_example_to_run.rb
|
139
|
+
docker run --rm -v $(pwd):/app/ -it quake-log-parser_specs bundle exec ruby real_example_to_run.rb
|
60
140
|
```
|
61
141
|
|
62
142
|
## Contributing
|
data/docker-compose.yaml
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
version: '3'
|
2
|
+
|
3
|
+
services:
|
4
|
+
zookeeper:
|
5
|
+
restart: always
|
6
|
+
image: confluentinc/cp-zookeeper:7.6.0
|
7
|
+
environment:
|
8
|
+
ZOOKEEPER_CLIENT_PORT: 2181
|
9
|
+
|
10
|
+
kafka:
|
11
|
+
restart: always
|
12
|
+
image: confluentinc/cp-kafka:7.6.0
|
13
|
+
depends_on:
|
14
|
+
- zookeeper
|
15
|
+
ports:
|
16
|
+
- "4000:9092"
|
17
|
+
- "3004:9094"
|
18
|
+
environment:
|
19
|
+
KAFKA_BROKER_ID: 1
|
20
|
+
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
|
21
|
+
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
|
22
|
+
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
|
23
|
+
KAFKA_LISTENERS: INTERNAL://:9092,OUTSIDE://:9094
|
24
|
+
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:9092,OUTSIDE://host.docker.internal:9094
|
25
|
+
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT
|
26
|
+
|
27
|
+
control-center:
|
28
|
+
restart: always
|
29
|
+
image: confluentinc/cp-enterprise-control-center:7.6.0
|
30
|
+
hostname: control-center
|
31
|
+
depends_on:
|
32
|
+
- kafka
|
33
|
+
ports:
|
34
|
+
- "9998:9021"
|
35
|
+
environment:
|
36
|
+
CONTROL_CENTER_BOOTSTRAP_SERVERS: 'kafka:9092'
|
37
|
+
CONTROL_CENTER_REPLICATION_FACTOR: 1
|
38
|
+
CONTROL_CENTER_CONNECT_CLUSTER: http://kafka-connect:8083
|
39
|
+
PORT: 9021
|
40
|
+
|
41
|
+
kafka_consumer:
|
42
|
+
depends_on:
|
43
|
+
- kafka
|
44
|
+
restart: always
|
45
|
+
image: ruby:3.1.6
|
46
|
+
working_dir: /app
|
47
|
+
volumes:
|
48
|
+
- ./:/app
|
49
|
+
command: /bin/bash -c "bundle install && bundle exec karafka-web migrate && bundle exec karafka topics migrate && bundle exec karafka server"
|
data/karafka.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
$stdout.sync = true
|
2
|
+
$stderr.sync = true
|
3
|
+
|
4
|
+
ENV['KARAFKA_ENV'] ||= 'development'
|
5
|
+
Bundler.require(:default, ENV['KARAFKA_ENV'])
|
6
|
+
|
7
|
+
require_relative 'lib/quake-log-parser'
|
8
|
+
|
9
|
+
class KarafkaApp < Karafka::App
|
10
|
+
setup do |config|
|
11
|
+
config.kafka = {
|
12
|
+
'bootstrap.servers': 'kafka:9092',
|
13
|
+
'allow.auto.create.topics': false
|
14
|
+
}
|
15
|
+
config.client_id = 'quake_log_parser_client'
|
16
|
+
config.initial_offset = 'earliest'
|
17
|
+
config.consumer_persistence = ENV['KARAFKA_ENV'] != 'development'
|
18
|
+
end
|
19
|
+
|
20
|
+
Karafka.monitor.subscribe(Karafka::Instrumentation::LoggerListener.new)
|
21
|
+
Karafka.producer.monitor.subscribe(
|
22
|
+
WaterDrop::Instrumentation::LoggerListener.new(
|
23
|
+
Karafka.logger,
|
24
|
+
log_messages: false
|
25
|
+
)
|
26
|
+
)
|
27
|
+
|
28
|
+
routes.draw do
|
29
|
+
topic :quake_log_parser_topic do
|
30
|
+
config(partitions: 3)
|
31
|
+
consumer QuakeLogParser::KafkaTopicConsumer
|
32
|
+
dead_letter_queue(
|
33
|
+
topic: 'quake_log_parser_dead_letter_topic',
|
34
|
+
max_retries: 0,
|
35
|
+
independent: false
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Karafka::Web.setup do |config|
|
42
|
+
config.ui.sessions.secret = 'dda09abf2cbd7d2e171dc44ed11877560a8bbc1ddbf54d2a58b0171634863513'
|
43
|
+
config.tracking.interval = 5_000
|
44
|
+
end
|
45
|
+
|
46
|
+
Karafka::Web.enable!
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'karafka'
|
2
|
+
|
3
|
+
module QuakeLogParser
|
4
|
+
class KafkaTopicConsumer < ::Karafka::BaseConsumer
|
5
|
+
def consume
|
6
|
+
::Karafka.logger.info "[QuakeLogParser::KafkaTopicConsumer] Consuming #{messages.size} messages from TOPIC #{topic.name}"
|
7
|
+
kafka_topic_reader = ::QuakeLogParser::KafkaTopicReader.new(messages)
|
8
|
+
kafka_topic_reader.read
|
9
|
+
::Karafka.logger.info "[QuakeLogParser::KafkaTopicConsumer] Results: #{kafka_topic_reader.results}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module QuakeLogParser
|
2
|
+
class KafkaTopicReader
|
3
|
+
def initialize(messages)
|
4
|
+
@messages = messages
|
5
|
+
@line_handler = QuakeLogParser::LineHandler.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def read
|
9
|
+
@messages.each do |message|
|
10
|
+
if message.payload['lines']
|
11
|
+
message.payload['lines'].each do |line|
|
12
|
+
case line
|
13
|
+
when QuakeLogParser::Patterns.new_game
|
14
|
+
@line_handler.handle_new_game(line)
|
15
|
+
when QuakeLogParser::Patterns.new_player
|
16
|
+
@line_handler.handle_new_player(line)
|
17
|
+
when QuakeLogParser::Patterns.new_kill
|
18
|
+
@line_handler.handle_new_kill(line)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def results
|
26
|
+
@line_handler.results
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/quake-log-parser.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require_relative 'quake-log-parser/version'
|
2
|
+
require_relative 'quake-log-parser/kafka_topic_reader'
|
3
|
+
require_relative 'quake-log-parser/kafka_topic_consumer'
|
2
4
|
require_relative 'quake-log-parser/logger'
|
3
5
|
require_relative 'quake-log-parser/patterns'
|
4
6
|
require_relative 'quake-log-parser/kill'
|
data/quake-log-parser.gemspec
CHANGED
@@ -21,6 +21,9 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
22
22
|
spec.require_paths = ['lib']
|
23
23
|
|
24
|
+
spec.add_dependency 'karafka'
|
25
|
+
spec.add_dependency 'karafka-web'
|
26
|
+
spec.add_development_dependency 'karafka-testing'
|
24
27
|
spec.add_development_dependency 'rake'
|
25
28
|
spec.add_development_dependency 'rspec'
|
26
29
|
spec.add_development_dependency 'rubocop'
|
metadata
CHANGED
@@ -1,15 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quake-log-parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pedro Furtado
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-09-
|
11
|
+
date: 2024-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: karafka
|
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: karafka-web
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
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: karafka-testing
|
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'
|
13
55
|
- !ruby/object:Gem::Dependency
|
14
56
|
name: rake
|
15
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,8 +117,12 @@ files:
|
|
75
117
|
- Rakefile
|
76
118
|
- bin/console
|
77
119
|
- bin/setup
|
120
|
+
- docker-compose.yaml
|
121
|
+
- karafka.rb
|
78
122
|
- lib/quake-log-parser.rb
|
79
123
|
- lib/quake-log-parser/game.rb
|
124
|
+
- lib/quake-log-parser/kafka_topic_consumer.rb
|
125
|
+
- lib/quake-log-parser/kafka_topic_reader.rb
|
80
126
|
- lib/quake-log-parser/kill.rb
|
81
127
|
- lib/quake-log-parser/line_handler.rb
|
82
128
|
- lib/quake-log-parser/log_reader.rb
|