Skip to content

MINOR: Ensure a reason is logged for all segment deletion operations#9110

Merged
hachikuji merged 8 commits into
apache:trunkfrom
dhruvilshah3:retention-logging
Aug 7, 2020
Merged

MINOR: Ensure a reason is logged for all segment deletion operations#9110
hachikuji merged 8 commits into
apache:trunkfrom
dhruvilshah3:retention-logging

Conversation

@dhruvilshah3

@dhruvilshah3 dhruvilshah3 commented Aug 1, 2020

Copy link
Copy Markdown
Contributor

This PR improves the logging for segment deletion to ensure that a reason is logged for segment deletions via all code paths. It also updates the logging so we can log a reason for an entire batch of deletions instead of logging one message per segment.

Sample log output:

[2020-08-05 11:56:35,826] INFO [Log partition=foo-0, dir=/tmp/kafka-logs] Deleting segment LogSegment(baseOffset=219030, size=1042252, lastModifiedTime=1596653795000, largestRecordTimestamp=Some(1596653795374)) due to retention time 1ms breach based on the largest record timestamp in the segment (kafka.log.Log)
[2020-08-05 11:56:35,826] INFO [Log partition=foo-0, dir=/tmp/kafka-logs] Deleting segment LogSegment(baseOffset=220035, size=1042252, lastModifiedTime=1596653795000, largestRecordTimestamp=Some(1596653795384)) due to retention time 1ms breach based on the largest record timestamp in the segment (kafka.log.Log)
...

Comment thread core/src/main/scala/kafka/log/Log.scala Outdated
// iteration remain valid and deterministic.
val toDelete = segments.toList
toDelete.foreach { segment =>
info(s"${reason.reasonString(this, segment)}")

@kowshik kowshik Aug 1, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we passed in the deletion reason further into the deleteSegmentFiles method, it seems we can print the reason string just once for a batch of segments being deleted. And within the reason string, we can provide the reason for deleting the batch:

https://github.com/confluentinc/ce-kafka/blob/master/core/src/main/scala/kafka/log/Log.scala#L2519
https://github.com/confluentinc/ce-kafka/blob/master/core/src/main/scala/kafka/log/Log.scala#L2526

ex: info("Deleting segments due to $reason: ${segments.mkString(",")}"

where $reason provides due to retention time 1200000ms breach.

The drawback is that sometimes we can not print segment-specific information since the error message is at a batch level. But generally it may be that segment-level deletion information could bloat our server logging, so it may be better to batch the logging instead.

What are your thoughts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While verbose, I think having the granularity of each segment is useful. This allows us to easily reason about why a particular segment was deleted. Note that we switched from a single log per batch to a log per segment in #8850.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we think about cases where this could be an issue? Say delete records is used, causing a large number of segments to be deleted Could that trigger excessive logging?

@kowshik kowshik Aug 2, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dhruvilshah3 Sounds good!

@dhruvilshah3 dhruvilshah3 Aug 2, 2020

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ijuma We log one message per deleted segment. This could cause temporary increase in log volume when DeleteRecords is used or when retention is lowered, for example.

Overall, we have a few options with different tradeoffs:

  1. Log a common reason per batch being deleted, including base offsets of segments being deleted. eg.
Deleting segments due to retention time 999ms breach. BaseOffsets: (0,5,...).
  1. Log a common reason per batch being deleted, including base offsets and metadata of segments. eg.
Deleting segments due to retention time 999ms breach: LogSegment(baseOffset=0, size=360, lastModifiedTime=1596387738000, largestRecordTimestamp=Some(1596387737414)),LogSegment(baseOffset=5, size=360, lastModifiedTime=1596387738000, largestRecordTimestamp=Some(1596387737414)),...
  1. Log one message per segment being deleted. This is the current behavior. eg.
Segment with base offset 0 will be deleted due to retention time 999ms breach based on the largest record timestamp from the segment, which is ...
Segment with base offset 5 will be deleted due to retention time 999ms breach based on the largest record timestamp from the segment, which is ...
...

Doing (2) may be a reasonable tradeoff. It eliminates some of the redundancy at the cost of making it to glean per segment metadata. Let me know what you think.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is important to capture the segment level details. In the past, we have had trouble explaining precisely why a specific segment got deleted. For example, was it because of the last modified time or the record timestamp? When users are looking to understand why data is deleted, we should be able to provide a clear answer.

My personal preference is probably 3) because I hate dealing with lists of things in log messages. Simple grepping no longer work to extract the details. Big messages also messes up console scrolling and can choke downstream systems. For segments, I am not so worried about log noise because the rate of segment creation is not that high.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is reasonable. Logging a segment per line will make it easier for us to diagnose issues. I made the change to log a segment per line for retention-related deletions. We still batch all segments in a single line for all other deletion events, eg. log deletion, truncation, etc.

@kowshik kowshik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good from my side, small comments inline.
It may be good for others to have a look also. cc @ijuma

Comment thread core/src/main/scala/kafka/log/Log.scala Outdated
// iteration remain valid and deterministic.
val toDelete = segments.toList
toDelete.foreach { segment =>
info(s"${reason.reasonString(this, segment)}")

@kowshik kowshik Aug 2, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dhruvilshah3 Sounds good!

Comment thread core/src/main/scala/kafka/log/LogSegment.scala
Comment thread core/src/main/scala/kafka/log/Log.scala Outdated
Comment thread core/src/main/scala/kafka/log/Log.scala Outdated
@dhruvilshah3 dhruvilshah3 changed the title MINOR: Ensure a reason is logged for every segment deletion MINOR: Ensure a reason is logged for all segment deletion operations Aug 3, 2020
Comment thread core/src/main/scala/kafka/log/Log.scala Outdated
Comment thread core/src/main/scala/kafka/log/Log.scala Outdated
Comment thread core/src/main/scala/kafka/log/LogSegment.scala
@dhruvilshah3

dhruvilshah3 commented Aug 3, 2020

Copy link
Copy Markdown
Contributor Author

Thanks for the reviews @kowshik, @hachikuji, @ijuma. I have addressed the comments. Let me know what you think.

@ijuma

ijuma commented Aug 3, 2020

Copy link
Copy Markdown
Member

ok to test

@hachikuji

Copy link
Copy Markdown
Contributor

retest this please

1 similar comment
@hachikuji

Copy link
Copy Markdown
Contributor

retest this please

Comment thread core/src/main/scala/kafka/log/Log.scala Outdated
// removing the deleted segment, we should force materialization of the iterator here, so that results of the
// iteration remain valid and deterministic.
val toDelete = segments.toList
info(s"${reason.logReason(this, toDelete)}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to get rid of the call to info here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching. I fixed this.

@hachikuji

Copy link
Copy Markdown
Contributor

retest this please

3 similar comments
@hachikuji

Copy link
Copy Markdown
Contributor

retest this please

@hachikuji

Copy link
Copy Markdown
Contributor

retest this please

@hachikuji

Copy link
Copy Markdown
Contributor

retest this please

@hachikuji hachikuji left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the patch!

@hachikuji
hachikuji merged commit 6f0ab89 into apache:trunk Aug 7, 2020
@dhruvilshah3
dhruvilshah3 deleted the retention-logging branch August 7, 2020 23:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants