summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Maennich <maennich@google.com>2021-11-18 16:52:24 +0000
committerMatthias Maennich <maennich@google.com>2021-11-20 22:14:55 +0000
commit599c4393aed38adba5d42a9fe17228bea6d07d52 (patch)
treece43f58becdd85633ed902e4b200af63639cd54b
parent40563db38b39bc09c40eed8f833f06d1e14b35bc (diff)
downloadbuild-tools-599c4393aed38adba5d42a9fe17228bea6d07d52.tar.gz
interceptor: replace JSON log by proto log
This implements serialization of commands to a corresponding protobuf based log protocol. Child processes append log::Message to the log (currently this implies a 'Command'). The parent process will reread the log before terminating and will combine the log to a more compact log::Log for further processing. Bug: 205577427 Signed-off-by: Matthias Maennich <maennich@google.com> Change-Id: I29cde728601fc3796f9b3ff0ff1b1d030bb86678
-rw-r--r--interceptor/Android.bp2
-rw-r--r--interceptor/interceptor.cc25
-rw-r--r--interceptor/interceptor.h3
-rw-r--r--interceptor/main.cc31
4 files changed, 52 insertions, 9 deletions
diff --git a/interceptor/Android.bp b/interceptor/Android.bp
index 85081c5..56ea6b2 100644
--- a/interceptor/Android.bp
+++ b/interceptor/Android.bp
@@ -2,6 +2,8 @@ cc_defaults {
name: "interceptor_defaults",
static_libs: [
"libc++fs",
+ "libinterceptor_log",
+ "libprotobuf-cpp-full",
],
}
diff --git a/interceptor/interceptor.cc b/interceptor/interceptor.cc
index 0a52870..f31b343 100644
--- a/interceptor/interceptor.cc
+++ b/interceptor/interceptor.cc
@@ -35,6 +35,7 @@
#include <utility>
#include <android-base/strings.h>
+#include <google/protobuf/util/delimited_message_util.h>
namespace fs = std::filesystem;
@@ -44,7 +45,7 @@ namespace fs = std::filesystem;
static void process_command(const char* filename, char* const argv[], char* const envp[]);
// log command if logging is enabled
-static void log(const interceptor::Command&, const std::string& prefix);
+static void log(const interceptor::Command&);
// execute potentially modified command
static void exec(const interceptor::Command&);
@@ -144,6 +145,19 @@ std::string Command::repr() const {
return os.str();
}
+log::Message Command::message() const {
+ log::Message result;
+ auto& command = *result.mutable_command();
+
+ command.set_program(program_);
+ *command.mutable_args() = {args().cbegin(), args().cend()};
+ command.set_current_dir(cwd_);
+ *command.mutable_outputs() = {outputs().cbegin(), outputs().cend()};
+ *command.mutable_inputs() = {inputs().cbegin(), inputs().cend()};
+
+ return result;
+}
+
void Command::make_relative() {
// determine the ROOT_DIR
std::string root_dir;
@@ -315,20 +329,21 @@ static void process_command(const char* filename, char* const argv[], char* cons
command.analyze();
- log(command, "");
+ log(command);
// pass down the transformed command to execve
exec(command);
}
-static void log(const interceptor::Command& command, const std::string& prefix) {
+static void log(const interceptor::Command& command) {
const auto& env = command.env();
if (const auto env_it = env.find(ENV_command_log); env_it != env.cend()) {
std::ofstream file;
- file.open(std::string(env_it->second), std::ofstream::out | std::ofstream::app);
+ file.open(std::string(env_it->second),
+ std::ofstream::out | std::ofstream::app | std::ofstream::binary);
if (file.is_open()) {
- file << prefix << command.repr() << ",\n";
+ google::protobuf::util::SerializeDelimitedToOstream(command.message(), &file);
}
}
}
diff --git a/interceptor/interceptor.h b/interceptor/interceptor.h
index f7ecae7..9e9a1e8 100644
--- a/interceptor/interceptor.h
+++ b/interceptor/interceptor.h
@@ -20,6 +20,8 @@
#include <unordered_map>
#include <vector>
+#include "log.pb.h"
+
// Options passed via environment variables from the interceptor starter
constexpr static auto ENV_command_log = "INTERCEPTOR_command_log";
constexpr static auto ENV_root_dir = "INTERCEPTOR_root_dir";
@@ -51,6 +53,7 @@ class Command {
const Outputs& outputs() const { return outputs_; }
std::string repr() const;
+ log::Message message() const;
// make command line calls relative to ROOT_DIR
void make_relative();
diff --git a/interceptor/main.cc b/interceptor/main.cc
index ae3d623..e9184e6 100644
--- a/interceptor/main.cc
+++ b/interceptor/main.cc
@@ -16,6 +16,7 @@
#include <getopt.h>
#include <stdlib.h>
+#include <sysexits.h>
#include <cstdlib>
#include <filesystem>
#include <fstream>
@@ -23,6 +24,8 @@
#include <optional>
#include <sstream>
+#include <google/protobuf/util/delimited_message_util.h>
+
#include "interceptor.h"
namespace fs = std::filesystem;
@@ -79,7 +82,7 @@ static void setup_interceptor_library_path() {
interceptor_library = fs::read_symlink(interceptor_library);
if (!fs::is_regular_file(interceptor_library)) {
std::cerr << "Interceptor library could not be found!\n";
- exit(1);
+ exit(EX_CONFIG);
}
setenv("LD_PRELOAD", interceptor_library.c_str(), 1);
}
@@ -101,14 +104,32 @@ class CommandLog {
if (command_log_file_) {
setenv(ENV_command_log, command_log_file_->c_str(), 1);
std::ofstream command_log(command_log_file_->c_str(), std::ios_base::trunc);
- command_log << "[\n";
+ if (!command_log) {
+ std::cerr << "Could not open command log for writing: " << *command_log_file_ << "\n";
+ exit(EX_CANTCREAT);
+ }
}
}
~CommandLog() {
if (command_log_file_) {
- std::ofstream command_log(command_log_file_->c_str(), std::ios_base::app);
- command_log << "]\n";
+ // compact the log by re-reading the individual log::Message's to combine
+ // them to a log::Log
+ interceptor::log::Log log;
+ {
+ std::ifstream command_log(command_log_file_->c_str(), std::ios_base::binary);
+
+ google::protobuf::io::IstreamInputStream input_stream(&command_log);
+ interceptor::log::Message message;
+ while (true) {
+ if (!google::protobuf::util::ParseDelimitedFromZeroCopyStream(&message, &input_stream,
+ nullptr))
+ break;
+ if (message.has_command()) log.add_commands()->Swap(message.release_command());
+ }
+ }
+ std::ofstream command_log(command_log_file_->c_str(), std::ios_base::binary);
+ log.SerializeToOstream(&command_log);
}
}
};
@@ -121,5 +142,7 @@ int main(int argc, char* argv[]) {
CommandLog command_log(options.command_log);
+ // TODO: cleanly to google::protobuf::ShutdownProtobufLibrary();
+
return std::system(options.command_line.c_str());
}