Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions base/cvd/cuttlefish/host/commands/metrics/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,70 @@ cf_cc_binary(
],
)

cf_cc_library(
name = "metrics_conversion",
srcs = [
"metrics_conversion.cc",
],
hdrs = [
"metrics_conversion.h",
],
deps = [
"//cuttlefish/common/libs/utils:result",
"//external_proto:clientanalytics_cc_proto",
"//external_proto:log_source_enum_cc_proto",
],
)

cf_cc_library(
name = "metrics_flags",
srcs = [
"metrics_flags.cc",
],
hdrs = [
"metrics_flags.h",
],
deps = [
"//cuttlefish/common/libs/utils:flag_parser",
"//cuttlefish/common/libs/utils:result",
"//cuttlefish/host/libs/metrics:metrics_environment",
],
)

cf_cc_library(
name = "metrics_transmission",
srcs = [
"metrics_transmission.cc",
],
hdrs = [
"metrics_transmission.h",
],
deps = [
"//cuttlefish/common/libs/utils:result",
"//cuttlefish/host/libs/web/http_client",
"//cuttlefish/host/libs/web/http_client:curl_global_init",
"//cuttlefish/host/libs/web/http_client:curl_http_client",
"//cuttlefish/host/libs/web/http_client:http_string",
"//cuttlefish/host/libs/metrics:metrics_environment",
"//external_proto:clientanalytics_cc_proto",
],
)

cf_cc_binary(
name = "metrics_transmitter",
srcs = [
"metrics_transmitter.cc",
],
deps = [
"//cuttlefish/common/libs/utils:result",
"//cuttlefish/host/commands/metrics:metrics_conversion",
"//cuttlefish/host/commands/metrics:metrics_flags",
"//cuttlefish/host/commands/metrics:metrics_transmission",
"//external_proto:clientanalytics_cc_proto",
"//libbase",
],
)

