24 #ifndef GOBY_MIDDLEWARE_LOG_PROTOBUF_LOG_PLUGIN_H
25 #define GOBY_MIDDLEWARE_LOG_PROTOBUF_LOG_PLUGIN_H
27 #include <google/protobuf/util/json_util.h>
36 #if GOOGLE_PROTOBUF_VERSION < 3001000
37 #define ByteSizeLong ByteSize
53 "Scheme must be PROTOBUF or DCCL");
63 for (
typename decltype(msgs)::size_type i = 0, n = msgs.size(); i < n; ++i)
66 ss <<
"[" << i <<
"]";
67 ss << msgs[i]->ShortDebugString();
74 std::vector<goby::middleware::HDF5ProtobufEntry> hdf5_entries;
79 hdf5_entries.emplace_back();
91 auto j = std::make_shared<nlohmann::json>();
94 for (
typename decltype(msgs)::size_type i = 0, n = msgs.size(); i < n; ++i)
97 google::protobuf::util::MessageToJsonString(*msgs[i], &jstr);
100 (*j)[n] = nlohmann::json::parse(jstr);
102 (*j) = nlohmann::json::parse(jstr);
110 google::protobuf::FileDescriptorProto::descriptor()->full_name()}] =
111 [&](
const std::vector<unsigned char>& data)
113 google::protobuf::FileDescriptorProto file_desc_proto;
114 file_desc_proto.ParseFromArray(&data[0], data.size());
116 if (!read_file_desc_names_.count(file_desc_proto.name()))
121 dccl::DynamicProtobufManager::add_protobuf_file(file_desc_proto);
122 read_file_desc_names_.insert(file_desc_proto.name());
130 { add_new_protobuf_type(
type, out_log_file); };
135 std::vector<std::shared_ptr<google::protobuf::Message>> msgs;
137 const auto& data = log_entry.
data();
138 auto bytes_begin = data.begin(), bytes_end = data.end(), actual_end = data.begin();
140 while (actual_end != bytes_end)
145 bytes_begin, bytes_end, actual_end, log_entry.
type(), user_pool_first_);
147 find_unknown_fields(*
msg);
150 catch (std::exception&
e)
153 log_entry.
type() +
", reason: " +
e.what()));
155 bytes_begin = actual_end;
162 void insert_protobuf_file_desc(
const google::protobuf::FileDescriptor* file_desc,
163 std::ofstream& out_log_file)
165 if (written_file_desc_.count(file_desc) == 0)
167 for (
int i = 0, n = file_desc->dependency_count(); i < n; ++i)
168 insert_protobuf_file_desc(file_desc->dependency(i), out_log_file);
171 goby::glog <<
"Inserting file descriptor proto for: " << file_desc->name() <<
" : "
172 << file_desc << std::endl;
174 written_file_desc_.insert(file_desc);
176 google::protobuf::FileDescriptorProto file_desc_proto;
177 file_desc->CopyTo(&file_desc_proto);
178 std::vector<unsigned char> data(file_desc_proto.ByteSizeLong());
179 file_desc_proto.SerializeToArray(&data[0], data.size());
181 google::protobuf::FileDescriptorProto::descriptor()->full_name(),
183 entry.serialize(&out_log_file);
188 <<
"Skipping already written file descriptor proto for: "
189 << file_desc->name() << std::endl;
193 void add_new_protobuf_type(
const std::string& protobuf_type, std::ofstream& out_log_file)
195 const google::protobuf::Descriptor* desc =
196 dccl::DynamicProtobufManager::find_descriptor(protobuf_type);
204 add_new_protobuf_type(desc, out_log_file);
208 void add_new_protobuf_type(
const google::protobuf::Descriptor* desc,
209 std::ofstream& out_log_file)
211 if (written_desc_.count(desc) == 0)
216 insert_protobuf_file_desc(desc->file(), out_log_file);
218 auto insert_extensions =
219 [
this, &out_log_file](
220 const std::vector<const google::protobuf::FieldDescriptor*> extensions)
222 for (
const auto* field_desc : extensions)
224 insert_protobuf_file_desc(field_desc->file(), out_log_file);
228 std::vector<const google::protobuf::FieldDescriptor*> generated_extensions;
229 google::protobuf::DescriptorPool::generated_pool()->FindAllExtensions(
230 desc, &generated_extensions);
232 for (
const auto* desc : generated_extensions)
234 << desc->number() <<
"]: " << desc->full_name()
235 <<
" in file: " << desc->file()->name()
238 insert_extensions(generated_extensions);
240 std::vector<const google::protobuf::FieldDescriptor*> user_extensions;
242 #ifdef DCCL_VERSION_4_1_OR_NEWER
243 dccl::DynamicProtobufManager::user_descriptor_pool_call(
244 &google::protobuf::DescriptorPool::FindAllExtensions, desc, &user_extensions);
246 dccl::DynamicProtobufManager::user_descriptor_pool().FindAllExtensions(
247 desc, &user_extensions);
250 for (
const auto* desc : user_extensions)
252 <<
"]: " << desc->full_name()
253 <<
" in file: " << desc->file()->name()
255 insert_extensions(user_extensions);
257 written_desc_.insert(desc);
260 for (
auto i = 0, n = desc->field_count(); i < n; ++i)
262 const auto* field_desc = desc->field(i);
263 if (field_desc->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
264 add_new_protobuf_type(field_desc->message_type(), out_log_file);
271 const auto* refl =
msg.GetReflection();
272 const auto* desc =
msg.GetDescriptor();
274 const google::protobuf::UnknownFieldSet& unknown_fields = refl->GetUnknownFields(
msg);
275 if (!unknown_fields.empty())
277 std::string unknown_field_numbers;
278 for (
int i = 0, n = unknown_fields.field_count(); i < n; ++i)
280 const auto& unknown_field = unknown_fields.field(i);
281 unknown_field_numbers +=
std::to_string(unknown_field.number()) +
" ";
285 goby::glog <<
"Unknown fields found in " << desc->full_name() <<
": "
286 << unknown_field_numbers
287 <<
", ensure all extensions are loaded using load_shared_library"
290 for (
auto i = 0, n = desc->field_count(); i < n; ++i)
292 const auto* field_desc = desc->field(i);
294 if (field_desc->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
296 if (field_desc->is_repeated())
298 for (
int i = 0, n = refl->FieldSize(
msg, field_desc); i < n; ++i)
300 find_unknown_fields(refl->GetRepeatedMessage(
msg, field_desc, i));
305 find_unknown_fields(refl->GetMessage(
msg, field_desc));
312 std::set<const google::protobuf::FileDescriptor*> written_file_desc_;
313 std::set<const google::protobuf::Descriptor*> written_desc_;
314 std::set<std::string> read_file_desc_names_;
315 bool user_pool_first_;