analytics: 3p NC: Implement ErrorCodeRecorder for AnalyticsRecorder.

PiperOrigin-RevId: 395881244
This commit is contained in:
edwinwu
2021-09-10 02:04:06 -07:00
committed by Copybara-Service
parent 7e4f65b882
commit 6926f5cd4b
7 changed files with 478 additions and 0 deletions
+35
View File
@@ -128,6 +128,28 @@ cc_library(
],
)
cc_library(
name = "error_code_recorder",
srcs = [
"error_code_recorder.cc",
],
hdrs = [
"error_code_params.h",
"error_code_recorder.h",
],
compatible_with = ["//buildenv/target:non_prod"],
visibility = [
"//third_party/nearby_connections/cpp/analytics:__subpackages__",
"//core/internal:__subpackages__",
"//platform/impl:__subpackages__",
],
deps = [
":logging",
"//proto:connections_enums_portable_proto",
"//third_party/nearby_connections/proto/errorcode:error_code_enums_portable_proto",
],
)
cc_library(
name = "test_util",
testonly = True,
@@ -194,6 +216,19 @@ cc_test(
],
)
cc_test(
name = "error_code_recorder_test",
srcs = [
"error_code_recorder_test.cc",
],
deps = [
":error_code_recorder",
":test_util",
"//testing/base/public:gunit_main",
"//platform/impl/g3", # build_cleaner: keep
],
)
cc_with_non_compile_test(
name = "exception_test",
srcs = [
+64
View File
@@ -0,0 +1,64 @@
// Copyright 2020 Google LLC
//
// Licensed 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.
#ifndef PLATFORM_BASE_ERROR_CORE_PARAMS_H_
#define PLATFORM_BASE_ERROR_CORE_PARAMS_H_
#include "proto/connections_enums.proto.h"
#include "proto/errorcode/error_code_enums.proto.h"
namespace location {
namespace nearby {
// A struct to consturct error code parameters for the analytics recorder.
struct ErrorCodeParams {
location::nearby::proto::connections::Medium medium =
location::nearby::proto::connections::UNKNOWN_MEDIUM;
location::nearby::errorcode::proto::Event event =
location::nearby::errorcode::proto::UNKNOWN_EVENT;
location::nearby::errorcode::proto::Description description =
location::nearby::errorcode::proto::UNKNOWN;
std::string pii_message = {};
bool is_common_error = false;
location::nearby::errorcode::proto::CommonError common_error =
location::nearby::errorcode::proto::UNKNOWN_ERROR;
location::nearby::errorcode::proto::ConnectError connect_error =
location::nearby::errorcode::proto::UNKNOWN_CONNECT_ERROR;
location::nearby::errorcode::proto::DisconnectError disconnect_error =
location::nearby::errorcode::proto::UNKNOWN_DISCONNECT_ERROR;
location::nearby::errorcode::proto::StartAdvertisingError
start_advertising_error =
location::nearby::errorcode::proto::UNKNOWN_START_ADVERTISING_ERROR;
location::nearby::errorcode::proto::StopAdvertisingError
stop_advertising_error =
location::nearby::errorcode::proto::UNKNOWN_STOP_ADVERTISING_ERROR;
location::nearby::errorcode::proto::StartDiscoveringError
start_discovering_error =
location::nearby::errorcode::proto::UNKNOWN_START_DISCOVERING_ERROR;
location::nearby::errorcode::proto::StopDiscoveringError
stop_discovering_error =
location::nearby::errorcode::proto::UNKNOWN_STOP_DISCOVERING_ERROR;
location::nearby::errorcode::proto::StartListeningIncomingConnectionError
start_listening_incoming_connection_error = location::nearby::errorcode::
proto::UNKNOWN_START_LISTENING_INCOMING_CONNECTION_ERROR;
location::nearby::errorcode::proto::StopListeningIncomingConnectionError
stop_listening_incoming_connection_error = location::nearby::errorcode::
proto::UNKNOWN_STOP_LISTENING_INCOMING_CONNECTION_ERROR;
std::string connection_token = {};
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_BASE_ERROR_CORE_PARAMS_H_
+116
View File
@@ -0,0 +1,116 @@
// Copyright 2020 Google LLC
//
// Licensed 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.
#include "platform/base/error_code_recorder.h"
#include "platform/base/logging.h"
#include "proto/errorcode/error_code_enums.proto.h"
namespace location {
namespace nearby {
using ::location::nearby::errorcode::proto::CommonError;
using ::location::nearby::errorcode::proto::CONNECT;
using ::location::nearby::errorcode::proto::ConnectError;
using ::location::nearby::errorcode::proto::Description;
using ::location::nearby::errorcode::proto::DISCONNECT;
using ::location::nearby::errorcode::proto::DisconnectError;
using ::location::nearby::errorcode::proto::Event;
using ::location::nearby::errorcode::proto::START_ADVERTISING;
using ::location::nearby::errorcode::proto::START_DISCOVERING;
using ::location::nearby::errorcode::proto::START_LISTENING_INCOMING_CONNECTION;
using ::location::nearby::errorcode::proto::StartAdvertisingError;
using ::location::nearby::errorcode::proto::StartDiscoveringError;
using ::location::nearby::errorcode::proto::
StartListeningIncomingConnectionError;
using ::location::nearby::errorcode::proto::STOP_ADVERTISING;
using ::location::nearby::errorcode::proto::STOP_DISCOVERING;
using ::location::nearby::errorcode::proto::STOP_LISTENING_INCOMING_CONNECTION;
using ::location::nearby::errorcode::proto::StopAdvertisingError;
using ::location::nearby::errorcode::proto::StopDiscoveringError;
using ::location::nearby::errorcode::proto::
StopListeningIncomingConnectionError;
using ::location::nearby::proto::connections::Medium;
// Default static no-op listener
ErrorCodeRecorder::ErrorCodeListener ErrorCodeRecorder::listener_ =
[](const ErrorCodeParams&) {};
void ErrorCodeRecorder::LogErrorCode(Medium medium, Event event, int error,
Description description,
const std::string& pii_message,
const std::string& connection_token) {
NEARBY_LOGS(INFO) << "ErrorCodeRecorder LogErrorCode";
ErrorCodeParams params = BuildErrorCodeParams(
medium, event, error, description, pii_message, connection_token);
listener_(params);
}
ErrorCodeParams ErrorCodeRecorder::BuildErrorCodeParams(
Medium medium, Event event, int error, Description description,
const std::string& pii_message, const std::string& connection_token) {
ErrorCodeParams params = {.medium = medium,
.event = event,
.description = description,
.pii_message = pii_message,
.connection_token = connection_token};
if (errorcode::proto::CommonError_IsValid(error)) {
params.common_error = static_cast<CommonError>(error);
params.is_common_error = true;
} else {
params.is_common_error = false;
switch (event) {
case START_ADVERTISING:
params.start_advertising_error =
static_cast<StartAdvertisingError>(error);
break;
case STOP_ADVERTISING:
params.stop_advertising_error =
static_cast<StopAdvertisingError>(error);
break;
case START_LISTENING_INCOMING_CONNECTION:
params.start_listening_incoming_connection_error =
static_cast<StartListeningIncomingConnectionError>(error);
break;
case STOP_LISTENING_INCOMING_CONNECTION:
params.stop_listening_incoming_connection_error =
static_cast<StopListeningIncomingConnectionError>(error);
break;
case START_DISCOVERING:
params.start_discovering_error =
static_cast<StartDiscoveringError>(error);
break;
case STOP_DISCOVERING:
params.stop_discovering_error =
static_cast<StopDiscoveringError>(error);
break;
case CONNECT:
params.connect_error = static_cast<ConnectError>(error);
break;
case DISCONNECT:
params.disconnect_error = static_cast<DisconnectError>(error);
break;
// Set the error as unknown if undefined event passed in.
default:
params.common_error = errorcode::proto::UNKNOWN_ERROR;
params.is_common_error = true;
break;
}
}
return params;
}
} // namespace nearby
} // namespace location
+86
View File
@@ -0,0 +1,86 @@
// Copyright 2020 Google LLC
//
// Licensed 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.
#ifndef PLATFORM_BASE_ERROR_CODE_RECORDER_H_
#define PLATFORM_BASE_ERROR_CODE_RECORDER_H_
#include <functional>
#include "platform/base/error_code_params.h"
namespace location {
namespace nearby {
// Deploys the error code of the platform medium to the analytics recorder.
//
// The usage is to call static method ErrorCode::LogErrorCode(...) in each
// medium platform supported whenever error occurred.
class ErrorCodeRecorder {
public:
using ErrorCodeListener = std::function<void(const ErrorCodeParams&)>;
explicit ErrorCodeRecorder(ErrorCodeListener listener) {
listener_ = std::move(listener);
}
ErrorCodeRecorder(const ErrorCodeRecorder&) = delete;
ErrorCodeRecorder& operator=(const ErrorCodeRecorder&) = delete;
// Logs error code when medium error occurred.
//
// Caller should pass the exact matched event and error enum value except
// the common error.
// e.g.
// - START_ADVERTISING_FAILED(43) in StartAdvertisingError =>
// START_ADVERTISING event.
// - DISCONNECT_NETWORK_FAILED(31) in Disconnect_error => DISCONNECT event.
// - INVALID_PARAMETER(1) for Common_error, and the event will be kept as it
// is passed in.
//
// medium - An enum defined in proto::connections::Medium.
// event - An enum defined in errorcode::proto::Event.
// error - An enum integer value in the range from 0..30 defined
// in errorcode::proto::CommonError and the range from 31..
// nn defined among
// errorcode::proto::StartAdvertisingError to
// errorcode::proto::DisconnectError.
// description - A description defiend in errorcode::proto::description.
// pii_message - A pii info defiend in errorcode::proto::pii_message. An
// empty string won't be recorded.
// connection_token - connection token string.
static void LogErrorCode(
location::nearby::proto::connections::Medium medium,
location::nearby::errorcode::proto::Event event, int error,
location::nearby::errorcode::proto::Description description,
const std::string& pii_message, const std::string& connection_token);
private:
// An auxiliary funciton for LogError() to assemble the ErrorCodeParams
// struct.
//
// See `LogErrorCode` for reference on the parameters.
static ErrorCodeParams BuildErrorCodeParams(
location::nearby::proto::connections::Medium medium,
location::nearby::errorcode::proto::Event event, int error,
location::nearby::errorcode::proto::Description description,
const std::string& pii_message, const std::string& connection_token);
// A listener to call back to AnlayticsRecorder.OnErrorCode() by building
// error_code_params.
static ErrorCodeListener listener_;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_BASE_ERROR_CODE_RECORDER_H_
@@ -0,0 +1,136 @@
// Copyright 2020 Google LLC
//
// Licensed 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.
#include "platform/base/error_code_recorder.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace location {
namespace nearby {
using ::testing::Field;
using ::testing::MockFunction;
using ::testing::StrictMock;
TEST(ErrorCodeRecorderTest, TestListenerWork) {
StrictMock<MockFunction<void(const ErrorCodeParams& params)>> mock_listener;
ErrorCodeRecorder::ErrorCodeListener listener = mock_listener.AsStdFunction();
EXPECT_CALL(mock_listener, Call).Times(1);
ErrorCodeRecorder error_code_recorder(listener);
ErrorCodeRecorder::LogErrorCode(
proto::connections::BLE, errorcode::proto::START_ADVERTISING,
errorcode::proto::MULTIPLE_FAST_ADVERTISEMENT_NOT_ALLOWED,
errorcode::proto::FEATURE_BLUETOOTH_NOT_SUPPORTED, "pii_message",
"connection_token");
}
TEST(ErrorCodeRecorderTest, TestBuildErrorCodeParamsWork) {
std::string pii_message = "pii_message";
std::string connection_token = "connection_token";
ErrorCodeParams error_code_params;
ErrorCodeRecorder error_recorder(
[&error_code_params](const ErrorCodeParams& params) {
error_code_params = std::move(params);
});
ErrorCodeRecorder::LogErrorCode(
proto::connections::BLE, errorcode::proto::START_ADVERTISING,
errorcode::proto::MULTIPLE_FAST_ADVERTISEMENT_NOT_ALLOWED,
errorcode::proto::FEATURE_BLUETOOTH_NOT_SUPPORTED, pii_message,
connection_token);
EXPECT_THAT(
error_code_params,
AllOf(Field("medium", &ErrorCodeParams::medium, proto::connections::BLE),
Field("event", &ErrorCodeParams::event,
errorcode::proto::START_ADVERTISING),
Field("description", &ErrorCodeParams::description,
errorcode::proto::FEATURE_BLUETOOTH_NOT_SUPPORTED),
Field("pii_message", &ErrorCodeParams::pii_message, pii_message),
Field("is_common_error", &ErrorCodeParams::is_common_error, false),
Field("start_advertising_error",
&ErrorCodeParams::start_advertising_error,
errorcode::proto::MULTIPLE_FAST_ADVERTISEMENT_NOT_ALLOWED),
Field("connection_token", &ErrorCodeParams::connection_token,
connection_token)));
}
TEST(ErrorCodeRecorderTest, TestBuildErrorCodeParamsWorkForCommonError) {
std::string pii_message = "pii_message";
std::string connection_token = "connection_token";
ErrorCodeParams error_code_params;
ErrorCodeRecorder error_recorder(
[&error_code_params](const ErrorCodeParams& params) {
error_code_params = std::move(params);
});
ErrorCodeRecorder::LogErrorCode(
proto::connections::BLE, errorcode::proto::START_ADVERTISING,
errorcode::proto::INVALID_PARAMETER, errorcode::proto::NULL_SERVICE_ID,
pii_message, connection_token);
EXPECT_THAT(
error_code_params,
AllOf(Field("medium", &ErrorCodeParams::medium, proto::connections::BLE),
Field("event", &ErrorCodeParams::event,
errorcode::proto::START_ADVERTISING),
Field("description", &ErrorCodeParams::description,
errorcode::proto::NULL_SERVICE_ID),
Field("pii_message", &ErrorCodeParams::pii_message, pii_message),
Field("is_common_error", &ErrorCodeParams::is_common_error, true),
Field("common_error", &ErrorCodeParams::common_error,
errorcode::proto::INVALID_PARAMETER),
Field("connection_token", &ErrorCodeParams::connection_token,
connection_token)));
}
TEST(ErrorCodeRecorderTest, TestBuildErrorCodeParamsWorkForUnknownEvent) {
std::string pii_message = "pii_message";
std::string connection_token = "connection_token";
ErrorCodeParams error_code_params;
ErrorCodeRecorder error_recorder(
[&error_code_params](const ErrorCodeParams& params) {
error_code_params = std::move(params);
});
// If event is UNKNOWN_EVENT and the error is not Common_Error then the error
// will be set to UNKNOWN_ERROR.
ErrorCodeRecorder::LogErrorCode(
proto::connections::BLE, errorcode::proto::UNKNOWN_EVENT,
errorcode::proto::MULTIPLE_FAST_ADVERTISEMENT_NOT_ALLOWED,
errorcode::proto::FEATURE_BLUETOOTH_NOT_SUPPORTED, pii_message,
connection_token);
EXPECT_THAT(
error_code_params,
AllOf(Field("medium", &ErrorCodeParams::medium, proto::connections::BLE),
Field("event", &ErrorCodeParams::event,
errorcode::proto::UNKNOWN_EVENT),
Field("description", &ErrorCodeParams::description,
errorcode::proto::FEATURE_BLUETOOTH_NOT_SUPPORTED),
Field("pii_message", &ErrorCodeParams::pii_message, pii_message),
Field("is_common_error", &ErrorCodeParams::is_common_error, true),
Field("common_error", &ErrorCodeParams::common_error,
errorcode::proto::UNKNOWN_ERROR),
Field("connection_token", &ErrorCodeParams::connection_token,
connection_token)));
}
} // namespace nearby
} // namespace location
+27
View File
@@ -14,6 +14,8 @@
# Proto for Nearby products
load("//net/proto2/contrib/portable/cc:portable_proto_build_defs.bzl", "portable_proto_library")
licenses(["notice"])
package(default_visibility = ["//visibility:public"])
@@ -32,3 +34,28 @@ java_lite_proto_library(
name = "error_code_enums_java_proto_lite",
deps = [":error_code_enums_proto"],
)
portable_proto_library(
name = "error_code_enums_portable_proto",
compatible_with = [
"//buildenv/target:non_prod",
],
config = ":error_code_enums_proto_config",
copts = [
"-DGOOGLE_PROTOBUF_NO_RTTI=1",
],
proto_deps = [
":error_code_enums_proto",
],
visibility = [
"//third_party/nearby_connections:__subpackages__",
],
)
filegroup(
name = "error_code_enums_proto_config",
srcs = ["error_code_enums_proto_config.asciipb"],
compatible_with = [
"//buildenv/target:non_prod",
],
)
@@ -0,0 +1,14 @@
optimize_mode: LITE_RUNTIME
allowed_enum: "location.nearby.errorcode.proto.ErrorType"
allowed_enum: "location.nearby.errorcode.proto.Event"
allowed_enum: "location.nearby.errorcode.proto.CommonError"
allowed_enum: "location.nearby.errorcode.proto.StartAdvertisingError"
allowed_enum: "location.nearby.errorcode.proto.StopAdvertisingError"
allowed_enum: "location.nearby.errorcode.proto.StartDiscoveringError"
allowed_enum: "location.nearby.errorcode.proto.StopDiscoveringError"
allowed_enum: "location.nearby.errorcode.proto.StartListeningIncomingConnectionError"
allowed_enum: "location.nearby.errorcode.proto.StopListeningIncomingConnectionError"
allowed_enum: "location.nearby.errorcode.proto.ConnectError"
allowed_enum: "location.nearby.errorcode.proto.DisconnectError"
allowed_enum: "location.nearby.errorcode.proto.Description"