in_kafka: time_source record drops the time parsed by apache2, syslog and some regexp parsers
Maintainers usually reply within 2 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 84/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- kafka, ruby
- Domain
- backend, stream-processing
Research direction
Start in lib/fluent/plugin/in_kafka.rb around the configure-time consumes_record_time_key check described in the issue, then compare how #598 handles parsed_time in in_kafka_group and in_rdkafka_group. Reproduce with the included script or the stated apache2, syslog, and regexp cases; done means each event uses the parsed message time when the record has no configured time field.
Written by the indexing model from the issue text.
Description
Describe the bug
With time_source record and a custom parser, in_kafka drops the time that the parser returns in some cases. The event then gets the current time. No warning is logged.
in_kafka decides at configure time whether the parser consumes the record time:
consumes_record_time_key = @custom_parser.time_key == @record_time_key && !@custom_parser.keep_time_key
https://github.com/fluent/fluent-plugin-kafka/blob/4a408fb/lib/fluent/plugin/in_kafka.rb#L190
This guess is false in the following cases, although the parser removes the time field from the record:
format apache2andformat syslog. Theirtime_keyis nil.format regexpwithtime_key ts, whilerecord_time_keyistime(the default).
So the parsed time is not passed on. With time_format set, the record has no time field, and the event gets Fluent::Engine.now.
#598 changed in_kafka_group and in_rdkafka_group to decide this at run time (parsed_time && !record.has_key?(@record_time_key)). in_kafka still uses the guess added in #592.
This affects master only. #592 is not released yet (0.19.9 was released before it).
To Reproduce
Use the configuration below and send this message to the topic:
192.168.0.1 - - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0"
I reproduced it without a broker. The script below calls TopicWatcher#consume with a stub client that returns one message.
Results on master (4a408fb):
| format | event time |
|---|---|
apache2 |
current time |
syslog |
current time |
regexp with time_key ts |
current time |
regexp with time_key time |
2013-02-28 03:00:00 UTC (correct) |
Expected behavior
The event time is the time in the message. For the apache2 example, it is 2013-02-28 03:00:00 UTC.
Your Environment
- Fluentd version: 1.20.1
- TD Agent version: -
- fluent-plugin-kafka version: master (4a408fb)
- ruby-kafka version: 1.5.0
- Ruby version: 4.0.9
- Operating system: Linux
Your Configuration
<source>
@type kafka
brokers localhost:9092
topics test
time_source record
format apache2
time_format %d/%b/%Y:%H:%M:%S %z
</source>
Your Error Log
No error or warning is logged.
Additional context
A possible fix is the same check as #598. Use the parsed time when parsed_time && !record.has_key?(@record_time_key). I can send a PR.
Reproduction script (run with bundle exec ruby -Ilib repro.rb in this repository)
require 'fluent/test'
require 'fluent/test/driver/input'
require 'fluent/plugin/in_kafka'
Fluent::Test.setup
Msg = Struct.new(:value, :offset, :key, :create_time)
class FakeKafka
def initialize(msgs)
@msgs = msgs
end
def fetch_messages(**)
@msgs
end
end
class FakeRouter
attr_reader :events
def initialize
@events = []
end
def emit_stream(tag, es)
es.each { |t, r| @events << [tag, t, r] }
end
end
def run_case(name, conf, value)
d = Fluent::Test::Driver::Input.new(Fluent::KafkaInput).configure(conf)
i = d.instance
iv = ->(n) { i.instance_variable_get(n) }
router = FakeRouter.new
te = Fluent::KafkaInput::TopicEntry.new('test', 0, 0)
tw = Fluent::KafkaInput::TopicWatcher.new(
te, FakeKafka.new([Msg.new(value, 0, nil, Time.at(1_600_000_000))]), 1,
iv.(:@parser_proc), nil, nil, nil, router, nil,
iv.(:@time_source), iv.(:@record_time_key), iv.(:@time_parser),
iv.(:@tag_source), iv.(:@record_tag_key), {}
)
tw.consume
parser = iv.(:@custom_parser)
puts "== #{name}"
puts " parser time_key=#{parser.time_key.inspect} keep_time_key=#{parser.keep_time_key.inspect} record_time_key=#{iv.(:@record_time_key).inspect}"
router.events.each do |tag, t, r|
puts " tag=#{tag} time=#{t.inspect} (#{Time.at(t.to_r).utc}) record=#{r.inspect}"
end
end
base = %[
@type kafka
brokers localhost:9092
topics test
time_source record
]
run_case('apache2', base + %[
format apache2
time_format %d/%b/%Y:%H:%M:%S %z
], '192.168.0.1 - - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0"')
run_case('regexp with time_key ts', base + %[
format /^(?<ts>[^ ]+) (?<message>.*)$/
time_key ts
time_format %Y-%m-%dT%H:%M:%S%z
], '2013-02-28T12:00:00+0900 hello')
run_case('regexp with time_key time (guess matches)', base + %[
format /^(?<time>[^ ]+) (?<message>.*)$/
time_format %Y-%m-%dT%H:%M:%S%z
], '2013-02-28T12:00:00+0900 hello')
run_case('syslog', base + %[
format syslog
time_format %b %d %H:%M:%S
], 'Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test')
- Dominant language
- Ruby
- Stars
- 307
- Forks
- 179
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 22
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from fluent/fluent-plugin-kafka
-
kafka2, rdkafka2: Support record_accessor syntax in message_key_key, partition_key_key and partition_keyPossibly taken @NopeCharon claimed this today. Openenhancement
Difficulty 3/5 1-2 days Newbie friendliness 65/100
fluent/fluent-plugin-kafka#619 ·
Maintainers usually reply within 2 days
-
bug
Difficulty 3/5 1-2 days Newbie friendliness 55/100
fluent/fluent-plugin-kafka#618 ·
Maintainers usually reply within 2 days
-
in_kafka and in_kafka_group retry the same messages forever when the output cannot format a recordOpenbug
Difficulty 4/5 3-5 days Newbie friendliness 55/100
fluent/fluent-plugin-kafka#617 ·
Maintainers usually reply within 2 days
-
bug
Difficulty 4/5 1-2 days Newbie friendliness 49/100
fluent/fluent-plugin-kafka#616 ·
Maintainers usually reply within 2 days
-
bug
Difficulty 4/5 3-5 days Newbie friendliness 55/100
fluent/fluent-plugin-kafka#611 ·
Maintainers usually reply within 2 days
All issues in fluent/fluent-plugin-kafka
Similar issues
-
Difficulty 1/5 1-3 hours Newbie friendliness 72/100
Parallels/vagrant-parallels#530 ·
-
Good first issue: add rails-hotwire stack budget preset (Ruby on Rails 8 + Hotwire + PostgreSQL)Openenhancement good first issue help wanted
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
simp/pupmod-simp-tftpboot#152 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Maintainers usually reply within 1 day
-
Websockify heartbeat for vnc_containerPossibly taken @robinkar claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day