Skip to content

Commit d2c6b12

Browse files
author
ystolbovskiy
committed
feat userver: support status codes log levels in grpc
commit_hash:a14b7f5cfa932aaf37727e2ec1ca8f8d51a2d679
1 parent 1825e27 commit d2c6b12

File tree

16 files changed

+128
-15
lines changed

16 files changed

+128
-15
lines changed

grpc/include/userver/ugrpc/server/impl/call_state.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <userver/ugrpc/server/impl/call_kind.hpp>
1818
#include <userver/ugrpc/server/middlewares/fwd.hpp>
1919
#include <userver/ugrpc/server/storage_context.hpp>
20+
#include <userver/ugrpc/status_codes.hpp>
2021

2122
USERVER_NAMESPACE_BEGIN
2223

@@ -37,6 +38,7 @@ struct CallParams {
3738
std::optional<tracing::InPlaceSpan>& span_storage;
3839
const Middlewares& middlewares;
3940
const dynamic_config::Source& config_source;
41+
const boost::container::flat_map<grpc::StatusCode, logging::Level>& status_codes_log_level;
4042
};
4143

4244
// Non-templated state of CallProcessor. Can be non-movable.

grpc/include/userver/ugrpc/server/impl/service_internals.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
#pragma once
22

3+
#include <boost/container/flat_map.hpp>
4+
35
#include <userver/dynamic_config/source.hpp>
46
#include <userver/engine/task/task_processor_fwd.hpp>
57
#include <userver/logging/fwd.hpp>
8+
#include <userver/logging/level.hpp>
69

710
#include <userver/ugrpc/server/middlewares/fwd.hpp>
11+
#include <userver/ugrpc/status_codes.hpp>
812

913
USERVER_NAMESPACE_BEGIN
1014

@@ -23,6 +27,7 @@ struct ServiceInternals final {
2327
ugrpc::impl::StatisticsStorage& statistics_storage;
2428
Middlewares middlewares;
2529
const dynamic_config::Source config_source;
30+
boost::container::flat_map<grpc::StatusCode, logging::Level> status_codes_log_level;
2631
};
2732

2833
} // namespace ugrpc::server::impl

grpc/include/userver/ugrpc/server/impl/service_worker_impl.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ class CallData final {
170170
span_storage_,
171171
method_data_.service_data.internals.middlewares,
172172
method_data_.service_data.internals.config_source,
173+
method_data_.service_data.internals.status_codes_log_level,
173174
},
174175
raw_responder_,
175176
initial_request_,

