Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
GrpcMeterIdPrefixFunction
(#2971)
Motivation: It'd be nice to have a dedicated `MeterIdPrefixFunction` implementation for gRPC, so that the tag for grpc-status is added automatically. Modifications: - Add `GrpcMeterIdPrefixFunction`. - Insert `GrpcWebTrailersExtrator` before `HttpClientDelegate` when the gRPC-web client is created. - Remove `GrpcWebUtil.parseTrailers()` which was used to extract web trailers from RetringClient. - Could use `GrpcWebTrailers.get(ctx)` to get gRPC web trailers instead. - Add `DefaultMeterIdPrefixFunction` which `GrpcMeterIdPrefixFunction` and `RetrofitMeterIdPrefixFunction` extend. - Add `AbstractClientOptionsBuilder.clearDecorator()` to remove decorators set. - Add meter tags in the Alphabet order. - Add grpc-status header to the unframed grpc service response headers. Result: - Close #2762 - You can now use `GrpcMeterIdPrefixFunction` to add `grpc.status` tag to the metric easily. To-do: - The marking of successes and failures is not working well when `MetricCollectingClient` is between `RetryingClient` and `HttpClientDelegate`.
- Loading branch information
Showing
33 changed files
with
993 additions
and
357 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
...c/main/java/com/linecorp/armeria/internal/common/metric/DefaultMeterIdPrefixFunction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* | ||
* Copyright 2020 LINE Corporation | ||
* | ||
* LINE Corporation licenses this file to you under the Apache License, | ||
* version 2.0 (the "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at: | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
package com.linecorp.armeria.internal.common.metric; | ||
|
||
import static com.google.common.base.MoreObjects.firstNonNull; | ||
import static java.util.Objects.requireNonNull; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.collect.ImmutableList.Builder; | ||
|
||
import com.linecorp.armeria.common.Flags; | ||
import com.linecorp.armeria.common.HttpStatus; | ||
import com.linecorp.armeria.common.RequestContext; | ||
import com.linecorp.armeria.common.logging.RequestLog; | ||
import com.linecorp.armeria.common.logging.RequestLogProperty; | ||
import com.linecorp.armeria.common.logging.RequestOnlyLog; | ||
import com.linecorp.armeria.common.metric.MeterIdPrefix; | ||
import com.linecorp.armeria.common.metric.MeterIdPrefixFunction; | ||
import com.linecorp.armeria.server.ServiceRequestContext; | ||
|
||
import io.micrometer.core.instrument.MeterRegistry; | ||
import io.micrometer.core.instrument.Tag; | ||
|
||
/** | ||
* Default {@link MeterIdPrefixFunction} implementation. | ||
*/ | ||
public final class DefaultMeterIdPrefixFunction implements MeterIdPrefixFunction { | ||
|
||
private final String name; | ||
|
||
public static MeterIdPrefixFunction of(String name) { | ||
return new DefaultMeterIdPrefixFunction(name); | ||
} | ||
|
||
private DefaultMeterIdPrefixFunction(String name) { | ||
this.name = requireNonNull(name, "name"); | ||
} | ||
|
||
@Override | ||
public MeterIdPrefix activeRequestPrefix(MeterRegistry registry, RequestOnlyLog log) { | ||
/* hostname.pattern, method, service */ | ||
final Builder<Tag> tagListBuilder = ImmutableList.builderWithExpectedSize(3); | ||
addActiveRequestPrefixTags(tagListBuilder, log); | ||
return new MeterIdPrefix(name, tagListBuilder.build()); | ||
} | ||
|
||
@Override | ||
public MeterIdPrefix completeRequestPrefix(MeterRegistry registry, RequestLog log) { | ||
/* hostname.pattern, http.status, method, service */ | ||
final Builder<Tag> tagListBuilder = ImmutableList.builderWithExpectedSize(4); | ||
addCompleteRequestPrefixTags(tagListBuilder, log); | ||
return new MeterIdPrefix(name, tagListBuilder.build()); | ||
} | ||
|
||
/** | ||
* Adds the active request tags in lexicographical order for better sort performance. | ||
* This adds {@code hostname.pattern}, {@code method} and {@code service}, in order. | ||
*/ | ||
public static void addActiveRequestPrefixTags(Builder<Tag> tagListBuilder, RequestOnlyLog log) { | ||
requireNonNull(tagListBuilder, "tagListBuilder"); | ||
requireNonNull(log, "log"); | ||
addHostnamePattern(tagListBuilder, log); | ||
addMethodAndService(tagListBuilder, log); | ||
} | ||
|
||
/** | ||
* Adds the complete request tags in lexicographical order for better sort performance. | ||
* This adds {@code hostname.pattern}, {@code http.status}, {@code method} and {@code service}, in order. | ||
*/ | ||
public static void addCompleteRequestPrefixTags(Builder<Tag> tagListBuilder, RequestLog log) { | ||
requireNonNull(tagListBuilder, "tagListBuilder"); | ||
requireNonNull(log, "log"); | ||
addHostnamePattern(tagListBuilder, log); | ||
addHttpStatus(tagListBuilder, log); | ||
addMethodAndService(tagListBuilder, log); | ||
} | ||
|
||
/** | ||
* Adds {@code http.status} tag to the {@code tagListBuilder}. | ||
*/ | ||
public static void addHttpStatus(Builder<Tag> tagListBuilder, RequestLog log) { | ||
requireNonNull(tagListBuilder, "tagListBuilder"); | ||
requireNonNull(log, "log"); | ||
// Add the 'httpStatus' tag. | ||
final HttpStatus status; | ||
if (log.isAvailable(RequestLogProperty.RESPONSE_HEADERS)) { | ||
status = log.responseHeaders().status(); | ||
} else { | ||
status = HttpStatus.UNKNOWN; | ||
} | ||
tagListBuilder.add(Tag.of(Flags.useLegacyMeterNames() ? "httpStatus" : "http.status", | ||
status.codeAsText())); | ||
} | ||
|
||
private static void addHostnamePattern(Builder<Tag> tagListBuilder, RequestOnlyLog log) { | ||
final RequestContext ctx = log.context(); | ||
if (ctx instanceof ServiceRequestContext) { | ||
final ServiceRequestContext sCtx = (ServiceRequestContext) ctx; | ||
tagListBuilder.add(Tag.of(Flags.useLegacyMeterNames() ? "hostnamePattern" | ||
: "hostname.pattern", | ||
sCtx.config().virtualHost().hostnamePattern())); | ||
} | ||
} | ||
|
||
private static void addMethodAndService(Builder<Tag> tagListBuilder, RequestOnlyLog log) { | ||
tagListBuilder.add(Tag.of("method", log.name())); | ||
tagListBuilder.add(Tag.of("service", firstNonNull(log.serviceName(), "none"))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.