13 #include <boost/lexical_cast.hpp>
53 if (!my->gelf_endpoint)
57 string::size_type colon_pos = my->cfg.endpoint.find(
':');
60 uint16_t port = boost::lexical_cast<uint16_t>(my->cfg.endpoint.substr(colon_pos + 1, my->cfg.endpoint.size()));
62 string hostname = my->cfg.endpoint.substr( 0, colon_pos );
63 std::vector<ip::endpoint> endpoints =
resolve(hostname, port);
64 if (endpoints.empty())
65 FC_THROW_EXCEPTION(unknown_host_exception,
"The host name can not be resolved: ${hostname}",
66 (
"hostname", hostname));
67 my->gelf_endpoint = endpoints.back();
69 catch (
const boost::bad_lexical_cast&)
71 FC_THROW(
"Bad port: ${port}", (
"port", my->cfg.endpoint.substr(colon_pos + 1, my->cfg.endpoint.size())));
75 if (my->gelf_endpoint)
76 my->gelf_socket.open();
80 std::cerr <<
"error opening GELF socket to endpoint ${endpoint}" << my->cfg.endpoint <<
"\n";
89 if (!my->gelf_endpoint)
95 gelf_message[
"version"] =
"1.1";
96 gelf_message[
"host"] = my->cfg.host;
99 gelf_message[
"timestamp"] =
context.get_timestamp().time_since_epoch().count() / 1000000.;
101 switch (
context.get_log_level())
104 gelf_message[
"level"] = 7;
107 gelf_message[
"level"] = 6;
110 gelf_message[
"level"] = 4;
113 gelf_message[
"level"] = 3;
118 gelf_message[
"level"] = 6;
122 if (!
context.get_context().empty())
123 gelf_message[
"context"] =
context.get_context();
124 gelf_message[
"_line"] =
context.get_line_number();
125 gelf_message[
"_file"] =
context.get_file();
126 gelf_message[
"_method_name"] =
context.get_method();
127 gelf_message[
"_thread_name"] =
context.get_thread_name();
128 if (!
context.get_task_name().empty())
129 gelf_message[
"_task_name"] =
context.get_task_name();
131 string gelf_message_as_string;
136 catch(
const fc::assert_exception& e )
138 gelf_message_as_string =
"{\"level\":3,\"short_message\":\"ERROR while generating log message\"}";
140 gelf_message_as_string =
zlib_compress(gelf_message_as_string);
146 assert(gelf_message_as_string[0] == (
char)0x78);
147 if (gelf_message_as_string[1] == (
char)0x01 ||
148 gelf_message_as_string[1] == (
char)0xda)
149 gelf_message_as_string[1] = (char)0x9c;
150 assert(gelf_message_as_string[1] == (
char)0x9c);
158 const unsigned max_payload_size = 512;
160 if (gelf_message_as_string.size() <= max_payload_size)
163 std::shared_ptr<char> send_buffer(
new char[gelf_message_as_string.size()],
164 [](
char* p){ delete[] p; });
165 memcpy(send_buffer.get(), gelf_message_as_string.c_str(),
166 gelf_message_as_string.size());
168 my->gelf_socket.send_to(send_buffer, gelf_message_as_string.size(),
176 uint64_t message_id =
city_hash64(gelf_message_as_string.c_str(), gelf_message_as_string.size());
177 const unsigned header_length = 2 + 8 + 1 + 1 ;
178 const unsigned body_length = max_payload_size - header_length;
179 unsigned total_number_of_packets = (gelf_message_as_string.size() + body_length - 1) / body_length;
180 unsigned bytes_sent = 0;
181 unsigned number_of_packets_sent = 0;
182 while (bytes_sent < gelf_message_as_string.size())
184 unsigned bytes_to_send = std::min((
unsigned)gelf_message_as_string.size() - bytes_sent,
187 std::shared_ptr<char> send_buffer(
new char[max_payload_size],
188 [](
char* p){
delete[] p; });
189 char*
ptr = send_buffer.get();
191 *(
unsigned char*)
ptr++ = 0x1e;
192 *(
unsigned char*)
ptr++ = 0x0f;
195 memcpy(
ptr, (
char*)&message_id,
sizeof(message_id));
196 ptr +=
sizeof(message_id);
198 *(
unsigned char*)(
ptr++) = number_of_packets_sent;
199 *(
unsigned char*)(
ptr++) = total_number_of_packets;
200 memcpy(
ptr, gelf_message_as_string.c_str() + bytes_sent,
202 my->gelf_socket.send_to(send_buffer, header_length + bytes_to_send,
204 ++number_of_packets_sent;
205 bytes_sent += bytes_to_send;
207 assert(number_of_packets_sent == total_number_of_packets);