[ 
https://issues.apache.org/jira/browse/KAFKA-21076?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Apoorv Mittal resolved KAFKA-21076.
-----------------------------------
    Fix Version/s: 4.5.0
       Resolution: Fixed

> Oversize decompressed telemetry payload returns INVALID_RECORD and 
> permanently disables client telemetry
> --------------------------------------------------------------------------------------------------------
>
>                 Key: KAFKA-21076
>                 URL: https://issues.apache.org/jira/browse/KAFKA-21076
>             Project: Kafka
>          Issue Type: Bug
>          Components: clients, core
>    Affects Versions: 4.3.1
>            Reporter: Steven Schlansker
>            Assignee: Rishi Kant Rana
>            Priority: Major
>             Fix For: 4.5.0
>
>
> Since [PR #22327|https://github.com/apache/kafka/pull/22327] (4.3.1, "MINOR: 
> Fixed metrics decompression"), {{ClientTelemetryUtils.decompress}} throws 
> {{TelemetryTooLargeException}} when the decompressed payload exceeds 
> {{{}telemetry.max.bytes{}}}. The call runs inside 
> {{ClientMetricsManager.processPushTelemetryRequest}} in the plugin export 
> block, whose {{catch (Throwable)}} maps every failure to 
> {{{}Errors.INVALID_RECORD{}}}:
> {code:java}
> catch (Throwable exception) {
>     clientMetricsStats.recordPluginErrorCount(clientInstanceId);
>     clientInstance.lastKnownError(Errors.INVALID_RECORD);
>     log.error("Error exporting client metrics to the plugin for client 
> instance id: {}", clientInstanceId, exception);
>     return request.errorResponse(0, Errors.INVALID_RECORD);
> }
> {code}
> KIP-714 defines INVALID_RECORD as "Broker failed to decode or validate the 
> client's encoded metrics. Log an error and stop pushing metrics. This is 
> viewed as a problem in the client implementation of metrics serialization 
> that is not likely to be resolved by retrying." The Java client implements 
> exactly that in {{{}ClientTelemetryUtils.maybeFetchErrorIntervalMs{}}}: on 
> INVALID_RECORD it sets the push interval to {{{}Integer.MAX_VALUE{}}}, so 
> telemetry from that client instance stops until the process restarts.
> The validatePushRequest method throws the same TelemetryTooLargeException 
> when the wire size exceeds telemetry.max.bytes, and that path returns the 
> error through Errors.forException, which yields TELEMETRY_TOO_LARGE. So the 
> broker returns two different codes for the same exception class depending on 
> whether the check happens before or after decompression.
> KIP-714 defines TELEMETRY_TOO_LARGE for a payload that is too large, and the 
> client handles that code by retrying at the normal interval.
> Observed effect: after a broker upgrade from 4.3.0 to 4.3.1, every Kafka 
> Streams stream-thread consumer (payload several MB decompressed, under 1 MiB 
> compressed) got INVALID_RECORD on its next push and disabled its telemetry. 
> All {{org.apache.kafka.stream.*}} metrics that KIP-1076 routes through the 
> stream-thread consumers disappeared from the metrics backend in every 
> environment at the same time. Broker log:
> {noformat}
> ERROR Error exporting client metrics to the plugin for client instance id: 
> xkdFrlXGTGig-RPx5SjuQA (org.apache.kafka.server.ClientMetricsManager)
> org.apache.kafka.common.errors.TelemetryTooLargeException: Decompressed 
> telemetry metrics exceed maximum allowed size: 1048576
> {noformat}
> Two further points:
>  * KIP-714 documents {{telemetry.max.bytes}} as "The maximum size (after 
> compression if compression is used) of telemetry pushed from a client to the 
> broker." PR #22327 changed the meaning to also bound the decompressed size, 
> with no KIP update, no release note, and no new configuration. A 4.3.0 
> cluster that accepted a client's pushes rejects the same pushes on 4.3.1.
>  * Before PR #22327 the same code path allocated {{metrics.limit() * 2}} 
> bytes and grew without bound, so a bound is reasonable. The bound needs its 
> own error code and, given that decompression ratios of 10x or more are normal 
> for OTLP metrics, its own configuration or a multiple of 
> {{{}telemetry.max.bytes{}}}.
> Measured on a Kafka Streams application (8 stream threads, subscription 
> metrics=*, push interval 30 s) against 4.3.1 brokers. The broker's 
> RequestMetrics RequestBytes histogram for PushTelemetry put the compressed 
> push at a 40 KB mean, 940 KB p95, 1.34 MB p99 and 1.41 MB max in one cluster, 
> 2.08 MB max in another; all of these passed the 1 MiB wire check before 4.3.1 
> or were rejected with the retryable TELEMETRY_TOO_LARGE. With 
> telemetry.max.bytes raised to 32 MiB the brokers still logged "Decompressed 
> telemetry metrics exceed maximum allowed size: 33554432" for several of these 
> pushes, and 128 MiB was needed before every push was accepted. That is an 
> expansion ratio of at least 25x between the compressed payload the client and 
> the wire check see and the decompressed payload the new check bounds, which 
> is the normal ratio for OTLP metrics with repeated label sets. A single 
> telemetry.max.bytes cannot bound both sensibly: a value that admits a 
> legitimate decompressed payload is meaningless as a wire limit. The 
> decompressed bound should have its own configuration, or a documented 
> multiple of telemetry.max.bytes, and it should return TELEMETRY_TOO_LARGE 
> like the wire check does.
> Suggested fix: catch {{TelemetryTooLargeException}} before the generic 
> {{catch (Throwable)}} and return {{{}Errors.TELEMETRY_TOO_LARGE{}}}, so the 
> client retries at its interval instead of disabling telemetry. Document the 
> decompressed bound in {{telemetry.max.bytes}} or add a separate 
> configuration, and mention the behavior change in the upgrade notes.
> Workaround: raise {{telemetry.max.bytes}} on the brokers and restart affected 
> clients.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to