grpc/include/userver/ugrpc/server/middlewares/log/component.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace ugrpc::server::middlewares::log {
2929
/// msg-log-level | logging level to use for request and response messages themselves | debug
3030
/// msg-size-log-limit | max message size to log, the rest will be truncated | 512
3131
/// local-log-level | local log level of the span for user-provided handler | debug
32+
/// status-codes-log-level | gRPC status code string -> response log level map | {}
3233
///
3334
/// ## Static configuration example:
3435
///

grpc/include/userver/ugrpc/server/service_base.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
/// @file userver/ugrpc/server/service_base.hpp
44
/// @brief @copybrief ugrpc::server::ServiceBase
55

6+
#include <boost/container/flat_map.hpp>
7+
68
#include <userver/engine/task/task_processor_fwd.hpp>
79

810
#include <userver/ugrpc/server/call_context.hpp>
911
#include <userver/ugrpc/server/impl/service_worker.hpp>
1012
#include <userver/ugrpc/server/middlewares/fwd.hpp>
13+
#include <userver/ugrpc/status_codes.hpp>
1114

1215
USERVER_NAMESPACE_BEGIN
1316

@@ -24,6 +27,10 @@ struct ServiceConfig final {
2427

2528
/// Server middlewares to use for the gRPC service.
2629
Middlewares middlewares;
30+
31+
/// map of "status_code": log_level items to override span log level for specific status codes
32+
/// see @ref ugrpc::kStatusCodesMap for available statuses
33+
boost::container::flat_map<grpc::StatusCode, logging::Level> status_codes_log_level;
2734
};
2835

2936
/// @brief The type-erased base class for all gRPC service implementations

grpc/include/userver/ugrpc/server/service_component_base.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ using MiddlewareRunnerComponentBase = USERVER_NAMESPACE::middlewares::RunnerComp
4343
/// disable-user-pipeline-middlewares | flag to disable `groups::User` middlewares from pipeline | false
4444
/// disable-all-pipeline-middlewares | flag to disable all middlewares from pipeline | false
4545
/// middlewares | middlewares names to use | `{}` (use server defaults)
46+
/// status-codes-log-level | gRPC status code string -> span log level map | {}
4647

4748
// clang-format on
4849

grpc/include/userver/ugrpc/status_codes.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
#include <grpcpp/support/status.h>
77

8+
#include <userver/formats/json_fwd.hpp>
9+
#include <userver/yaml_config/fwd.hpp>
10+
811
USERVER_NAMESPACE_BEGIN
912

1013
namespace ugrpc {
@@ -34,4 +37,20 @@ bool IsServerError(grpc::StatusCode code) noexcept;
3437

3538
} // namespace ugrpc
3639

40+
namespace formats::parse {
41+
42+
/// @ref yaml_config::YamlConfig parsing support for `grpc::StatusCode`.
43+
grpc::StatusCode Parse(const yaml_config::YamlConfig& value, To<grpc::StatusCode>);
44+
45+
/// Support for parsing `grpc::StatusCode` from string. Used for headers and map keys.
46+
grpc::StatusCode Parse(std::string_view value, To<grpc::StatusCode>);
47+
48+
} // namespace formats::parse
49+
50+
namespace formats::serialize {
51+
52+
formats::json::Value Serialize(const grpc::StatusCode& value, formats::serialize::To<formats::json::Value>);
53+
54+
}
55+
3756
USERVER_NAMESPACE_END

grpc/src/ugrpc/server/impl/call_processor.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#include <chrono>
44

5+
#include <boost/container/flat_map.hpp>
6+
57
#include <userver/logging/impl/logger_base.hpp>
68
#include <userver/logging/log.hpp>
79
#include <userver/tracing/opentelemetry.hpp>
@@ -20,20 +22,21 @@ namespace ugrpc::server::impl {
2022

2123
namespace {
2224

23-
void ReportFinishSuccess(
24-
const grpc::Status& status,
25-
tracing::Span& span,
26-
ugrpc::impl::RpcStatisticsScope& statistics_scope
27-
) noexcept {
25+
void ReportFinishSuccess(const grpc::Status& status, CallState& state) noexcept {
2826
try {
2927
const auto status_code = status.error_code();
30-
statistics_scope.OnExplicitFinish(status_code);
28+
state.statistics_scope.OnExplicitFinish(status_code);
3129

30+
auto& span = state.GetSpan();
3231
span.AddNonInheritableTag("grpc_code", ugrpc::ToString(status_code));
3332
if (!status.ok()) {
3433
span.AddNonInheritableTag(tracing::kErrorFlag, true);
3534
span.AddNonInheritableTag(tracing::kErrorMessage, status.error_message());
36-
span.SetLogLevel(IsServerError(status_code) ? logging::Level::kError : logging::Level::kWarning);
35+
const auto default_error_log_level =
36+
IsServerError(status.error_code()) ? logging::Level::kError : logging::Level::kWarning;
37+
const auto error_log_level =
38+
utils::FindOrDefault(state.status_codes_log_level, status.error_code(), default_error_log_level);
39+
span.SetLogLevel(error_log_level);
3740
}
3841
} catch (const std::exception& ex) {
3942
LOG_ERROR() << "Error in ReportFinishSuccess: " << ex;
@@ -143,7 +146,7 @@ ReportCustomError(const USERVER_NAMESPACE::server::handlers::CustomHandlerExcept
143146

144147
void CheckFinishStatus(bool finish_op_succeeded, const grpc::Status& status, CallState& state) noexcept {
145148
if (finish_op_succeeded) {
146-
ReportFinishSuccess(status, state.GetSpan(), state.statistics_scope);
149+
ReportFinishSuccess(status, state);
147150
} else {
148151
ReportRpcInterruptedError(state);
149152
}

grpc/src/ugrpc/server/impl/parse_config.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#include <ugrpc/server/impl/parse_config.hpp>
22

3+
#include <boost/container/flat_map.hpp>
34
#include <boost/range/adaptor/transformed.hpp>
45

6+
#include <userver/formats/parse/common_containers.hpp>
57
#include <userver/fs/blocking/read.hpp>
68
#include <userver/logging/component.hpp>
79
#include <userver/logging/impl/logger_base.hpp>
@@ -11,6 +13,7 @@
1113
#include <userver/utils/algo.hpp>
1214

1315
#include <userver/ugrpc/server/middlewares/base.hpp>
16+
#include <userver/ugrpc/status_codes.hpp>
1417

1518
USERVER_NAMESPACE_BEGIN
1619

@@ -19,6 +22,7 @@ namespace ugrpc::server::impl {
1922
namespace {
2023

2124
constexpr std::string_view kTaskProcessorKey = "task-processor";
25+
constexpr std::string_view kStatusCodesLogLevelKey = "status-codes-log-level";
2226

2327
template <typename ParserFunc>
2428
auto ParseOptional(
@@ -71,6 +75,8 @@ server::ServiceConfig ParseServiceConfig(
7175
value[kTaskProcessorKey], defaults.task_processor, context, ParseTaskProcessor
7276
),
7377
/*middlewares=*/{},
78+
/*status_codes_log_level=*/
79+
value[kStatusCodesLogLevelKey].As<boost::container::flat_map<grpc::StatusCode, logging::Level>>({}),
7480
};
7581
}
7682

grpc/src/ugrpc/server/middlewares/log/component.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#include <userver/ugrpc/server/middlewares/log/component.hpp>
22

33
#include <userver/components/component_config.hpp>
4+
#include <userver/formats/parse/common_containers.hpp>
45
#include <userver/logging/level_serialization.hpp>
56
#include <userver/yaml_config/merge_schemas.hpp>
67

78
#include <ugrpc/server/middlewares/log/middleware.hpp>
89
#include <userver/middlewares/groups.hpp>
910
#include <userver/ugrpc/server/middlewares/access_log/component.hpp>
11+
#include <userver/ugrpc/status_codes.hpp>
1012

1113
USERVER_NAMESPACE_BEGIN
1214

@@ -18,6 +20,8 @@ Settings Parse(const yaml_config::YamlConfig& config, formats::parse::To<Setting
1820
settings.msg_log_level = config["msg-log-level"].As<logging::Level>(settings.msg_log_level);
1921
settings.max_msg_size = config["msg-size-log-limit"].As<std::size_t>(settings.max_msg_size);
2022
settings.local_log_level = config["local-log-level"].As<logging::Level>(settings.local_log_level);
23+
settings.status_codes_log_level =
24+
config["status-codes-log-level"].As<boost::container::flat_map<grpc::StatusCode, logging::Level>>({});
2125
return settings;
2226
}
2327

@@ -57,6 +61,21 @@ additionalProperties: false
5761
local-log-level:
5862
type: string
5963
description: local log level of the span for user-provided handler
64+
status-codes-log-level:
65+
type: object
66+
properties: {}
67+
additionalProperties:
68+
type: string
69+
description: log level
70+
description: |
71+
gRPC status code string -> log level map.
72+
Allows overriding the log level for the response for individual statuses.
73+
See grpcpp StatusCode documentation for the list of possible values:
74+
https://grpc.github.io/grpc/cpp/namespacegrpc.html#aff1730578c90160528f6a8d67ef5c43b
75+
76+
Example:
77+
- FAILED_PRECONDITION: info
78+
6079
)");
6180
}
6281

0 commit comments

Comments
 (0)