passenger 3.0.8 → 3.0.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data/NEWS +9 -0
- data/bin/passenger-install-nginx-module +1 -1
- data/build/basics.rb +0 -1
- data/build/cxx_tests.rb +5 -0
- data/build/rpm.rb +1 -1
- data/doc/Users guide Apache.html +1 -1
- data/doc/Users guide Nginx.html +1 -1
- data/ext/apache2/Configuration.cpp +12 -0
- data/ext/apache2/Configuration.hpp +12 -1
- data/ext/apache2/Hooks.cpp +2 -0
- data/ext/common/AgentsStarter.cpp +4 -0
- data/ext/common/AgentsStarter.h +2 -0
- data/ext/common/AgentsStarter.hpp +4 -0
- data/ext/common/Constants.h +1 -1
- data/ext/common/Logging.h +481 -261
- data/ext/common/LoggingAgent/LoggingServer.h +10 -4
- data/ext/common/LoggingAgent/Main.cpp +7 -2
- data/ext/common/LoggingAgent/RemoteSender.h +25 -3
- data/ext/common/MessageChannel.h +18 -227
- data/ext/common/MessageClient.h +95 -92
- data/ext/common/Utils/IOUtils.cpp +114 -1
- data/ext/common/Utils/IOUtils.h +57 -1
- data/ext/common/Utils/MessageIO.h +576 -0
- data/ext/nginx/Configuration.c +35 -0
- data/ext/nginx/Configuration.h +2 -0
- data/ext/nginx/ContentHandler.c +17 -6
- data/ext/nginx/ngx_http_passenger_module.c +8 -0
- data/lib/phusion_passenger.rb +2 -2
- data/lib/phusion_passenger/analytics_logger.rb +174 -117
- data/lib/phusion_passenger/app_process.rb +14 -2
- data/test/cxx/CxxTestMain.cpp +14 -19
- data/test/cxx/IOUtilsTest.cpp +68 -18
- data/test/cxx/LoggingTest.cpp +20 -24
- data/test/cxx/MessageChannelTest.cpp +1 -1
- data/test/cxx/MessageIOTest.cpp +310 -0
- data/test/cxx/TestSupport.cpp +47 -0
- data/test/cxx/TestSupport.h +8 -0
- data/test/ruby/analytics_logger_spec.rb +20 -28
- data/test/tut/tut.h +2 -0
- metadata +11 -11
- data/build/rdoctask.rb +0 -209
- data/test/cxx/HttpStatusExtractorTest.cpp +0 -198
data/NEWS
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
Release 3.0.9
|
2
|
+
-------------
|
3
|
+
|
4
|
+
* [Nginx] Fixed a NULL pointer crash that occurs on HTTP/1.0 requests
|
5
|
+
when the Host header isn't given.
|
6
|
+
* Fixed deprecation warnings on RubyGems >= 1.6.
|
7
|
+
* Improved Union Station support stability.
|
8
|
+
|
9
|
+
|
1
10
|
Release 3.0.8
|
2
11
|
-------------
|
3
12
|
|
@@ -192,7 +192,7 @@ private
|
|
192
192
|
new_screen
|
193
193
|
color_puts "<banner>Downloading Nginx...</banner>"
|
194
194
|
|
195
|
-
url = "http://
|
195
|
+
url = "http://www.nginx.org/download/nginx-#{PREFERRED_NGINX_VERSION}.tar.gz"
|
196
196
|
dirname = "nginx-#{PREFERRED_NGINX_VERSION}"
|
197
197
|
tarball = "#{@working_dir}/nginx.tar.gz"
|
198
198
|
|
data/build/basics.rb
CHANGED
@@ -38,7 +38,6 @@ require 'phusion_passenger/platform_info/documentation_tools'
|
|
38
38
|
include PhusionPassenger
|
39
39
|
include PhusionPassenger::PlatformInfo
|
40
40
|
|
41
|
-
require 'build/rdoctask'
|
42
41
|
require 'build/packagetask'
|
43
42
|
require 'build/gempackagetask'
|
44
43
|
require 'build/rake_extensions'
|
data/build/cxx_tests.rb
CHANGED
@@ -28,6 +28,7 @@ TEST_CXX_CFLAGS = "-Iext -Iext/common -Iext/nginx " <<
|
|
28
28
|
"#{TEST_COMMON_CFLAGS}"
|
29
29
|
TEST_CXX_LDFLAGS = "#{TEST_COMMON_LIBRARY} #{TEST_BOOST_OXT_LIBRARY} #{LIBEV_LIBS} " <<
|
30
30
|
"#{PlatformInfo.curl_libs} " <<
|
31
|
+
"#{PlatformInfo.zlib_libs} " <<
|
31
32
|
"#{PlatformInfo.portability_ldflags} #{EXTRA_LDFLAGS}"
|
32
33
|
TEST_CXX_OBJECTS = {
|
33
34
|
'test/cxx/CxxTestMain.o' => %w(
|
@@ -187,6 +188,10 @@ TEST_CXX_OBJECTS = {
|
|
187
188
|
test/cxx/BufferedIOTest.cpp
|
188
189
|
ext/common/Utils/BufferedIO.h
|
189
190
|
ext/common/Utils/Timer.h),
|
191
|
+
'test/cxx/MessageIOTest.o' => %w(
|
192
|
+
test/cxx/MessageIOTest.cpp
|
193
|
+
ext/common/Utils/MessageIO.h
|
194
|
+
ext/common/Utils/IOUtils.h),
|
190
195
|
'test/cxx/VariantMapTest.o' => %w(
|
191
196
|
test/cxx/VariantMapTest.cpp
|
192
197
|
ext/common/MessageChannel.h
|
data/build/rpm.rb
CHANGED
@@ -42,7 +42,7 @@ namespace :package do
|
|
42
42
|
def fetch(dir)
|
43
43
|
tarball = "nginx-#{PREFERRED_NGINX_VERSION}.tar.gz"
|
44
44
|
return true if File.exists?("#{dir}/#{tarball}")
|
45
|
-
download("http://
|
45
|
+
download("http://www.nginx.org/download/#{tarball}", "#{dir}/#{tarball}")
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
data/doc/Users guide Apache.html
CHANGED
data/doc/Users guide Nginx.html
CHANGED
@@ -282,6 +282,8 @@ DEFINE_SERVER_STR_CONFIG_SETTER(cmd_passenger_temp_dir, tempDir)
|
|
282
282
|
DEFINE_SERVER_STR_CONFIG_SETTER(cmd_union_station_gateway_address, unionStationGatewayAddress)
|
283
283
|
DEFINE_SERVER_INT_CONFIG_SETTER(cmd_union_station_gateway_port, unionStationGatewayPort, int, 1)
|
284
284
|
DEFINE_SERVER_STR_CONFIG_SETTER(cmd_union_station_gateway_cert, unionStationGatewayCert)
|
285
|
+
DEFINE_SERVER_STR_CONFIG_SETTER(cmd_union_station_proxy_address, unionStationProxyAddress)
|
286
|
+
DEFINE_SERVER_STR_CONFIG_SETTER(cmd_union_station_proxy_type, unionStationProxyType)
|
285
287
|
DEFINE_SERVER_STR_CONFIG_SETTER(cmd_passenger_analytics_log_dir, analyticsLogDir)
|
286
288
|
DEFINE_SERVER_STR_CONFIG_SETTER(cmd_passenger_analytics_log_user, analyticsLogUser)
|
287
289
|
DEFINE_SERVER_STR_CONFIG_SETTER(cmd_passenger_analytics_log_group, analyticsLogGroup)
|
@@ -619,6 +621,16 @@ const command_rec passenger_commands[] = {
|
|
619
621
|
NULL,
|
620
622
|
RSRC_CONF,
|
621
623
|
"The Union Station Gateway certificate."),
|
624
|
+
AP_INIT_TAKE1("UnionStationProxyAddress",
|
625
|
+
(Take1Func) cmd_union_station_proxy_address,
|
626
|
+
NULL,
|
627
|
+
RSRC_CONF,
|
628
|
+
"The address of the proxy that should be used for sending data to Union Station."),
|
629
|
+
AP_INIT_TAKE1("UnionStationProxyType",
|
630
|
+
(Take1Func) cmd_union_station_proxy_type,
|
631
|
+
NULL,
|
632
|
+
RSRC_CONF,
|
633
|
+
"The type of the proxy that should be used for sending data to Union Station."),
|
622
634
|
AP_INIT_TAKE1("PassengerAnalyticsLogDir",
|
623
635
|
(Take1Func) cmd_passenger_analytics_log_dir,
|
624
636
|
NULL,
|
@@ -399,6 +399,8 @@ struct ServerConfig {
|
|
399
399
|
string unionStationGatewayAddress;
|
400
400
|
int unionStationGatewayPort;
|
401
401
|
string unionStationGatewayCert;
|
402
|
+
string unionStationProxyAddress;
|
403
|
+
string unionStationProxyType;
|
402
404
|
|
403
405
|
/** Directory in which analytics logs should be saved. */
|
404
406
|
string analyticsLogDir;
|
@@ -421,7 +423,9 @@ struct ServerConfig {
|
|
421
423
|
tempDir = getSystemTempDir();
|
422
424
|
unionStationGatewayAddress = DEFAULT_UNION_STATION_GATEWAY_ADDRESS;
|
423
425
|
unionStationGatewayPort = DEFAULT_UNION_STATION_GATEWAY_PORT;
|
424
|
-
unionStationGatewayCert =
|
426
|
+
unionStationGatewayCert = string();
|
427
|
+
unionStationProxyAddress = string();
|
428
|
+
unionStationProxyType = string();
|
425
429
|
analyticsLogUser = DEFAULT_ANALYTICS_LOG_USER;
|
426
430
|
analyticsLogGroup = DEFAULT_ANALYTICS_LOG_GROUP;
|
427
431
|
analyticsLogPermissions = DEFAULT_ANALYTICS_LOG_PERMISSIONS;
|
@@ -466,6 +470,13 @@ struct ServerConfig {
|
|
466
470
|
"/passenger-analytics-logs." +
|
467
471
|
username;
|
468
472
|
}
|
473
|
+
|
474
|
+
if (unionStationProxyType != ""
|
475
|
+
&& unionStationProxyType != "http"
|
476
|
+
&& unionStationProxyType != "socks5") {
|
477
|
+
throw ConfigurationException(string("The option 'UnionStationProxyType' ") +
|
478
|
+
"may only be set to 'http' or 'socks5'.");
|
479
|
+
}
|
469
480
|
}
|
470
481
|
};
|
471
482
|
|
data/ext/apache2/Hooks.cpp
CHANGED
@@ -1404,6 +1404,8 @@ public:
|
|
1404
1404
|
serverConfig.unionStationGatewayAddress,
|
1405
1405
|
serverConfig.unionStationGatewayPort,
|
1406
1406
|
serverConfig.unionStationGatewayCert,
|
1407
|
+
serverConfig.unionStationProxyAddress,
|
1408
|
+
serverConfig.unionStationProxyType,
|
1407
1409
|
serverConfig.prestartURLs);
|
1408
1410
|
|
1409
1411
|
analyticsLogger = ptr(new AnalyticsLogger(agentsStarter.getLoggingSocketAddress(),
|
@@ -61,6 +61,8 @@ agents_starter_start(AgentsStarter *as,
|
|
61
61
|
const char *unionStationGatewayAddress,
|
62
62
|
unsigned short unionStationGatewayPort,
|
63
63
|
const char *unionStationGatewayCert,
|
64
|
+
const char *unionStationProxyAddress,
|
65
|
+
const char *unionStationProxyType,
|
64
66
|
const char **prestartURLs, unsigned int prestartURLsCount,
|
65
67
|
const AfterForkCallback afterFork,
|
66
68
|
void *callbackArgument,
|
@@ -91,6 +93,8 @@ agents_starter_start(AgentsStarter *as,
|
|
91
93
|
unionStationGatewayAddress,
|
92
94
|
unionStationGatewayPort,
|
93
95
|
unionStationGatewayCert,
|
96
|
+
unionStationProxyAddress,
|
97
|
+
unionStationProxyType,
|
94
98
|
setOfprestartURLs,
|
95
99
|
afterForkFunctionObject);
|
96
100
|
return 1;
|
data/ext/common/AgentsStarter.h
CHANGED
@@ -61,6 +61,8 @@ int agents_starter_start(AgentsStarter *as,
|
|
61
61
|
const char *unionStationGatewayAddress,
|
62
62
|
unsigned short unionStationGatewayPort,
|
63
63
|
const char *unionStationGatewayCert,
|
64
|
+
const char *unionStationProxyAddress,
|
65
|
+
const char *unionStationProxyType,
|
64
66
|
const char **prestartURLs, unsigned int prestartURLsCount,
|
65
67
|
const AfterForkCallback afterFork,
|
66
68
|
void *callbackArgument,
|
@@ -384,6 +384,8 @@ public:
|
|
384
384
|
const string &unionStationGatewayAddress,
|
385
385
|
unsigned short unionStationGatewayPort,
|
386
386
|
const string &unionStationGatewayCert,
|
387
|
+
const string &unionStationProxyAddress,
|
388
|
+
const string &unionStationProxyType,
|
387
389
|
const set<string> &prestartURLs,
|
388
390
|
const function<void ()> &afterFork = function<void ()>())
|
389
391
|
{
|
@@ -425,6 +427,8 @@ public:
|
|
425
427
|
.set ("union_station_gateway_address", unionStationGatewayAddress)
|
426
428
|
.setInt ("union_station_gateway_port", unionStationGatewayPort)
|
427
429
|
.set ("union_station_gateway_cert", realUnionStationGatewayCert)
|
430
|
+
.set ("union_station_proxy_address", unionStationProxyAddress)
|
431
|
+
.set ("union_station_proxy_type", unionStationProxyType)
|
428
432
|
.set ("prestart_urls", serializePrestartURLs(prestartURLs));
|
429
433
|
|
430
434
|
SocketPair fds;
|
data/ext/common/Constants.h
CHANGED
data/ext/common/Logging.h
CHANGED
@@ -26,6 +26,8 @@
|
|
26
26
|
#define _PASSENGER_LOGGING_H_
|
27
27
|
|
28
28
|
#include <boost/shared_ptr.hpp>
|
29
|
+
#include <boost/noncopyable.hpp>
|
30
|
+
#include <oxt/thread.hpp>
|
29
31
|
#include <oxt/system_calls.hpp>
|
30
32
|
#include <oxt/backtrace.hpp>
|
31
33
|
|
@@ -38,21 +40,23 @@
|
|
38
40
|
#include <pthread.h>
|
39
41
|
#include <string>
|
40
42
|
#include <map>
|
43
|
+
#include <stdexcept>
|
41
44
|
#include <ostream>
|
42
45
|
#include <sstream>
|
43
46
|
#include <cstdio>
|
44
47
|
#include <ctime>
|
45
48
|
#include <cerrno>
|
46
49
|
|
47
|
-
#include
|
48
|
-
#include
|
49
|
-
#include
|
50
|
-
#include
|
51
|
-
#include
|
52
|
-
#include
|
53
|
-
#include
|
54
|
-
#include
|
55
|
-
#include
|
50
|
+
#include <RandomGenerator.h>
|
51
|
+
#include <FileDescriptor.h>
|
52
|
+
#include <StaticString.h>
|
53
|
+
#include <Exceptions.h>
|
54
|
+
#include <Utils.h>
|
55
|
+
#include <Utils/ScopeGuard.h>
|
56
|
+
#include <Utils/MessageIO.h>
|
57
|
+
#include <Utils/StrIntUtils.h>
|
58
|
+
#include <Utils/MD5.h>
|
59
|
+
#include <Utils/SystemTime.h>
|
56
60
|
|
57
61
|
|
58
62
|
namespace Passenger {
|
@@ -152,51 +156,89 @@ void setDebugFile(const char *logFile = NULL);
|
|
152
156
|
|
153
157
|
/********** Analytics logging facilities *********/
|
154
158
|
|
155
|
-
|
156
|
-
|
157
|
-
|
159
|
+
// All access to the file descriptor must be synchronized through the lock.
|
160
|
+
struct AnalyticsLoggerConnection {
|
161
|
+
mutable boost::mutex lock;
|
162
|
+
FileDescriptor fd;
|
158
163
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
164
|
+
AnalyticsLoggerConnection(FileDescriptor _fd)
|
165
|
+
: fd(_fd)
|
166
|
+
{ }
|
167
|
+
|
168
|
+
bool connected() const {
|
169
|
+
return fd != -1;
|
170
|
+
}
|
171
|
+
|
172
|
+
bool disconnect(string &errorResponse) {
|
173
|
+
if (!connected()) {
|
174
|
+
return false;
|
175
|
+
}
|
176
|
+
|
177
|
+
// The server might send an "error" array message
|
178
|
+
// just before disconnecting. Try to read it.
|
179
|
+
TRACE_POINT();
|
180
|
+
vector<string> response;
|
181
|
+
try {
|
182
|
+
while (true) {
|
183
|
+
unsigned long long timeout = 10000;
|
184
|
+
response = readArrayMessage(fd, &timeout);
|
173
185
|
}
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
186
|
+
} catch (const TimeoutException &) {
|
187
|
+
// This means that the last message isn't an array
|
188
|
+
// message or that the server didn't send it quickly
|
189
|
+
// enough. In any case, discard whatever previous
|
190
|
+
// array messages we were able to read because they're
|
191
|
+
// guaranteed not to be the error message we're expecting.
|
192
|
+
response.clear();
|
193
|
+
} catch (const SystemException &e) {
|
194
|
+
// We treat ECONNRESET the same as EOFException.
|
195
|
+
// Other errors are treated as TimeoutException.
|
196
|
+
if (e.code() != ECONNRESET) {
|
197
|
+
response.clear();
|
183
198
|
}
|
199
|
+
} catch (const EOFException &) {
|
200
|
+
// Do nothing. We've successfully read the last array message.
|
201
|
+
}
|
202
|
+
|
203
|
+
this_thread::disable_interruption di;
|
204
|
+
this_thread::disable_syscall_interruption dsi;
|
205
|
+
UPDATE_TRACE_POINT();
|
206
|
+
fd.close();
|
207
|
+
|
208
|
+
if (response.size() == 2 && response[0] == "error") {
|
209
|
+
errorResponse = response[1];
|
210
|
+
return true;
|
184
211
|
} else {
|
185
|
-
|
212
|
+
return false;
|
186
213
|
}
|
187
214
|
}
|
215
|
+
|
216
|
+
void disconnect() {
|
217
|
+
fd.close();
|
218
|
+
}
|
188
219
|
};
|
189
|
-
|
220
|
+
|
221
|
+
typedef shared_ptr<AnalyticsLoggerConnection> AnalyticsLoggerConnectionPtr;
|
222
|
+
|
223
|
+
|
224
|
+
enum ExceptionHandlingMode {
|
225
|
+
PRINT,
|
226
|
+
THROW,
|
227
|
+
IGNORE
|
228
|
+
};
|
229
|
+
|
190
230
|
|
191
231
|
class AnalyticsLog {
|
192
232
|
private:
|
193
233
|
static const int INT64_STR_BUFSIZE = 22; // Long enough for a 64-bit number.
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
string
|
198
|
-
string
|
199
|
-
string
|
234
|
+
static const unsigned long long IO_TIMEOUT = 5000000; // In microseconds.
|
235
|
+
|
236
|
+
const AnalyticsLoggerConnectionPtr connection;
|
237
|
+
const string txnId;
|
238
|
+
const string groupName;
|
239
|
+
const string category;
|
240
|
+
const string unionStationKey;
|
241
|
+
const ExceptionHandlingMode exceptionHandlingMode;
|
200
242
|
bool shouldFlushToDiskAfterClose;
|
201
243
|
|
202
244
|
/**
|
@@ -227,68 +269,135 @@ private:
|
|
227
269
|
return buffer + 1;
|
228
270
|
}
|
229
271
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
272
|
+
template<typename ExceptionType>
|
273
|
+
void handleException(const ExceptionType &e) {
|
274
|
+
switch (exceptionHandlingMode) {
|
275
|
+
case THROW:
|
276
|
+
throw e;
|
277
|
+
case PRINT:
|
278
|
+
try {
|
279
|
+
const tracable_exception &te =
|
280
|
+
dynamic_cast<const tracable_exception &>(e);
|
281
|
+
P_WARN(te.what() << "\n" << te.backtrace());
|
282
|
+
} catch (const bad_cast &) {
|
283
|
+
P_WARN(e.what());
|
284
|
+
}
|
285
|
+
break;
|
286
|
+
default:
|
287
|
+
break;
|
288
|
+
}
|
242
289
|
}
|
243
290
|
|
291
|
+
public:
|
292
|
+
AnalyticsLog()
|
293
|
+
: exceptionHandlingMode(PRINT)
|
294
|
+
{ }
|
295
|
+
|
296
|
+
AnalyticsLog(const AnalyticsLoggerConnectionPtr &_connection,
|
297
|
+
const string &_txnId,
|
298
|
+
const string &_groupName,
|
299
|
+
const string &_category,
|
300
|
+
const string &_unionStationKey,
|
301
|
+
ExceptionHandlingMode _exceptionHandlingMode = PRINT)
|
302
|
+
: connection(_connection),
|
303
|
+
txnId(_txnId),
|
304
|
+
groupName(_groupName),
|
305
|
+
category(_category),
|
306
|
+
unionStationKey(_unionStationKey),
|
307
|
+
exceptionHandlingMode(_exceptionHandlingMode),
|
308
|
+
shouldFlushToDiskAfterClose(false)
|
309
|
+
{ }
|
310
|
+
|
244
311
|
~AnalyticsLog() {
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
312
|
+
TRACE_POINT();
|
313
|
+
if (connection == NULL) {
|
314
|
+
return;
|
315
|
+
}
|
316
|
+
lock_guard<boost::mutex> l(connection->lock);
|
317
|
+
if (!connection->connected()) {
|
318
|
+
return;
|
319
|
+
}
|
320
|
+
|
321
|
+
char timestamp[2 * sizeof(unsigned long long) + 1];
|
322
|
+
integerToHexatri<unsigned long long>(SystemTime::getUsec(),
|
323
|
+
timestamp);
|
324
|
+
|
325
|
+
UPDATE_TRACE_POINT();
|
326
|
+
ScopeGuard guard(boost::bind(&AnalyticsLoggerConnection::disconnect,
|
327
|
+
connection.get()));
|
328
|
+
try {
|
329
|
+
unsigned long long timeout = IO_TIMEOUT;
|
330
|
+
writeArrayMessage(connection->fd, &timeout,
|
331
|
+
"closeTransaction",
|
332
|
+
txnId.c_str(),
|
333
|
+
timestamp,
|
334
|
+
NULL);
|
335
|
+
|
336
|
+
if (shouldFlushToDiskAfterClose) {
|
337
|
+
UPDATE_TRACE_POINT();
|
338
|
+
timeout = IO_TIMEOUT;
|
339
|
+
writeArrayMessage(connection->fd, &timeout,
|
340
|
+
"flush", NULL);
|
341
|
+
readArrayMessage(connection->fd, &timeout);
|
342
|
+
}
|
343
|
+
guard.clear();
|
344
|
+
} catch (const SystemException &e) {
|
345
|
+
string errorResponse;
|
346
|
+
|
347
|
+
UPDATE_TRACE_POINT();
|
348
|
+
guard.clear();
|
349
|
+
if (connection->disconnect(errorResponse)) {
|
350
|
+
handleException(IOException(
|
351
|
+
string("Logging agent disconnected with error: ") +
|
352
|
+
e.what()));
|
353
|
+
} else {
|
354
|
+
handleException(e);
|
268
355
|
}
|
269
356
|
}
|
270
357
|
}
|
271
358
|
|
272
359
|
void message(const StaticString &text) {
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
360
|
+
TRACE_POINT();
|
361
|
+
if (connection == NULL) {
|
362
|
+
return;
|
363
|
+
}
|
364
|
+
lock_guard<boost::mutex> l(connection->lock);
|
365
|
+
if (!connection->connected()) {
|
366
|
+
return;
|
367
|
+
}
|
368
|
+
|
369
|
+
char timestamp[2 * sizeof(unsigned long long) + 1];
|
370
|
+
integerToHexatri<unsigned long long>(SystemTime::getUsec(), timestamp);
|
371
|
+
|
372
|
+
UPDATE_TRACE_POINT();
|
373
|
+
ScopeGuard guard(boost::bind(&AnalyticsLoggerConnection::disconnect,
|
374
|
+
connection.get()));
|
375
|
+
try {
|
376
|
+
unsigned long long timeout = IO_TIMEOUT;
|
377
|
+
writeArrayMessage(connection->fd, &timeout,
|
378
|
+
"log",
|
379
|
+
txnId.c_str(),
|
380
|
+
timestamp,
|
381
|
+
NULL);
|
382
|
+
writeScalarMessage(connection->fd, text, &timeout);
|
383
|
+
guard.clear();
|
384
|
+
} catch (const std::exception &e) {
|
385
|
+
string errorResponse;
|
386
|
+
|
387
|
+
UPDATE_TRACE_POINT();
|
388
|
+
guard.clear();
|
389
|
+
if (connection->disconnect(errorResponse)) {
|
390
|
+
handleException(IOException(
|
391
|
+
string("Logging agent disconnected with error: ") +
|
392
|
+
e.what()));
|
393
|
+
} else {
|
394
|
+
handleException(e);
|
281
395
|
}
|
282
396
|
}
|
283
397
|
}
|
284
398
|
|
285
399
|
void abort(const StaticString &text) {
|
286
|
-
|
287
|
-
lock_guard<boost::mutex> l(sharedData->lock);
|
288
|
-
if (sharedData->client.connected()) {
|
289
|
-
message("ABORT");
|
290
|
-
}
|
291
|
-
}
|
400
|
+
message("ABORT");
|
292
401
|
}
|
293
402
|
|
294
403
|
void flushToDiskAfterClose(bool value) {
|
@@ -296,7 +405,7 @@ public:
|
|
296
405
|
}
|
297
406
|
|
298
407
|
bool isNull() const {
|
299
|
-
return
|
408
|
+
return connection == NULL;
|
300
409
|
}
|
301
410
|
|
302
411
|
string getTxnId() const {
|
@@ -318,9 +427,10 @@ public:
|
|
318
427
|
|
319
428
|
typedef shared_ptr<AnalyticsLog> AnalyticsLogPtr;
|
320
429
|
|
321
|
-
|
430
|
+
|
431
|
+
class AnalyticsScopeLog: public boost::noncopyable {
|
322
432
|
private:
|
323
|
-
AnalyticsLog *log;
|
433
|
+
AnalyticsLog * const log;
|
324
434
|
enum {
|
325
435
|
NAME,
|
326
436
|
GRANULAR
|
@@ -346,8 +456,9 @@ private:
|
|
346
456
|
}
|
347
457
|
|
348
458
|
public:
|
349
|
-
AnalyticsScopeLog(const AnalyticsLogPtr &
|
350
|
-
|
459
|
+
AnalyticsScopeLog(const AnalyticsLogPtr &_log, const char *name)
|
460
|
+
: log(_log.get())
|
461
|
+
{
|
351
462
|
type = NAME;
|
352
463
|
data.name = name;
|
353
464
|
ok = false;
|
@@ -373,16 +484,18 @@ public:
|
|
373
484
|
}
|
374
485
|
}
|
375
486
|
|
376
|
-
AnalyticsScopeLog(const AnalyticsLogPtr &
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
487
|
+
AnalyticsScopeLog(const AnalyticsLogPtr &_log,
|
488
|
+
const char *beginMessage,
|
489
|
+
const char *endMessage,
|
490
|
+
const char *abortMessage = NULL)
|
491
|
+
: log(_log.get())
|
492
|
+
{
|
493
|
+
if (_log != NULL) {
|
381
494
|
type = GRANULAR;
|
382
495
|
data.granular.endMessage = endMessage;
|
383
496
|
data.granular.abortMessage = abortMessage;
|
384
497
|
ok = abortMessage == NULL;
|
385
|
-
|
498
|
+
_log->message(beginMessage);
|
386
499
|
}
|
387
500
|
}
|
388
501
|
|
@@ -429,36 +542,37 @@ public:
|
|
429
542
|
}
|
430
543
|
};
|
431
544
|
|
545
|
+
|
432
546
|
class AnalyticsLogger {
|
433
547
|
private:
|
434
|
-
/** A special lock type for
|
548
|
+
/** A special lock type for AnalyticsLoggerConnection that also
|
435
549
|
* keeps a smart pointer to the data structure so that the mutex
|
436
550
|
* is not destroyed prematurely.
|
437
551
|
*/
|
438
|
-
struct
|
439
|
-
|
552
|
+
struct ConnectionLock {
|
553
|
+
AnalyticsLoggerConnectionPtr connection;
|
440
554
|
bool locked;
|
441
555
|
|
442
|
-
|
443
|
-
:
|
556
|
+
ConnectionLock(const AnalyticsLoggerConnectionPtr &c)
|
557
|
+
: connection(c)
|
444
558
|
{
|
445
|
-
|
559
|
+
c->lock.lock();
|
446
560
|
locked = true;
|
447
561
|
}
|
448
562
|
|
449
|
-
~
|
563
|
+
~ConnectionLock() {
|
450
564
|
if (locked) {
|
451
|
-
|
565
|
+
connection->lock.unlock();
|
452
566
|
}
|
453
567
|
}
|
454
568
|
|
455
|
-
void reset(const
|
569
|
+
void reset(const AnalyticsLoggerConnectionPtr &c, bool lockNow = true) {
|
456
570
|
if (locked) {
|
457
|
-
|
571
|
+
connection->lock.unlock();
|
458
572
|
}
|
459
|
-
|
573
|
+
connection = c;
|
460
574
|
if (lockNow) {
|
461
|
-
|
575
|
+
connection->lock.lock();
|
462
576
|
locked = true;
|
463
577
|
} else {
|
464
578
|
locked = false;
|
@@ -467,39 +581,84 @@ private:
|
|
467
581
|
|
468
582
|
void lock() {
|
469
583
|
assert(!locked);
|
470
|
-
|
584
|
+
connection->lock.lock();
|
471
585
|
locked = true;
|
472
586
|
}
|
473
587
|
};
|
474
588
|
|
475
|
-
|
476
|
-
|
477
|
-
string
|
478
|
-
string
|
479
|
-
string password;
|
480
|
-
string nodeName;
|
589
|
+
const string serverAddress;
|
590
|
+
const string username;
|
591
|
+
const string password;
|
592
|
+
const string nodeName;
|
481
593
|
RandomGenerator randomGenerator;
|
482
594
|
|
483
|
-
/** Lock protecting the fields that follow, but not the
|
595
|
+
/** Lock protecting the fields that follow, but not the
|
596
|
+
* contents of the connection object.
|
597
|
+
*/
|
484
598
|
mutable boost::mutex lock;
|
485
599
|
|
486
600
|
unsigned int maxConnectTries;
|
487
601
|
unsigned long long reconnectTimeout;
|
488
602
|
unsigned long long nextReconnectTime;
|
489
|
-
/**
|
490
|
-
|
603
|
+
/** Normally never NULL, except when constructed with the default constructor
|
604
|
+
* or if serverName is empty. In those cases the AnalyticsLogger object is
|
605
|
+
* considered unusable.
|
606
|
+
*/
|
607
|
+
AnalyticsLoggerConnectionPtr connection;
|
608
|
+
|
609
|
+
static string determineNodeName(const string &givenNodeName) {
|
610
|
+
if (givenNodeName.empty()) {
|
611
|
+
return getHostName();
|
612
|
+
} else {
|
613
|
+
return givenNodeName;
|
614
|
+
}
|
615
|
+
}
|
616
|
+
|
617
|
+
static bool isNetworkError(int code) {
|
618
|
+
return code == EPIPE || code == ECONNREFUSED || code == ECONNRESET
|
619
|
+
|| code == EHOSTUNREACH || code == ENETDOWN || code == ENETUNREACH
|
620
|
+
|| code == ETIMEDOUT;
|
621
|
+
}
|
491
622
|
|
492
623
|
bool connected() const {
|
493
|
-
return
|
624
|
+
return connection->connected();
|
494
625
|
}
|
495
626
|
|
496
627
|
void connect() {
|
497
628
|
TRACE_POINT();
|
629
|
+
FileDescriptor fd;
|
498
630
|
vector<string> args;
|
631
|
+
unsigned long long timeout = 15000000;
|
632
|
+
|
633
|
+
fd = connectToServer(serverAddress);
|
634
|
+
if (!readArrayMessage(fd, args, &timeout)) {
|
635
|
+
throw IOException("The logging agent closed the connection before sending a version identifier.");
|
636
|
+
}
|
637
|
+
if (args.size() != 2 || args[0] != "version") {
|
638
|
+
throw IOException("The logging agent server didn't sent a valid version identifier.");
|
639
|
+
}
|
640
|
+
if (args[1] != "1") {
|
641
|
+
string message = string("Unsupported logging agent protocol version ") +
|
642
|
+
args[1] + ".";
|
643
|
+
throw IOException(message);
|
644
|
+
}
|
645
|
+
|
646
|
+
UPDATE_TRACE_POINT();
|
647
|
+
writeScalarMessage(fd, username, &timeout);
|
648
|
+
writeScalarMessage(fd, password, &timeout);
|
649
|
+
|
650
|
+
UPDATE_TRACE_POINT();
|
651
|
+
if (!readArrayMessage(fd, args, &timeout)) {
|
652
|
+
throw IOException("The logging agent did not send an authentication response.");
|
653
|
+
} else if (args.size() != 1) {
|
654
|
+
throw IOException("The authentication response that the logging agent sent is not valid.");
|
655
|
+
} else if (args[0] != "ok") {
|
656
|
+
throw SecurityException("The logging agent server denied authentication: " + args[0]);
|
657
|
+
}
|
499
658
|
|
500
|
-
|
501
|
-
|
502
|
-
if (!
|
659
|
+
UPDATE_TRACE_POINT();
|
660
|
+
writeArrayMessage(fd, &timeout, "init", nodeName.c_str(), NULL);
|
661
|
+
if (!readArrayMessage(fd, args, &timeout)) {
|
503
662
|
throw SystemException("Cannot connect to logging server", ECONNREFUSED);
|
504
663
|
} else if (args.size() != 1) {
|
505
664
|
throw IOException("Logging server returned an invalid reply for the 'init' command");
|
@@ -509,58 +668,48 @@ private:
|
|
509
668
|
throw IOException("Logging server returned an invalid reply for the 'init' command");
|
510
669
|
}
|
511
670
|
|
512
|
-
|
513
|
-
// message before closing the socket.
|
514
|
-
sharedData->client.setAutoDisconnect(false);
|
515
|
-
}
|
516
|
-
|
517
|
-
void disconnect(bool checkErrorResponse = false) {
|
518
|
-
sharedData->disconnect(checkErrorResponse);
|
519
|
-
// We create a new SharedData here so that existing AnalyticsLog
|
520
|
-
// objects still refer to the old client object and don't interfere
|
521
|
-
// with any newly-established connections.
|
522
|
-
sharedData.reset(new AnalyticsLoggerSharedData());
|
523
|
-
}
|
524
|
-
|
525
|
-
bool isNetworkError(int code) const {
|
526
|
-
return code == EPIPE || code == ECONNREFUSED || code == ECONNRESET
|
527
|
-
|| code == EHOSTUNREACH || code == ENETDOWN || code == ENETUNREACH
|
528
|
-
|| code == ETIMEDOUT;
|
671
|
+
connection = make_shared<AnalyticsLoggerConnection>(fd);
|
529
672
|
}
|
530
673
|
|
531
674
|
public:
|
532
675
|
AnalyticsLogger() { }
|
533
676
|
|
534
|
-
AnalyticsLogger(const string &
|
535
|
-
const string &
|
677
|
+
AnalyticsLogger(const string &_serverAddress, const string &_username,
|
678
|
+
const string &_password, const string &_nodeName = "")
|
679
|
+
: serverAddress(_serverAddress),
|
680
|
+
username(_username),
|
681
|
+
password(_password),
|
682
|
+
nodeName(determineNodeName(_nodeName))
|
536
683
|
{
|
537
|
-
this->serverAddress = serverAddress;
|
538
|
-
this->username = username;
|
539
|
-
this->password = password;
|
540
|
-
if (nodeName.empty()) {
|
541
|
-
this->nodeName = getHostName();
|
542
|
-
} else {
|
543
|
-
this->nodeName = nodeName;
|
544
|
-
}
|
545
684
|
if (!serverAddress.empty()) {
|
546
|
-
|
685
|
+
connection = make_shared<AnalyticsLoggerConnection>(FileDescriptor());
|
547
686
|
}
|
548
687
|
if (isLocalSocketAddress(serverAddress)) {
|
549
688
|
maxConnectTries = 10;
|
550
689
|
} else {
|
551
690
|
maxConnectTries = 1;
|
552
691
|
}
|
553
|
-
maxConnectTries = 10;
|
554
692
|
reconnectTimeout = 1000000;
|
555
693
|
nextReconnectTime = 0;
|
556
694
|
}
|
557
695
|
|
558
|
-
|
696
|
+
template<typename T>
|
697
|
+
static bool instanceof(const std::exception &e) {
|
698
|
+
try {
|
699
|
+
dynamic_cast<const T &>(e);
|
700
|
+
return true;
|
701
|
+
} catch (const bad_cast &) {
|
702
|
+
return false;
|
703
|
+
}
|
704
|
+
}
|
705
|
+
|
706
|
+
AnalyticsLogPtr newTransaction(const string &groupName,
|
707
|
+
const string &category = "requests",
|
559
708
|
const string &unionStationKey = string(),
|
560
709
|
const string &filters = string())
|
561
710
|
{
|
562
711
|
if (serverAddress.empty()) {
|
563
|
-
return
|
712
|
+
return make_shared<AnalyticsLog>();
|
564
713
|
}
|
565
714
|
|
566
715
|
unsigned long long timestamp = SystemTime::getUsec();
|
@@ -593,129 +742,200 @@ public:
|
|
593
742
|
integerToHexatri<unsigned long long>(timestamp, timestampStr);
|
594
743
|
|
595
744
|
unique_lock<boost::mutex> l(lock);
|
596
|
-
|
745
|
+
if (SystemTime::getUsec() < nextReconnectTime) {
|
746
|
+
return make_shared<AnalyticsLog>();
|
747
|
+
}
|
748
|
+
ConnectionLock cl(connection);
|
597
749
|
|
598
|
-
if (
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
NULL);
|
618
|
-
|
619
|
-
vector<string> args;
|
620
|
-
sharedData->client.read(args);
|
621
|
-
if (args.size() == 2 && args[0] == "error") {
|
622
|
-
disconnect();
|
623
|
-
throw IOException("The logging server responded with an error: " + args[1]);
|
624
|
-
} else if (args.empty() || args[0] != "ok") {
|
625
|
-
disconnect();
|
626
|
-
throw IOException("The logging server sent an unexpected reply.");
|
627
|
-
}
|
628
|
-
|
629
|
-
return ptr(new AnalyticsLog(sharedData,
|
630
|
-
string(txnId, end - txnId),
|
631
|
-
groupName, category,
|
632
|
-
unionStationKey));
|
633
|
-
} catch (const SystemException &e) {
|
634
|
-
TRACE_POINT();
|
635
|
-
if (e.code() == ENOENT || isNetworkError(e.code())) {
|
636
|
-
tryCount++;
|
637
|
-
disconnect(true);
|
638
|
-
sl.reset(sharedData, false);
|
639
|
-
l.unlock();
|
640
|
-
if (tryCount < maxConnectTries) {
|
641
|
-
syscalls::usleep(RETRY_SLEEP);
|
642
|
-
}
|
643
|
-
l.lock();
|
644
|
-
sl.lock();
|
645
|
-
} else {
|
646
|
-
disconnect();
|
647
|
-
throw;
|
648
|
-
}
|
750
|
+
if (!connected()) {
|
751
|
+
TRACE_POINT();
|
752
|
+
try {
|
753
|
+
connect();
|
754
|
+
cl.reset(connection);
|
755
|
+
} catch (const TimeoutException &) {
|
756
|
+
P_WARN("Timeout trying to connect to the logging agent at " << serverAddress << "; " <<
|
757
|
+
"will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
|
758
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
759
|
+
return make_shared<AnalyticsLog>();
|
760
|
+
} catch (const tracable_exception &e) {
|
761
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
762
|
+
if (instanceof<IOException>(e) || instanceof<SystemException>(e)) {
|
763
|
+
P_WARN("Cannot connect to the logging agent at " << serverAddress <<
|
764
|
+
" (" << e.what() << "); will reconnect in " <<
|
765
|
+
reconnectTimeout / 1000000 << " second(s).");
|
766
|
+
return make_shared<AnalyticsLog>();
|
767
|
+
} else {
|
768
|
+
throw;
|
649
769
|
}
|
770
|
+
}
|
771
|
+
}
|
772
|
+
|
773
|
+
ScopeGuard guard(boost::bind(
|
774
|
+
&AnalyticsLoggerConnection::disconnect,
|
775
|
+
connection.get()));
|
776
|
+
try {
|
777
|
+
unsigned long long timeout = 15000000;
|
778
|
+
|
779
|
+
writeArrayMessage(connection->fd, &timeout,
|
780
|
+
"openTransaction",
|
781
|
+
txnId,
|
782
|
+
groupName.c_str(),
|
783
|
+
"",
|
784
|
+
category.c_str(),
|
785
|
+
timestampStr,
|
786
|
+
unionStationKey.c_str(),
|
787
|
+
"true",
|
788
|
+
"true",
|
789
|
+
filters.c_str(),
|
790
|
+
NULL);
|
791
|
+
|
792
|
+
vector<string> args;
|
793
|
+
if (!readArrayMessage(connection->fd, args, &timeout)) {
|
794
|
+
P_WARN("The logging agent at " << serverAddress <<
|
795
|
+
" closed the connection (no error message given);" <<
|
796
|
+
" will reconnect in " << reconnectTimeout / 1000000 <<
|
797
|
+
" second(s).");
|
798
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
799
|
+
return make_shared<AnalyticsLog>();
|
800
|
+
} else if (args.size() == 2 && args[0] == "error") {
|
801
|
+
P_WARN("The logging agent at " << serverAddress <<
|
802
|
+
" closed the connection (error message: " << args[1] <<
|
803
|
+
"); will reconnect in " << reconnectTimeout / 1000000 <<
|
804
|
+
" second(s).");
|
805
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
806
|
+
return make_shared<AnalyticsLog>();
|
807
|
+
} else if (args.empty() || args[0] != "ok") {
|
808
|
+
P_WARN("The logging agent at " << serverAddress <<
|
809
|
+
" sent an unexpected reply;" <<
|
810
|
+
" will reconnect in " << reconnectTimeout / 1000000 <<
|
811
|
+
" second(s).");
|
812
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
813
|
+
return make_shared<AnalyticsLog>();
|
814
|
+
}
|
815
|
+
|
816
|
+
guard.clear();
|
817
|
+
return make_shared<AnalyticsLog>(connection,
|
818
|
+
string(txnId, end - txnId),
|
819
|
+
groupName, category,
|
820
|
+
unionStationKey);
|
821
|
+
|
822
|
+
} catch (const TimeoutException &) {
|
823
|
+
P_WARN("Timeout trying to communicate with the logging agent at " << serverAddress << "; " <<
|
824
|
+
"will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
|
825
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
826
|
+
return make_shared<AnalyticsLog>();
|
827
|
+
|
828
|
+
} catch (const SystemException &e) {
|
829
|
+
if (e.code() == ENOENT || isNetworkError(e.code())) {
|
830
|
+
string errorResponse;
|
650
831
|
|
651
|
-
|
652
|
-
|
653
|
-
"
|
832
|
+
guard.clear();
|
833
|
+
if (connection->disconnect(errorResponse)) {
|
834
|
+
P_WARN("The logging agent at " << serverAddress <<
|
835
|
+
" closed the connection (error message: " << errorResponse <<
|
836
|
+
"); will reconnect in " << reconnectTimeout / 1000000 <<
|
837
|
+
" second(s).");
|
838
|
+
} else {
|
839
|
+
P_WARN("The logging agent at " << serverAddress <<
|
840
|
+
" closed the connection (no error message given);" <<
|
841
|
+
" will reconnect in " << reconnectTimeout / 1000000 <<
|
842
|
+
" second(s).");
|
843
|
+
}
|
654
844
|
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
845
|
+
return make_shared<AnalyticsLog>();
|
846
|
+
} else {
|
847
|
+
throw;
|
655
848
|
}
|
656
849
|
}
|
657
|
-
return ptr(new AnalyticsLog());
|
658
850
|
}
|
659
851
|
|
660
852
|
AnalyticsLogPtr continueTransaction(const string &txnId, const string &groupName,
|
661
853
|
const string &category = "requests", const string &unionStationKey = string())
|
662
854
|
{
|
663
855
|
if (serverAddress.empty() || txnId.empty()) {
|
664
|
-
return
|
856
|
+
return make_shared<AnalyticsLog>();
|
665
857
|
}
|
666
858
|
|
667
859
|
char timestampStr[2 * sizeof(unsigned long long) + 1];
|
668
860
|
integerToHexatri<unsigned long long>(SystemTime::getUsec(), timestampStr);
|
669
861
|
|
670
862
|
unique_lock<boost::mutex> l(lock);
|
671
|
-
|
863
|
+
if (SystemTime::getUsec() < nextReconnectTime) {
|
864
|
+
return make_shared<AnalyticsLog>();
|
865
|
+
}
|
866
|
+
ConnectionLock cl(connection);
|
672
867
|
|
673
|
-
if (
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
txnId, groupName, category,
|
693
|
-
unionStationKey));
|
694
|
-
} catch (const SystemException &e) {
|
695
|
-
TRACE_POINT();
|
696
|
-
if (e.code() == EPIPE || isNetworkError(e.code())) {
|
697
|
-
tryCount++;
|
698
|
-
disconnect(true);
|
699
|
-
sl.reset(sharedData, false);
|
700
|
-
l.unlock();
|
701
|
-
if (tryCount < maxConnectTries) {
|
702
|
-
syscalls::usleep(RETRY_SLEEP);
|
703
|
-
}
|
704
|
-
l.lock();
|
705
|
-
sl.lock();
|
706
|
-
} else {
|
707
|
-
disconnect();
|
708
|
-
throw;
|
709
|
-
}
|
868
|
+
if (!connected()) {
|
869
|
+
TRACE_POINT();
|
870
|
+
try {
|
871
|
+
connect();
|
872
|
+
cl.reset(connection);
|
873
|
+
} catch (const TimeoutException &) {
|
874
|
+
P_WARN("Timeout trying to connect to the logging agent at " << serverAddress << "; " <<
|
875
|
+
"will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
|
876
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
877
|
+
return make_shared<AnalyticsLog>();
|
878
|
+
} catch (const tracable_exception &e) {
|
879
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
880
|
+
if (instanceof<IOException>(e) || instanceof<SystemException>(e)) {
|
881
|
+
P_WARN("Cannot connect to the logging agent at " << serverAddress <<
|
882
|
+
" (" << e.what() << "); will reconnect in " <<
|
883
|
+
reconnectTimeout / 1000000 << " second(s).");
|
884
|
+
return make_shared<AnalyticsLog>();
|
885
|
+
} else {
|
886
|
+
throw;
|
710
887
|
}
|
711
888
|
}
|
889
|
+
}
|
890
|
+
|
891
|
+
ScopeGuard guard(boost::bind(
|
892
|
+
&AnalyticsLoggerConnection::disconnect,
|
893
|
+
connection.get()));
|
894
|
+
try {
|
895
|
+
unsigned long long timeout = 15000000;
|
896
|
+
writeArrayMessage(connection->fd, &timeout,
|
897
|
+
"openTransaction",
|
898
|
+
txnId.c_str(),
|
899
|
+
groupName.c_str(),
|
900
|
+
"",
|
901
|
+
category.c_str(),
|
902
|
+
timestampStr,
|
903
|
+
unionStationKey.c_str(),
|
904
|
+
"true",
|
905
|
+
NULL);
|
906
|
+
guard.clear();
|
907
|
+
return make_shared<AnalyticsLog>(connection,
|
908
|
+
txnId, groupName, category,
|
909
|
+
unionStationKey);
|
712
910
|
|
713
|
-
|
714
|
-
P_WARN("
|
715
|
-
"
|
911
|
+
} catch (const TimeoutException &) {
|
912
|
+
P_WARN("Timeout trying to communicate with the logging agent at " << serverAddress << "; " <<
|
913
|
+
"will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
|
716
914
|
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
915
|
+
return make_shared<AnalyticsLog>();
|
916
|
+
|
917
|
+
} catch (const SystemException &e) {
|
918
|
+
if (e.code() == ENOENT || isNetworkError(e.code())) {
|
919
|
+
string errorResponse;
|
920
|
+
|
921
|
+
guard.clear();
|
922
|
+
if (connection->disconnect(errorResponse)) {
|
923
|
+
P_WARN("The logging agent at " << serverAddress <<
|
924
|
+
" closed the connection (error message: " << errorResponse <<
|
925
|
+
"); will reconnect in " << reconnectTimeout / 1000000 <<
|
926
|
+
" second(s).");
|
927
|
+
} else {
|
928
|
+
P_WARN("The logging agent at " << serverAddress <<
|
929
|
+
" closed the connection (no error message given);" <<
|
930
|
+
" will reconnect in " << reconnectTimeout / 1000000 <<
|
931
|
+
" second(s).");
|
932
|
+
}
|
933
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
934
|
+
return make_shared<AnalyticsLog>();
|
935
|
+
} else {
|
936
|
+
throw;
|
937
|
+
}
|
717
938
|
}
|
718
|
-
return ptr(new AnalyticsLog());
|
719
939
|
}
|
720
940
|
|
721
941
|
void setMaxConnectTries(unsigned int value) {
|
@@ -746,8 +966,8 @@ public:
|
|
746
966
|
|
747
967
|
FileDescriptor getConnection() const {
|
748
968
|
lock_guard<boost::mutex> l(lock);
|
749
|
-
lock_guard<boost::mutex> l2(
|
750
|
-
return
|
969
|
+
lock_guard<boost::mutex> l2(connection->lock);
|
970
|
+
return connection->fd;
|
751
971
|
}
|
752
972
|
|
753
973
|
/**
|