passenger 5.3.4 → 6.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +69 -0
- data/CONTRIBUTORS +1 -0
- data/README.md +2 -1
- data/Rakefile +0 -5
- data/build/agent.rb +6 -3
- data/build/cxx_tests.rb +28 -19
- data/build/integration_tests.rb +6 -2
- data/build/misc.rb +2 -1
- data/build/packaging.rb +2 -0
- data/build/support/cplusplus.rb +2 -2
- data/build/support/cxx_dependency_map.rb +2651 -2189
- data/dev/colorize-logs +272 -0
- data/dev/show-latest-crashlog-dir +27 -0
- data/resources/templates/standalone/http.erb +2 -0
- data/resources/templates/standalone/server.erb +1 -0
- data/src/agent/AgentMain.cpp +4 -0
- data/src/agent/Core/AdminPanelConnector.h +6 -6
- data/src/agent/Core/ApiServer.h +4 -4
- data/src/agent/Core/ApplicationPool/BasicProcessInfo.h +2 -2
- data/src/agent/Core/ApplicationPool/Context.h +5 -1
- data/src/agent/Core/ApplicationPool/Group/InternalUtils.cpp +2 -2
- data/src/agent/Core/ApplicationPool/Group/LifetimeAndBasics.cpp +5 -0
- data/src/agent/Core/ApplicationPool/Group/Miscellaneous.cpp +2 -1
- data/src/agent/Core/ApplicationPool/Group/OutOfBandWork.cpp +3 -3
- data/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +1 -1
- data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +13 -20
- data/src/agent/Core/ApplicationPool/Group.h +4 -2
- data/src/agent/Core/ApplicationPool/Implementation.cpp +5 -5
- data/src/agent/Core/ApplicationPool/Options.h +42 -38
- data/src/agent/Core/ApplicationPool/Pool/GroupUtils.cpp +2 -1
- data/src/agent/Core/ApplicationPool/Pool.h +4 -4
- data/src/agent/Core/ApplicationPool/Process.h +13 -15
- data/src/agent/Core/ApplicationPool/Socket.h +5 -5
- data/src/agent/Core/ApplicationPool/TestSession.h +3 -3
- data/src/agent/Core/Config.h +50 -10
- data/src/agent/Core/ConfigChange.cpp +13 -1
- data/src/agent/Core/Controller/Config.h +41 -17
- data/src/agent/Core/Controller/ForwardResponse.cpp +4 -0
- data/src/agent/Core/Controller/InitRequest.cpp +14 -8
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +5 -0
- data/src/agent/Core/Controller/SendRequest.cpp +9 -9
- data/src/agent/Core/Controller/TurboCaching.h +2 -2
- data/src/agent/Core/Controller.h +7 -5
- data/src/agent/Core/CoreMain.cpp +204 -60
- data/src/agent/Core/OptionParser.h +20 -3
- data/src/agent/Core/ResponseCache.h +3 -3
- data/src/agent/Core/SecurityUpdateChecker.h +4 -2
- data/src/agent/Core/SpawningKit/Config/AutoGeneratedCode.h +1 -1
- data/src/agent/Core/SpawningKit/Config.h +3 -2
- data/src/agent/Core/SpawningKit/Context.h +8 -2
- data/src/agent/Core/SpawningKit/DirectSpawner.h +4 -4
- data/src/agent/Core/SpawningKit/DummySpawner.h +3 -3
- data/src/agent/Core/SpawningKit/ErrorRenderer.h +1 -1
- data/src/agent/Core/SpawningKit/Exceptions.h +21 -14
- data/src/agent/Core/SpawningKit/Factory.h +1 -1
- data/src/agent/Core/SpawningKit/Handshake/BackgroundIOCapturer.h +1 -1
- data/src/agent/Core/SpawningKit/Handshake/Perform.h +14 -2
- data/src/agent/Core/SpawningKit/Handshake/Prepare.h +3 -3
- data/src/agent/Core/SpawningKit/Handshake/WorkDir.h +1 -1
- data/src/agent/Core/SpawningKit/Journey.h +4 -5
- data/src/agent/Core/SpawningKit/PipeWatcher.h +1 -1
- data/src/agent/Core/SpawningKit/README.md +34 -17
- data/src/agent/Core/SpawningKit/Result/AutoGeneratedCode.h +1 -1
- data/src/agent/Core/SpawningKit/Result.h +20 -8
- data/src/agent/Core/SpawningKit/SmartSpawner.h +7 -7
- data/src/agent/Core/SpawningKit/Spawner.h +25 -8
- data/src/agent/Core/SpawningKit/UserSwitchingRules.h +17 -7
- data/src/agent/Core/TelemetryCollector.h +681 -0
- data/src/agent/ExecHelper/ExecHelperMain.cpp +1 -1
- data/src/agent/FileReadHelper/FileReadHelperMain.cpp +198 -0
- data/src/agent/README.md +1 -1
- data/src/agent/Shared/ApiAccountUtils.h +1 -1
- data/src/agent/Shared/ApiServerUtils.h +3 -3
- data/src/agent/Shared/ApplicationPoolApiKey.h +2 -2
- data/src/agent/Shared/Fundamentals/AbortHandler.cpp +324 -98
- data/src/agent/Shared/Fundamentals/AbortHandler.h +31 -4
- data/src/agent/Shared/Fundamentals/Initialization.cpp +4 -5
- data/src/agent/Shared/Fundamentals/Initialization.h +9 -1
- data/src/agent/SpawnEnvSetupper/SpawnEnvSetupperMain.cpp +1 -1
- data/src/agent/SystemMetrics/SystemMetricsMain.cpp +4 -3
- data/src/agent/TempDirToucher/TempDirToucherMain.cpp +3 -3
- data/src/agent/Watchdog/ApiServer.h +3 -3
- data/src/agent/Watchdog/Config.h +24 -5
- data/src/agent/Watchdog/CoreWatcher.cpp +2 -2
- data/src/agent/Watchdog/WatchdogMain.cpp +97 -28
- data/src/apache2_module/Config.cpp +14 -14
- data/src/apache2_module/Config.h +8 -16
- data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +510 -481
- data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp.cxxcodebuilder +39 -17
- data/src/apache2_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.cpp +5 -0
- data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +69 -1
- data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp.cxxcodebuilder +31 -1
- data/src/apache2_module/ConfigGeneral/Common.h +45 -0
- data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp +17 -1
- data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp.cxxcodebuilder +16 -1
- data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp +19 -5
- data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp.cxxcodebuilder +26 -9
- data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp +19 -1
- data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp.cxxcodebuilder +10 -1
- data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp +14 -1
- data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp.cxxcodebuilder +11 -1
- data/src/apache2_module/DirConfig/AutoGeneratedStruct.h +36 -1
- data/src/apache2_module/DirConfig/AutoGeneratedStruct.h.cxxcodebuilder +34 -1
- data/src/apache2_module/DirectoryMapper.h +36 -37
- data/src/apache2_module/Hooks.cpp +27 -8
- data/src/apache2_module/ServerConfig/AutoGeneratedManifestGeneration.cpp +20 -0
- data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h +48 -1
- data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h.cxxcodebuilder +36 -1
- data/src/cxx_supportlib/{Utils → Algorithms}/Hasher.cpp +2 -2
- data/src/cxx_supportlib/{Utils → Algorithms}/Hasher.h +4 -4
- data/src/cxx_supportlib/AppLocalConfigFileUtils.h +148 -0
- data/src/cxx_supportlib/AppTypeDetector/CBindings.cpp +147 -0
- data/src/cxx_supportlib/AppTypeDetector/CBindings.h +75 -0
- data/src/cxx_supportlib/{AppTypes.h → AppTypeDetector/Detector.h} +92 -131
- data/src/cxx_supportlib/ConfigKit/README.md +90 -2
- data/src/cxx_supportlib/ConfigKit/Schema.h +60 -15
- data/src/cxx_supportlib/ConfigKit/Store.h +129 -5
- data/src/cxx_supportlib/Constants.h +1 -1
- data/src/cxx_supportlib/{Utils → DataStructures}/HashMap.h +4 -4
- data/src/cxx_supportlib/DataStructures/HashedStaticString.h +5 -5
- data/src/cxx_supportlib/DataStructures/LString.h +3 -3
- data/src/cxx_supportlib/{Utils → DataStructures}/StringMap.h +36 -36
- data/src/cxx_supportlib/FileTools/FileManip.cpp +1 -1
- data/src/cxx_supportlib/FileTools/PathManip.cpp +2 -2
- data/src/cxx_supportlib/FileTools/PathSecurityCheck.cpp +1 -1
- data/src/cxx_supportlib/Hooks.h +2 -2
- data/src/cxx_supportlib/{Utils → IOTools}/BufferedIO.h +5 -5
- data/src/cxx_supportlib/{Utils → IOTools}/IOUtils.cpp +4 -3
- data/src/cxx_supportlib/{Utils → IOTools}/IOUtils.h +3 -3
- data/src/cxx_supportlib/{Utils → IOTools}/MessageIO.h +7 -7
- data/src/cxx_supportlib/{MessageReadersWriters.h → IOTools/MessageSerialization.h} +5 -5
- data/src/cxx_supportlib/InstanceDirectory.h +4 -4
- data/src/cxx_supportlib/Integrations/LibevJsonUtils.h +3 -3
- data/src/cxx_supportlib/{Utils → JsonTools}/JsonUtils.h +5 -5
- data/src/cxx_supportlib/LoggingKit/Context.h +2 -2
- data/src/cxx_supportlib/LoggingKit/Implementation.cpp +3 -3
- data/src/cxx_supportlib/MemoryKit/mbuf.cpp +2 -2
- data/src/cxx_supportlib/ProcessManagement/Ruby.cpp +3 -3
- data/src/cxx_supportlib/ProcessManagement/Ruby.h +7 -2
- data/src/cxx_supportlib/ProcessManagement/Spawn.cpp +19 -12
- data/src/cxx_supportlib/ProcessManagement/Spawn.h +21 -2
- data/src/cxx_supportlib/ProcessManagement/Utils.h +10 -0
- data/src/cxx_supportlib/RandomGenerator.h +2 -2
- data/src/cxx_supportlib/ResourceLocator.h +1 -1
- data/src/cxx_supportlib/{Crypto.cpp → SecurityKit/Crypto.cpp} +4 -4
- data/src/cxx_supportlib/{Crypto.h → SecurityKit/Crypto.h} +4 -4
- data/src/cxx_supportlib/{Utils → SecurityKit}/MemZeroGuard.h +0 -0
- data/src/cxx_supportlib/ServerKit/AcceptLoadBalancer.h +2 -2
- data/src/cxx_supportlib/ServerKit/Channel.h +1 -1
- data/src/cxx_supportlib/ServerKit/ClientRef.h +17 -7
- data/src/cxx_supportlib/ServerKit/Context.h +2 -2
- data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +1 -1
- data/src/cxx_supportlib/ServerKit/HttpHeaderParser.h +3 -3
- data/src/cxx_supportlib/ServerKit/HttpHeaderParserState.h +2 -2
- data/src/cxx_supportlib/ServerKit/HttpRequestRef.h +17 -7
- data/src/cxx_supportlib/ServerKit/HttpServer.h +16 -10
- data/src/cxx_supportlib/ServerKit/Server.h +3 -4
- data/src/cxx_supportlib/{Utils → StrIntTools}/DateParsing.h +5 -5
- data/src/cxx_supportlib/{Utils → StrIntTools}/StrIntUtils.cpp +3 -3
- data/src/cxx_supportlib/{Utils → StrIntTools}/StrIntUtils.h +0 -0
- data/src/cxx_supportlib/{Utils → StrIntTools}/StrIntUtilsNoStrictAliasing.cpp +12 -12
- data/src/cxx_supportlib/{Utils → StrIntTools}/StringScanning.h +5 -5
- data/src/cxx_supportlib/{Utils → StrIntTools}/Template.h +30 -5
- data/src/cxx_supportlib/SystemTools/ContainerHelpers.h +88 -0
- data/src/cxx_supportlib/{Utils → SystemTools}/ProcessMetricsCollector.h +15 -12
- data/src/cxx_supportlib/{Utils → SystemTools}/SystemMetricsCollector.h +3 -3
- data/src/cxx_supportlib/{Utils → SystemTools}/SystemTime.cpp +1 -1
- data/src/cxx_supportlib/{Utils → SystemTools}/SystemTime.h +0 -0
- data/src/cxx_supportlib/SystemTools/UserDatabase.h +1 -1
- data/src/cxx_supportlib/Utils/CachedFileStat.hpp +3 -3
- data/src/cxx_supportlib/Utils/Curl.h +2 -2
- data/src/cxx_supportlib/Utils/FileChangeChecker.h +2 -2
- data/src/cxx_supportlib/Utils/MessagePassing.h +1 -1
- data/src/cxx_supportlib/Utils/SpeedMeter.h +2 -2
- data/src/cxx_supportlib/Utils/Timer.h +2 -2
- data/src/cxx_supportlib/Utils/VariantMap.h +3 -3
- data/src/cxx_supportlib/Utils.cpp +2 -2
- data/src/cxx_supportlib/WatchdogLauncher.h +3 -3
- data/src/cxx_supportlib/WebSocketCommandReverseServer.h +1 -1
- data/src/cxx_supportlib/WrapperRegistry/CBindings.cpp +85 -0
- data/src/cxx_supportlib/{Utils/MemoryBarrier.h → WrapperRegistry/CBindings.h} +30 -27
- data/src/cxx_supportlib/WrapperRegistry/Entry.h +112 -0
- data/src/cxx_supportlib/WrapperRegistry/README.md +37 -0
- data/src/cxx_supportlib/WrapperRegistry/Registry.h +309 -0
- data/src/cxx_supportlib/vendor-modified/psg_sysqueue.h +3 -0
- data/src/helper-scripts/download_binaries/extconf.rb +6 -2
- data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +32 -0
- data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c +12 -0
- data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +36 -0
- data/src/nginx_module/Configuration.c +23 -3
- data/src/nginx_module/ContentHandler.c +331 -32
- data/src/nginx_module/ContentHandler.h +8 -3
- data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c +10 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedManifestGeneration.c +27 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c +3 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h +7 -0
- data/src/nginx_module/MainConfig/AutoGeneratedCreateFunction.c +11 -0
- data/src/nginx_module/MainConfig/AutoGeneratedManifestGeneration.c +23 -0
- data/src/nginx_module/MainConfig/AutoGeneratedStruct.h +8 -0
- data/src/nginx_module/config +2 -1
- data/src/nginx_module/ngx_http_passenger_module.c +9 -3
- data/src/nginx_module/ngx_http_passenger_module.h +10 -3
- data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +19 -0
- data/src/ruby_supportlib/phusion_passenger/common_library.rb +19 -16
- data/src/ruby_supportlib/phusion_passenger/config/agent_compiler.rb +4 -4
- data/src/ruby_supportlib/phusion_passenger/config/download_agent_command.rb +6 -2
- data/src/ruby_supportlib/phusion_passenger/config/download_nginx_engine_command.rb +6 -2
- data/src/ruby_supportlib/phusion_passenger/config/nginx_engine_compiler.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/message_channel.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/native_support.rb +7 -3
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +29 -0
- data/src/ruby_supportlib/phusion_passenger/packaging.rb +20 -19
- data/src/ruby_supportlib/phusion_passenger/platform_info/apache.rb +22 -4
- data/src/ruby_supportlib/phusion_passenger/platform_info/ruby.rb +33 -13
- data/src/ruby_supportlib/phusion_passenger/standalone/app_finder.rb +1 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +22 -2
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +4 -1
- data/src/ruby_supportlib/phusion_passenger.rb +7 -5
- data/src/schema_printer/SchemaPrinterMain.cpp +2 -0
- metadata +40 -89
- data/.editorconfig +0 -134
- data/CODE_OF_CONDUCT.md +0 -52
- data/dev/boost-patches/0001-Patch-boost-thread-so-that-oxt-thread-can-use-it.patch +0 -48
- data/dev/boost-patches/0002-Make-boost-thread_interrupted-derive-from-oxt-tracab.patch +0 -33
- data/dev/boost-patches/0003-Disable-a-Clang-pragma-to-prevent-warnings-on-OS-X.patch +0 -25
- data/dev/ci/README.md +0 -134
- data/dev/ci/lib/functions.sh +0 -129
- data/dev/ci/lib/set-container-envvars.sh +0 -53
- data/dev/ci/lib/setup-container.sh +0 -46
- data/dev/ci/run-tests-natively +0 -24
- data/dev/ci/run-tests-with-docker +0 -42
- data/dev/ci/scripts/debug-console-wrapper.sh +0 -29
- data/dev/ci/scripts/docker-entrypoint-stage2.sh +0 -17
- data/dev/ci/scripts/docker-entrypoint.sh +0 -17
- data/dev/ci/scripts/inituidgid +0 -17
- data/dev/ci/scripts/run-tests-natively-stage2.sh +0 -17
- data/dev/ci/scripts/setup-host-natively.sh +0 -11
- data/dev/ci/setup-host +0 -56
- data/dev/ci/tests/apache2/run +0 -6
- data/dev/ci/tests/apache2/setup +0 -4
- data/dev/ci/tests/binaries/Jenkinsfile +0 -105
- data/dev/ci/tests/binaries/build-linux +0 -38
- data/dev/ci/tests/binaries/build-macos +0 -40
- data/dev/ci/tests/binaries/prepare-macos +0 -38
- data/dev/ci/tests/binaries/test-linux +0 -45
- data/dev/ci/tests/binaries/test-macos +0 -38
- data/dev/ci/tests/cxx/run +0 -9
- data/dev/ci/tests/cxx/setup +0 -4
- data/dev/ci/tests/debian/Jenkinsfile +0 -89
- data/dev/ci/tests/debian/run +0 -60
- data/dev/ci/tests/nginx/run +0 -5
- data/dev/ci/tests/nginx/setup +0 -4
- data/dev/ci/tests/nginx-dynamic/run +0 -20
- data/dev/ci/tests/nginx-dynamic/setup +0 -4
- data/dev/ci/tests/nodejs/run +0 -4
- data/dev/ci/tests/nodejs/setup +0 -4
- data/dev/ci/tests/rpm/Jenkinsfile +0 -68
- data/dev/ci/tests/rpm/run +0 -63
- data/dev/ci/tests/ruby/run +0 -4
- data/dev/ci/tests/ruby/setup +0 -4
- data/dev/ci/tests/source-packaging/run +0 -4
- data/dev/ci/tests/source-packaging/setup +0 -4
- data/dev/ci/tests/standalone/run +0 -4
- data/dev/ci/tests/standalone/setup +0 -4
- data/dev/configkit-schemas/index.json +0 -1748
- data/dev/configkit-schemas/update_schema_inline_comments.rb +0 -118
- data/dev/rack.test/config.ru +0 -5
- data/dev/rack.test/public/asset.txt +0 -1
- data/dev/vagrant/apache_default_site.conf +0 -35
- data/dev/vagrant/apache_passenger.conf +0 -5
- data/dev/vagrant/apache_passenger.load +0 -1
- data/dev/vagrant/apache_ports.conf +0 -24
- data/dev/vagrant/apache_rack_test.conf +0 -9
- data/dev/vagrant/bashrc +0 -23
- data/dev/vagrant/nginx.conf +0 -39
- data/dev/vagrant/nginx_rakefile +0 -33
- data/dev/vagrant/nginx_start +0 -32
- data/dev/vagrant/provision.sh +0 -117
- data/dev/vagrant/sudoers.conf +0 -5
- data/resources/templates/error_renderer/.editorconfig +0 -19
- data/src/cxx_supportlib/AppTypes.cpp +0 -109
- data/src/cxx_supportlib/vendor-modified/SmallVector.h +0 -653
@@ -0,0 +1,681 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2018 Phusion Holding B.V.
|
4
|
+
*
|
5
|
+
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
+
* trademarks of Phusion Holding B.V.
|
7
|
+
*
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
+
* of this software and associated documentation files (the "Software"), to deal
|
10
|
+
* in the Software without restriction, including without limitation the rights
|
11
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
+
* copies of the Software, and to permit persons to whom the Software is
|
13
|
+
* furnished to do so, subject to the following conditions:
|
14
|
+
*
|
15
|
+
* The above copyright notice and this permission notice shall be included in
|
16
|
+
* all copies or substantial portions of the Software.
|
17
|
+
*
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24
|
+
* THE SOFTWARE.
|
25
|
+
*/
|
26
|
+
#ifndef _PASSENGER_TELEMETRY_COLLECTOR_H_
|
27
|
+
#define _PASSENGER_TELEMETRY_COLLECTOR_H_
|
28
|
+
|
29
|
+
#include <string>
|
30
|
+
#include <vector>
|
31
|
+
#include <limits>
|
32
|
+
#include <cstddef>
|
33
|
+
#include <cstdlib>
|
34
|
+
#include <cassert>
|
35
|
+
|
36
|
+
#include <boost/cstdint.hpp>
|
37
|
+
#include <boost/bind.hpp>
|
38
|
+
#include <oxt/thread.hpp>
|
39
|
+
#include <oxt/backtrace.hpp>
|
40
|
+
|
41
|
+
#include <curl/curl.h>
|
42
|
+
|
43
|
+
#include <Constants.h>
|
44
|
+
#include <Exceptions.h>
|
45
|
+
#include <Core/Controller.h>
|
46
|
+
#include <LoggingKit/LoggingKit.h>
|
47
|
+
#include <ConfigKit/ConfigKit.h>
|
48
|
+
#include <Utils/Curl.h>
|
49
|
+
#include <StrIntTools/StrIntUtils.h>
|
50
|
+
|
51
|
+
namespace Passenger {
|
52
|
+
namespace Core {
|
53
|
+
|
54
|
+
using namespace std;
|
55
|
+
|
56
|
+
|
57
|
+
class TelemetryCollector {
|
58
|
+
public:
|
59
|
+
/*
|
60
|
+
* BEGIN ConfigKit schema: Passenger::Core::TelemetryCollector::Schema
|
61
|
+
* (do not edit: following text is automatically generated
|
62
|
+
* by 'rake configkit_schemas_inline_comments')
|
63
|
+
*
|
64
|
+
* ca_certificate_path string - -
|
65
|
+
* debug_curl boolean - default(false)
|
66
|
+
* disabled boolean - default(false)
|
67
|
+
* final_run_timeout unsigned integer - default(5)
|
68
|
+
* first_interval unsigned integer - default(7200)
|
69
|
+
* interval unsigned integer - default(21600)
|
70
|
+
* interval_jitter unsigned integer - default(7200)
|
71
|
+
* proxy_url string - -
|
72
|
+
* timeout unsigned integer - default(180)
|
73
|
+
* url string - default("https://anontelemetry.phusionpassenger.com/v1/collect.json")
|
74
|
+
* verify_server boolean - default(true)
|
75
|
+
*
|
76
|
+
* END
|
77
|
+
*/
|
78
|
+
class Schema: public ConfigKit::Schema {
|
79
|
+
private:
|
80
|
+
static void validateProxyUrl(const ConfigKit::Store &config, vector<ConfigKit::Error> &errors) {
|
81
|
+
if (config["proxy_url"].isNull()) {
|
82
|
+
return;
|
83
|
+
}
|
84
|
+
if (config["proxy_url"].asString().empty()) {
|
85
|
+
errors.push_back(ConfigKit::Error("'{{proxy_url}}', if specified, may not be empty"));
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
|
89
|
+
try {
|
90
|
+
prepareCurlProxy(config["proxy_url"].asString());
|
91
|
+
} catch (const ArgumentException &e) {
|
92
|
+
errors.push_back(ConfigKit::Error(
|
93
|
+
P_STATIC_STRING("'{{proxy_url}}': ")
|
94
|
+
+ e.what()));
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
public:
|
99
|
+
Schema() {
|
100
|
+
using namespace ConfigKit;
|
101
|
+
|
102
|
+
add("disabled", BOOL_TYPE, OPTIONAL, false);
|
103
|
+
add("url", STRING_TYPE, OPTIONAL, "https://anontelemetry.phusionpassenger.com/v1/collect.json");
|
104
|
+
// Should be in the form: scheme://user:password@proxy_host:proxy_port
|
105
|
+
add("proxy_url", STRING_TYPE, OPTIONAL);
|
106
|
+
add("ca_certificate_path", STRING_TYPE, OPTIONAL);
|
107
|
+
add("verify_server", BOOL_TYPE, OPTIONAL, true);
|
108
|
+
add("first_interval", UINT_TYPE, OPTIONAL, 2 * 60 * 60);
|
109
|
+
add("interval", UINT_TYPE, OPTIONAL, 6 * 60 * 60);
|
110
|
+
add("interval_jitter", UINT_TYPE, OPTIONAL, 2 * 60 * 60);
|
111
|
+
add("debug_curl", BOOL_TYPE, OPTIONAL, false);
|
112
|
+
add("timeout", UINT_TYPE, OPTIONAL, 180);
|
113
|
+
add("final_run_timeout", UINT_TYPE, OPTIONAL, 5);
|
114
|
+
|
115
|
+
addValidator(validateProxyUrl);
|
116
|
+
|
117
|
+
finalize();
|
118
|
+
}
|
119
|
+
};
|
120
|
+
|
121
|
+
struct ConfigRealization {
|
122
|
+
CurlProxyInfo proxyInfo;
|
123
|
+
string url;
|
124
|
+
string caCertificatePath;
|
125
|
+
|
126
|
+
ConfigRealization(const ConfigKit::Store &config)
|
127
|
+
: proxyInfo(prepareCurlProxy(config["proxy_url"].asString())),
|
128
|
+
url(config["url"].asString()),
|
129
|
+
caCertificatePath(config["ca_certificate_path"].asString())
|
130
|
+
{ }
|
131
|
+
|
132
|
+
void swap(ConfigRealization &other) BOOST_NOEXCEPT_OR_NOTHROW {
|
133
|
+
proxyInfo.swap(other.proxyInfo);
|
134
|
+
url.swap(other.url);
|
135
|
+
caCertificatePath.swap(other.caCertificatePath);
|
136
|
+
}
|
137
|
+
};
|
138
|
+
|
139
|
+
struct ConfigChangeRequest {
|
140
|
+
boost::scoped_ptr<ConfigKit::Store> config;
|
141
|
+
boost::scoped_ptr<ConfigRealization> configRlz;
|
142
|
+
};
|
143
|
+
|
144
|
+
struct TelemetryData {
|
145
|
+
vector<boost::uint64_t> requestsHandled;
|
146
|
+
MonotonicTimeUsec timestamp;
|
147
|
+
};
|
148
|
+
|
149
|
+
private:
|
150
|
+
/*
|
151
|
+
* Since the telemetry collector runs in a separate thread,
|
152
|
+
* and the configuration can change while the collector is active,
|
153
|
+
* we make a copy of the current configuration at the beginning
|
154
|
+
* of each collection cycle.
|
155
|
+
*/
|
156
|
+
struct SessionState {
|
157
|
+
ConfigKit::Store config;
|
158
|
+
ConfigRealization configRlz;
|
159
|
+
|
160
|
+
SessionState(const ConfigKit::Store ¤tConfig,
|
161
|
+
const ConfigRealization ¤tConfigRlz)
|
162
|
+
: config(currentConfig),
|
163
|
+
configRlz(currentConfigRlz)
|
164
|
+
{ }
|
165
|
+
};
|
166
|
+
|
167
|
+
mutable boost::mutex configSyncher;
|
168
|
+
ConfigKit::Store config;
|
169
|
+
ConfigRealization configRlz;
|
170
|
+
TelemetryData lastTelemetryData;
|
171
|
+
oxt::thread *collectorThread;
|
172
|
+
|
173
|
+
void threadMain() {
|
174
|
+
TRACE_POINT();
|
175
|
+
|
176
|
+
{
|
177
|
+
// Sleep for a short while to allow interruption during the Apache integration
|
178
|
+
// double startup procedure, this prevents running the update check twice
|
179
|
+
boost::unique_lock<boost::mutex> l(configSyncher);
|
180
|
+
ConfigKit::Store config(this->config);
|
181
|
+
l.unlock();
|
182
|
+
|
183
|
+
unsigned int backoffSec = config["first_interval"].asUInt()
|
184
|
+
+ calculateIntervalJitter(config);
|
185
|
+
P_DEBUG("Next anonymous telemetry collection in " <<
|
186
|
+
distanceOfTimeInWords(SystemTime::get() + backoffSec));
|
187
|
+
boost::this_thread::sleep_for(boost::chrono::seconds(backoffSec));
|
188
|
+
}
|
189
|
+
|
190
|
+
while (!boost::this_thread::interruption_requested()) {
|
191
|
+
UPDATE_TRACE_POINT();
|
192
|
+
unsigned int backoffSec = 0;
|
193
|
+
try {
|
194
|
+
backoffSec = runOneCycle();
|
195
|
+
} catch (const oxt::tracable_exception &e) {
|
196
|
+
P_ERROR(e.what() << "\n" << e.backtrace());
|
197
|
+
}
|
198
|
+
|
199
|
+
if (backoffSec == 0) {
|
200
|
+
boost::unique_lock<boost::mutex> l(configSyncher);
|
201
|
+
backoffSec = config["interval"].asUInt()
|
202
|
+
+ calculateIntervalJitter(config);
|
203
|
+
}
|
204
|
+
|
205
|
+
UPDATE_TRACE_POINT();
|
206
|
+
P_DEBUG("Next anonymous telemetry collection in "
|
207
|
+
<< distanceOfTimeInWords(SystemTime::get() + backoffSec));
|
208
|
+
boost::this_thread::sleep_for(boost::chrono::seconds(backoffSec));
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
static unsigned int calculateIntervalJitter(const ConfigKit::Store &config) {
|
213
|
+
unsigned int jitter = config["interval_jitter"].asUInt();
|
214
|
+
if (jitter == 0) {
|
215
|
+
return 0;
|
216
|
+
} else {
|
217
|
+
return std::rand() % jitter;
|
218
|
+
}
|
219
|
+
}
|
220
|
+
|
221
|
+
// Virtual to allow mocking in unit tests.
|
222
|
+
virtual TelemetryData collectTelemetryData(bool isFinalRun) const {
|
223
|
+
TRACE_POINT();
|
224
|
+
TelemetryData tmData;
|
225
|
+
unsigned int counter = 0;
|
226
|
+
boost::mutex syncher;
|
227
|
+
boost::condition_variable cond;
|
228
|
+
|
229
|
+
tmData.requestsHandled.resize(controllers.size(), 0);
|
230
|
+
|
231
|
+
UPDATE_TRACE_POINT();
|
232
|
+
for (unsigned int i = 0; i < controllers.size(); i++) {
|
233
|
+
if (isFinalRun) {
|
234
|
+
inspectController(&tmData, controllers[i], i, &counter,
|
235
|
+
&syncher, &cond);
|
236
|
+
} else {
|
237
|
+
controllers[i]->getContext()->libev->runLater(boost::bind(
|
238
|
+
&TelemetryCollector::inspectController, this, &tmData,
|
239
|
+
controllers[i], i, &counter, &syncher, &cond));
|
240
|
+
}
|
241
|
+
}
|
242
|
+
|
243
|
+
UPDATE_TRACE_POINT();
|
244
|
+
{
|
245
|
+
boost::unique_lock<boost::mutex> l(syncher);
|
246
|
+
while (counter != controllers.size()) {
|
247
|
+
cond.wait(l);
|
248
|
+
}
|
249
|
+
}
|
250
|
+
|
251
|
+
tmData.timestamp = SystemTime::getMonotonicUsecWithGranularity
|
252
|
+
<SystemTime::GRAN_1SEC>();
|
253
|
+
return tmData;
|
254
|
+
}
|
255
|
+
|
256
|
+
void inspectController(TelemetryData *tmData, Controller *controller,
|
257
|
+
unsigned int index, unsigned int *counter, boost::mutex *syncher,
|
258
|
+
boost::condition_variable *cond) const
|
259
|
+
{
|
260
|
+
boost::unique_lock<boost::mutex> l(*syncher);
|
261
|
+
tmData->requestsHandled[index] = controller->totalRequestsBegun;
|
262
|
+
(*counter)++;
|
263
|
+
cond->notify_one();
|
264
|
+
}
|
265
|
+
|
266
|
+
string createRequestBody(const TelemetryData &tmData) const {
|
267
|
+
Json::Value doc;
|
268
|
+
boost::uint64_t totalRequestsHandled = 0;
|
269
|
+
|
270
|
+
P_ASSERT_EQ(tmData.requestsHandled.size(),
|
271
|
+
lastTelemetryData.requestsHandled.size());
|
272
|
+
|
273
|
+
for (unsigned int i = 0; i < tmData.requestsHandled.size(); i++) {
|
274
|
+
if (tmData.requestsHandled[i] >= lastTelemetryData.requestsHandled[i]) {
|
275
|
+
totalRequestsHandled += tmData.requestsHandled[i]
|
276
|
+
- lastTelemetryData.requestsHandled[i];
|
277
|
+
} else {
|
278
|
+
// Counter overflowed
|
279
|
+
totalRequestsHandled += std::numeric_limits<boost::uint64_t>::max()
|
280
|
+
- lastTelemetryData.requestsHandled[i]
|
281
|
+
+ 1
|
282
|
+
+ tmData.requestsHandled[i];
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
doc["requests_handled"] = (Json::UInt64) totalRequestsHandled;
|
287
|
+
doc["begin_time"] = (Json::UInt64) monoTimeToRealTime(
|
288
|
+
lastTelemetryData.timestamp);
|
289
|
+
doc["end_time"] = (Json::UInt64) monoTimeToRealTime(
|
290
|
+
tmData.timestamp);
|
291
|
+
doc["version"] = PASSENGER_VERSION;
|
292
|
+
#ifdef PASSENGER_IS_ENTERPRISE
|
293
|
+
doc["edition"] = "enterprise";
|
294
|
+
#else
|
295
|
+
doc["edition"] = "oss";
|
296
|
+
#endif
|
297
|
+
|
298
|
+
return doc.toStyledString();
|
299
|
+
}
|
300
|
+
|
301
|
+
static time_t monoTimeToRealTime(MonotonicTimeUsec monoTime) {
|
302
|
+
MonotonicTimeUsec monoNow = SystemTime::getMonotonicUsecWithGranularity
|
303
|
+
<SystemTime::GRAN_1SEC>();
|
304
|
+
unsigned long long realNow = SystemTime::getUsec();
|
305
|
+
MonotonicTimeUsec diff;
|
306
|
+
|
307
|
+
if (monoNow >= monoTime) {
|
308
|
+
diff = monoNow - monoTime;
|
309
|
+
return (realNow - diff) / 1000000;
|
310
|
+
} else {
|
311
|
+
diff = monoTime - monoNow;
|
312
|
+
return (realNow + diff) / 1000000;
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
static CURL *prepareCurlRequest(SessionState &sessionState, bool isFinalRun,
|
317
|
+
struct curl_slist **headers, char *lastErrorMessage,
|
318
|
+
const string &requestBody, string &responseData)
|
319
|
+
{
|
320
|
+
CURL *curl;
|
321
|
+
CURLcode code;
|
322
|
+
|
323
|
+
curl = curl_easy_init();
|
324
|
+
if (curl == NULL) {
|
325
|
+
P_ERROR("Error initializing libcurl");
|
326
|
+
return NULL;
|
327
|
+
}
|
328
|
+
|
329
|
+
code = curl_easy_setopt(curl, CURLOPT_VERBOSE,
|
330
|
+
sessionState.config["debug_curl"].asBool() ? 1L : 0L);
|
331
|
+
if (code != CURLE_OK) {
|
332
|
+
goto error;
|
333
|
+
}
|
334
|
+
|
335
|
+
code = setCurlDefaultCaInfo(curl);
|
336
|
+
if (code != CURLE_OK) {
|
337
|
+
goto error;
|
338
|
+
}
|
339
|
+
|
340
|
+
code = setCurlProxy(curl, sessionState.configRlz.proxyInfo);
|
341
|
+
if (code != CURLE_OK) {
|
342
|
+
goto error;
|
343
|
+
}
|
344
|
+
|
345
|
+
code = curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
346
|
+
if (code != CURLE_OK) {
|
347
|
+
goto error;
|
348
|
+
}
|
349
|
+
|
350
|
+
code = curl_easy_setopt(curl, CURLOPT_URL,
|
351
|
+
sessionState.configRlz.url.c_str());
|
352
|
+
if (code != CURLE_OK) {
|
353
|
+
goto error;
|
354
|
+
}
|
355
|
+
|
356
|
+
code = curl_easy_setopt(curl, CURLOPT_HTTPGET, 0);
|
357
|
+
if (code != CURLE_OK) {
|
358
|
+
goto error;
|
359
|
+
}
|
360
|
+
|
361
|
+
code = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, requestBody.c_str());
|
362
|
+
if (code != CURLE_OK) {
|
363
|
+
goto error;
|
364
|
+
}
|
365
|
+
|
366
|
+
code = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, requestBody.length());
|
367
|
+
if (code != CURLE_OK) {
|
368
|
+
goto error;
|
369
|
+
}
|
370
|
+
|
371
|
+
*headers = curl_slist_append(NULL, "Content-Type: application/json");
|
372
|
+
code = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, *headers);
|
373
|
+
if (code != CURLE_OK) {
|
374
|
+
goto error;
|
375
|
+
}
|
376
|
+
|
377
|
+
if (!sessionState.configRlz.caCertificatePath.empty()) {
|
378
|
+
code = curl_easy_setopt(curl, CURLOPT_CAINFO,
|
379
|
+
sessionState.configRlz.caCertificatePath.c_str());
|
380
|
+
if (code != CURLE_OK) {
|
381
|
+
goto error;
|
382
|
+
}
|
383
|
+
}
|
384
|
+
|
385
|
+
if (sessionState.config["verify_server"].asBool()) {
|
386
|
+
// These should be on by default, but make sure.
|
387
|
+
code = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
|
388
|
+
if (code != CURLE_OK) {
|
389
|
+
goto error;
|
390
|
+
}
|
391
|
+
code = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
|
392
|
+
if (code != CURLE_OK) {
|
393
|
+
goto error;
|
394
|
+
}
|
395
|
+
} else {
|
396
|
+
code = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
397
|
+
if (code != CURLE_OK) {
|
398
|
+
goto error;
|
399
|
+
}
|
400
|
+
code = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
401
|
+
if (code != CURLE_OK) {
|
402
|
+
goto error;
|
403
|
+
}
|
404
|
+
}
|
405
|
+
|
406
|
+
code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, lastErrorMessage);
|
407
|
+
if (code != CURLE_OK) {
|
408
|
+
goto error;
|
409
|
+
}
|
410
|
+
code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, receiveResponseBytes);
|
411
|
+
if (code != CURLE_OK) {
|
412
|
+
goto error;
|
413
|
+
}
|
414
|
+
code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);
|
415
|
+
if (code != CURLE_OK) {
|
416
|
+
goto error;
|
417
|
+
}
|
418
|
+
|
419
|
+
// setopt failure(s) below don't abort the check.
|
420
|
+
if (isFinalRun) {
|
421
|
+
curl_easy_setopt(curl, CURLOPT_TIMEOUT,
|
422
|
+
sessionState.config["final_run_timeout"].asUInt());
|
423
|
+
} else {
|
424
|
+
curl_easy_setopt(curl, CURLOPT_TIMEOUT,
|
425
|
+
sessionState.config["timeout"].asUInt());
|
426
|
+
}
|
427
|
+
|
428
|
+
return curl;
|
429
|
+
|
430
|
+
error:
|
431
|
+
curl_easy_cleanup(curl);
|
432
|
+
curl_slist_free_all(*headers);
|
433
|
+
P_ERROR("Error setting libcurl handle parameters: " << curl_easy_strerror(code));
|
434
|
+
return NULL;
|
435
|
+
}
|
436
|
+
|
437
|
+
static size_t receiveResponseBytes(void *buffer, size_t size,
|
438
|
+
size_t nmemb, void *userData)
|
439
|
+
{
|
440
|
+
string *responseData = (string *) userData;
|
441
|
+
responseData->append((const char *) buffer, size * nmemb);
|
442
|
+
return size * nmemb;
|
443
|
+
}
|
444
|
+
|
445
|
+
// Virtual to allow mocking in unit tests.
|
446
|
+
virtual CURLcode performCurlAction(CURL *curl, const char *lastErrorMessage,
|
447
|
+
const string &_requestBody, // only used by unit tests
|
448
|
+
string &_responseData, // only used by unit tests
|
449
|
+
long &responseCode)
|
450
|
+
{
|
451
|
+
TRACE_POINT();
|
452
|
+
CURLcode code = curl_easy_perform(curl);
|
453
|
+
if (code != CURLE_OK) {
|
454
|
+
P_ERROR("Error contacting anonymous telemetry server: "
|
455
|
+
<< lastErrorMessage);
|
456
|
+
return code;
|
457
|
+
}
|
458
|
+
|
459
|
+
code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
|
460
|
+
if (code != CURLE_OK) {
|
461
|
+
P_ERROR("Error querying libcurl handle for HTTP response code: "
|
462
|
+
<< curl_easy_strerror(code));
|
463
|
+
return code;
|
464
|
+
}
|
465
|
+
|
466
|
+
return CURLE_OK;
|
467
|
+
}
|
468
|
+
|
469
|
+
static bool responseCodeSupported(long code) {
|
470
|
+
return code == 200 || code == 400 || code == 422 || code == 500;
|
471
|
+
}
|
472
|
+
|
473
|
+
static bool parseResponseBody(const string &responseData, Json::Value &jsonBody) {
|
474
|
+
Json::Reader reader;
|
475
|
+
if (reader.parse(responseData, jsonBody, false)) {
|
476
|
+
return true;
|
477
|
+
} else {
|
478
|
+
P_ERROR("Error in anonymous telemetry server response:"
|
479
|
+
" JSON response parse error: " << reader.getFormattedErrorMessages()
|
480
|
+
<< "; data: \"" << cEscapeString(responseData) << "\"");
|
481
|
+
return false;
|
482
|
+
}
|
483
|
+
}
|
484
|
+
|
485
|
+
static bool validateResponseBody(const Json::Value &jsonBody) {
|
486
|
+
if (!jsonBody.isObject()) {
|
487
|
+
P_ERROR("Error in anonymous telemetry server response:"
|
488
|
+
" JSON response is not an object (data: "
|
489
|
+
<< stringifyJson(jsonBody) << ")");
|
490
|
+
return false;
|
491
|
+
}
|
492
|
+
if (!jsonBody.isMember("data_processed")) {
|
493
|
+
P_ERROR("Error in anonymous telemetry server response:"
|
494
|
+
" JSON response must contain a 'data_processed' field (data: "
|
495
|
+
<< stringifyJson(jsonBody) << ")");
|
496
|
+
return false;
|
497
|
+
}
|
498
|
+
if (!jsonBody["data_processed"].isBool()) {
|
499
|
+
P_ERROR("Error in anonymous telemetry server response:"
|
500
|
+
" 'data_processed' field must be a boolean (data: "
|
501
|
+
<< stringifyJson(jsonBody) << ")");
|
502
|
+
return false;
|
503
|
+
}
|
504
|
+
if (jsonBody.isMember("backoff") && !jsonBody["backoff"].isUInt()) {
|
505
|
+
P_ERROR("Error in anonymous telemetry server response:"
|
506
|
+
" 'backoff' field must be an unsigned integer (data: "
|
507
|
+
<< stringifyJson(jsonBody) << ")");
|
508
|
+
return false;
|
509
|
+
}
|
510
|
+
if (jsonBody.isMember("log_message") && !jsonBody["log_message"].isString()) {
|
511
|
+
P_ERROR("Error in anonymous telemetry server response:"
|
512
|
+
" 'log_message' field must be a string (data: "
|
513
|
+
<< stringifyJson(jsonBody) << ")");
|
514
|
+
return false;
|
515
|
+
}
|
516
|
+
return true;
|
517
|
+
}
|
518
|
+
|
519
|
+
unsigned int handleResponseBody(const TelemetryData &tmData,
|
520
|
+
const Json::Value &jsonBody)
|
521
|
+
{
|
522
|
+
unsigned int backoffSec = 0;
|
523
|
+
|
524
|
+
if (jsonBody["data_processed"].asBool()) {
|
525
|
+
lastTelemetryData = tmData;
|
526
|
+
}
|
527
|
+
if (jsonBody.isMember("backoff")) {
|
528
|
+
backoffSec = jsonBody["backoff"].asUInt();
|
529
|
+
}
|
530
|
+
if (jsonBody.isMember("log_message")) {
|
531
|
+
P_NOTICE("Message from " PROGRAM_AUTHOR ": " << jsonBody["log_message"].asString());
|
532
|
+
}
|
533
|
+
|
534
|
+
return backoffSec;
|
535
|
+
}
|
536
|
+
|
537
|
+
public:
|
538
|
+
// Dependencies
|
539
|
+
vector<Controller *> controllers;
|
540
|
+
|
541
|
+
TelemetryCollector(const Schema &schema,
|
542
|
+
const Json::Value &initialConfig = Json::Value(),
|
543
|
+
const ConfigKit::Translator &translator = ConfigKit::DummyTranslator())
|
544
|
+
: config(schema, initialConfig, translator),
|
545
|
+
configRlz(config),
|
546
|
+
collectorThread(NULL)
|
547
|
+
{ }
|
548
|
+
|
549
|
+
virtual ~TelemetryCollector() {
|
550
|
+
stop();
|
551
|
+
}
|
552
|
+
|
553
|
+
void initialize() {
|
554
|
+
if (controllers.empty()) {
|
555
|
+
throw RuntimeException("controllers must be initialized");
|
556
|
+
}
|
557
|
+
lastTelemetryData.requestsHandled.resize(controllers.size(), 0);
|
558
|
+
lastTelemetryData.timestamp =
|
559
|
+
SystemTime::getMonotonicUsecWithGranularity<SystemTime::GRAN_1SEC>();
|
560
|
+
}
|
561
|
+
|
562
|
+
void start() {
|
563
|
+
assert(!lastTelemetryData.requestsHandled.empty());
|
564
|
+
collectorThread = new oxt::thread(
|
565
|
+
boost::bind(&TelemetryCollector::threadMain, this),
|
566
|
+
"Telemetry collector",
|
567
|
+
1024 * 512
|
568
|
+
);
|
569
|
+
}
|
570
|
+
|
571
|
+
void stop() {
|
572
|
+
if (collectorThread != NULL) {
|
573
|
+
collectorThread->interrupt_and_join();
|
574
|
+
delete collectorThread;
|
575
|
+
collectorThread = NULL;
|
576
|
+
}
|
577
|
+
}
|
578
|
+
|
579
|
+
unsigned int runOneCycle(bool isFinalRun = false) {
|
580
|
+
TRACE_POINT();
|
581
|
+
boost::unique_lock<boost::mutex> l(configSyncher);
|
582
|
+
SessionState sessionState(config, configRlz);
|
583
|
+
l.unlock();
|
584
|
+
|
585
|
+
if (sessionState.config["disabled"].asBool()) {
|
586
|
+
P_DEBUG("Telemetry collector disabled; not sending anonymous telemetry data");
|
587
|
+
return 0;
|
588
|
+
}
|
589
|
+
|
590
|
+
UPDATE_TRACE_POINT();
|
591
|
+
TelemetryData tmData = collectTelemetryData(isFinalRun);
|
592
|
+
|
593
|
+
UPDATE_TRACE_POINT();
|
594
|
+
CURL *curl = NULL;
|
595
|
+
CURLcode code;
|
596
|
+
struct curl_slist *headers = NULL;
|
597
|
+
string requestBody = createRequestBody(tmData);
|
598
|
+
string responseData;
|
599
|
+
char lastErrorMessage[CURL_ERROR_SIZE] = "unknown error";
|
600
|
+
Json::Value jsonBody;
|
601
|
+
|
602
|
+
curl = prepareCurlRequest(sessionState, isFinalRun, &headers,
|
603
|
+
lastErrorMessage, requestBody, responseData);
|
604
|
+
if (curl == NULL) {
|
605
|
+
// Error message already printed
|
606
|
+
goto error;
|
607
|
+
}
|
608
|
+
|
609
|
+
P_INFO("Sending anonymous telemetry data to " PROGRAM_AUTHOR);
|
610
|
+
P_DEBUG("Telemetry server URL is: " << sessionState.configRlz.url);
|
611
|
+
P_DEBUG("Telemetry data to be sent is: " << requestBody);
|
612
|
+
|
613
|
+
UPDATE_TRACE_POINT();
|
614
|
+
long responseCode;
|
615
|
+
code = performCurlAction(curl, lastErrorMessage, requestBody,
|
616
|
+
responseData, responseCode);
|
617
|
+
if (code != CURLE_OK) {
|
618
|
+
// Error message already printed
|
619
|
+
goto error;
|
620
|
+
}
|
621
|
+
|
622
|
+
UPDATE_TRACE_POINT();
|
623
|
+
P_DEBUG("Response from telemetry server: status=" << responseCode
|
624
|
+
<< ", body=" << responseData);
|
625
|
+
|
626
|
+
if (!responseCodeSupported(responseCode)) {
|
627
|
+
P_ERROR("Error from anonymous telemetry server:"
|
628
|
+
" response status not supported: " << responseCode);
|
629
|
+
goto error;
|
630
|
+
}
|
631
|
+
|
632
|
+
if (!parseResponseBody(responseData, jsonBody)
|
633
|
+
|| !validateResponseBody(jsonBody))
|
634
|
+
{
|
635
|
+
// Error message already printed
|
636
|
+
goto error;
|
637
|
+
}
|
638
|
+
|
639
|
+
curl_slist_free_all(headers);
|
640
|
+
curl_easy_cleanup(curl);
|
641
|
+
|
642
|
+
return handleResponseBody(tmData, jsonBody);
|
643
|
+
|
644
|
+
error:
|
645
|
+
curl_slist_free_all(headers);
|
646
|
+
if (curl != NULL) {
|
647
|
+
curl_easy_cleanup(curl);
|
648
|
+
}
|
649
|
+
return 0;
|
650
|
+
}
|
651
|
+
|
652
|
+
bool prepareConfigChange(const Json::Value &updates,
|
653
|
+
vector<ConfigKit::Error> &errors, ConfigChangeRequest &req)
|
654
|
+
{
|
655
|
+
{
|
656
|
+
boost::lock_guard<boost::mutex> l(configSyncher);
|
657
|
+
req.config.reset(new ConfigKit::Store(config, updates, errors));
|
658
|
+
}
|
659
|
+
if (errors.empty()) {
|
660
|
+
req.configRlz.reset(new ConfigRealization(*req.config));
|
661
|
+
}
|
662
|
+
return errors.empty();
|
663
|
+
}
|
664
|
+
|
665
|
+
void commitConfigChange(ConfigChangeRequest &req) BOOST_NOEXCEPT_OR_NOTHROW {
|
666
|
+
boost::lock_guard<boost::mutex> l(configSyncher);
|
667
|
+
config.swap(*req.config);
|
668
|
+
configRlz.swap(*req.configRlz);
|
669
|
+
}
|
670
|
+
|
671
|
+
Json::Value inspectConfig() const {
|
672
|
+
boost::lock_guard<boost::mutex> l(configSyncher);
|
673
|
+
return config.inspect();
|
674
|
+
}
|
675
|
+
};
|
676
|
+
|
677
|
+
|
678
|
+
} // namespace Core
|
679
|
+
} // namespace Passenger
|
680
|
+
|
681
|
+
#endif /* _PASSENGER_TELEMETRY_COLLECTOR_H_ */
|