cf_cc_library(
name = "send",
srcs = ["send.cc"],
Expand Down
56 changes: 56 additions & 0 deletions base/cvd/cuttlefish/host/commands/metrics/metrics_conversion.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* 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
*
* http://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 "cuttlefish/host/commands/metrics/metrics_conversion.h"

#include <chrono>
#include <string>

#include "external_proto/clientanalytics.pb.h"
#include "external_proto/log_source_enum.pb.h"

namespace cuttlefish {
namespace {

using wireless_android_play_playlog::ClientInfo;
using wireless_android_play_playlog::LogEvent;
using wireless_android_play_playlog::LogRequest;
using wireless_android_play_playlog::LogSourceEnum::LogSource;

constexpr LogSource kLogSourceId = LogSource::CUTTLEFISH_METRICS;
constexpr char kLogSourceStr[] = "CUTTLEFISH_METRICS";
constexpr ClientInfo::ClientType kCppClientType = ClientInfo::CPLUSPLUS;

} // namespace

LogRequest BuildLogRequest(const std::string& serialized_cf_log_event) {
LogRequest log_request;
const auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
log_request.set_request_time_ms(now.count());
log_request.set_log_source(kLogSourceId);
log_request.set_log_source_name(kLogSourceStr);

ClientInfo& client_info = *log_request.mutable_client_info();
client_info.set_client_type(kCppClientType);

LogEvent& log_event = *log_request.add_log_event();
log_event.set_event_time_ms(now.count());
log_event.set_source_extension(serialized_cf_log_event);
return log_request;
}

} // namespace cuttlefish
28 changes: 28 additions & 0 deletions base/cvd/cuttlefish/host/commands/metrics/metrics_conversion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* 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
*
* http://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.
*/

#pragma once

#include <string>

#include "external_proto/clientanalytics.pb.h"

namespace cuttlefish {

wireless_android_play_playlog::LogRequest BuildLogRequest(
const std::string& serialized_cf_log_event);

} // namespace cuttlefish
70 changes: 70 additions & 0 deletions base/cvd/cuttlefish/host/commands/metrics/metrics_flags.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* 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
*
* http://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 "cuttlefish/host/commands/metrics/metrics_flags.h"

#include <string>
#include <vector>

#include "cuttlefish/common/libs/utils/flag_parser.h"
#include "cuttlefish/common/libs/utils/result.h"
#include "cuttlefish/host/libs/metrics/metrics_environment.h"

namespace cuttlefish {
namespace {

Flag EnvironmentGflagsCompatFlag(const std::string& name,
ClearcutEnvironment& value) {
return GflagsCompatFlag(name)
.Getter([&value]() { return EnvironmentToString(value); })
.Setter([name, &value](const FlagMatch& match) -> Result<void> {
if (match.value == kLocal) {
value = ClearcutEnvironment::Local;
} else if (match.value == kStaging) {
value = ClearcutEnvironment::Staging;
} else if (match.value == kProduction) {
value = ClearcutEnvironment::Production;
} else {
CF_ERRF("Unexpected environment value: \"{}\"", match.value);
}
return {};
});
}

} // namespace

// TODO: chadreynolds - add path flag to send logs to metrics/metrics.log
// TODO: chadreynolds - add debug flag to specify metrics file and transmit
// for convenient use with different transmission environments

Result<MetricsFlags> ProcessFlags(int argc, char** argv) {
MetricsFlags result;
std::vector<Flag> flags;
flags.emplace_back(
EnvironmentGflagsCompatFlag("environment", result.environment)
.Help("Specify the environment to transmit to."));
flags.emplace_back(
GflagsCompatFlag("serialized_proto", result.serialized_proto)
.Help("The serialized proto data to transmit."));
flags.emplace_back(HelpFlag(flags));
flags.emplace_back(UnexpectedArgumentGuard());
std::vector<std::string> args =
ArgsToVec(argc - 1, argv + 1); // Skip argv[0]
CF_EXPECT(ConsumeFlags(flags, args));
return result;
}

} // namespace cuttlefish
33 changes: 33 additions & 0 deletions base/cvd/cuttlefish/host/commands/metrics/metrics_flags.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* 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
*
* http://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.
*/

#pragma once

#include <string>

#include "cuttlefish/common/libs/utils/result.h"
#include "cuttlefish/host/libs/metrics/metrics_environment.h"

namespace cuttlefish {

struct MetricsFlags {
ClearcutEnvironment environment = ClearcutEnvironment::Production;
std::string serialized_proto;
};

Result<MetricsFlags> ProcessFlags(int argc, char** argv);

} // namespace cuttlefish
70 changes: 70 additions & 0 deletions base/cvd/cuttlefish/host/commands/metrics/metrics_transmission.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* 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
*
* http://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 "cuttlefish/host/commands/metrics/metrics_transmission.h"

#include <memory>
#include <string>

#include "cuttlefish/common/libs/utils/result.h"
#include "cuttlefish/host/libs/metrics/metrics_environment.h"
#include "cuttlefish/host/libs/web/http_client/curl_global_init.h"
#include "cuttlefish/host/libs/web/http_client/curl_http_client.h"
#include "cuttlefish/host/libs/web/http_client/http_client.h"
#include "cuttlefish/host/libs/web/http_client/http_string.h"
#include "external_proto/clientanalytics.pb.h"

namespace cuttlefish {
namespace {

std::string ClearcutEnvironmentUrl(const ClearcutEnvironment environment) {
switch (environment) {
case ClearcutEnvironment::Local:
return "http://localhost:27910/log";
case ClearcutEnvironment::Staging:
return "https://play.googleapis.com:443/staging/log";
case ClearcutEnvironment::Production:
return "https://play.googleapis.com:443/log";
}
}

Result<void> PostRequest(HttpClient& http_client, const std::string& output,
const ClearcutEnvironment server) {
const std::string clearcut_url = ClearcutEnvironmentUrl(server);
const HttpResponse<std::string> response =
CF_EXPECT(HttpPostToString(http_client, clearcut_url, output));
CF_EXPECTF(response.HttpSuccess(), "Metrics POST failed ({}): {}",
response.http_code, response.data);
return {};
}

} // namespace

Result<void> TransmitMetricsEvent(
const wireless_android_play_playlog::LogRequest& log_request,
ClearcutEnvironment environment) {
CurlGlobalInit curl_global_init;
const bool use_logging_debug_function = true;
std::unique_ptr<HttpClient> http_client =
CurlHttpClient(use_logging_debug_function);
CF_EXPECT(http_client.get() != nullptr,
"Unable to create cURL client for metrics transmission");
CF_EXPECT(
PostRequest(*http_client, log_request.SerializeAsString(), environment));
return {};
}

} // namespace cuttlefish
29 changes: 29 additions & 0 deletions base/cvd/cuttlefish/host/commands/metrics/metrics_transmission.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* 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
*
* http://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.
*/

#pragma once

#include "cuttlefish/common/libs/utils/result.h"
#include "cuttlefish/host/libs/metrics/metrics_environment.h"
#include "external_proto/clientanalytics.pb.h"

namespace cuttlefish {

Result<void> TransmitMetricsEvent(
const wireless_android_play_playlog::LogRequest& log_request,
ClearcutEnvironment environment);

} // namespace cuttlefish
Loading
Loading