99use Sentry \Agent \EnvelopeQueue ;
1010use Sentry \Agent \Server ;
1111
12- // @TODO: Improve the help output to be a little more useful and explain the different options
13- if (($ argv [1 ] ?? '' ) === 'help ' || ($ argv [1 ] ?? '' ) === '--help ' || ($ argv [1 ] ?? '' ) === '-h ' ) {
14- echo 'Usage: ./sentry-agent [listen_address] [listen_port] [upstream_timeout] [upstream_concurrency] [queue_limit] ' . \PHP_EOL ;
15- exit ;
16- }
12+ $ vendorPath = __DIR__ . '/../vendor ' ;
1713
1814if (class_exists ('Phar ' ) && Phar::running (false ) !== '' ) {
1915 // If running the .phar directly from ./vendor/bin/, we don't want to use $_composer_autoload_path since this
2016 // will load the projects files and lead to ClassNotFound errors.
2117 // We want to use the autoload.php from the phar itself.
22- require __DIR__ . ' /../vendor/ autoload.php' ;
18+ require_once "{ $ vendorPath } / autoload.php" ;
2319} else {
2420 // This works fine for local development or if running the phar from ./vendor/sentry/sentry-agent/bin/
25- require $ _composer_autoload_path ?? __DIR__ . '/../vendor/autoload.php ' ;
21+ require_once $ _composer_autoload_path ?? "{$ vendorPath }/autoload.php " ;
22+ }
23+
24+ $ sentryAgentVersion = '0.0.0 ' ;
25+
26+ if (file_exists ("{$ vendorPath }/composer/installed.php " )) {
27+ $ installed = require "{$ vendorPath }/composer/installed.php " ;
28+
29+ $ sentryAgentVersion = $ installed ['root ' ]['pretty_version ' ] ?? $ sentryAgentVersion ;
30+ }
31+
32+ function printHelp (): void
33+ {
34+ global $ sentryAgentVersion ;
35+
36+ echo <<<HELP
37+ Sentry Agent {$ sentryAgentVersion }
38+
39+ Description:
40+ A local agent that listens for Sentry SDK requests and forwards them to the destined Sentry server.
41+
42+ Usage:
43+ ./sentry-agent [options]
44+
45+ Options:
46+ -h, --help Display this help output
47+ --listen=ADDRESS The address the agent listens for connections on [default: "127.0.0.1:5148"]
48+ --upstream-timeout=SECONDS The timeout for the connection to Sentry (in seconds) [default: "2.0"]
49+ --upstream-concurrency=REQUESTS Configures the amount of concurrent requests the agent is allowed to make towards Sentry [default: "10"]
50+ --queue-limit=ENVELOPES How many envelopes we want to keep in memory before we start dropping them [default: "1000"]
51+ -v, --verbose When supplied the agent will print debug messages to the console, otherwise only errors and info messages are printed
52+
53+ HELP ;
54+ }
55+
56+ $ options = getopt ('h ' , ['listen:: ' , 'upstream-timeout:: ' , 'upstream-concurrency:: ' , 'queue-limit:: ' , 'help ' ]);
57+
58+ if ($ options === false ) {
59+ Log::error ('Failed to parse command line options. ' );
60+
61+ exit (1 );
62+ }
63+
64+ $ getOption = static function (string $ key , $ default = null ) use ($ options ) {
65+ if (!isset ($ options [$ key ])) {
66+ return $ default ;
67+ }
68+
69+ // If the option is provided multiple times, we take the first value.
70+ $ value = is_array ($ options [$ key ])
71+ ? $ options [$ key ][0 ]
72+ : $ options [$ key ];
73+
74+ // Options without a value are returned as false by getopt. We treat them as boolean flags and return true instead.
75+ return $ value === false
76+ ? true
77+ : $ value ;
78+ };
79+
80+ $ firstArgument = $ argv [1 ] ?? '- ' ;
81+
82+ if ($ firstArgument === 'help ' || $ firstArgument [0 ] !== '- ' || $ getOption ('h ' ) || $ getOption ('help ' )) {
83+ printHelp ();
84+
85+ // Showed help, exit.
86+ exit (0 );
87+ }
88+
89+ Log::setVerbose ($ getOption ('v ' ) || $ getOption ('verbose ' ));
90+
91+ $ listenAddress = $ getOption ('listen ' , '127.0.0.1:5148 ' );
92+
93+ $ upstreamTimeout = (float ) $ getOption ('upstream-timeout ' , 2.0 );
94+
95+ if ($ upstreamTimeout <= 0 ) {
96+ Log::error ('The upstream timeout must be a positive number. ' );
97+
98+ exit (1 );
99+ }
100+
101+ $ upstreamConcurrency = (int ) $ getOption ('upstream-concurrency ' , 10 );
102+
103+ if ($ upstreamConcurrency <= 0 ) {
104+ Log::error ('The upstream concurrency must be a positive integer. ' );
105+
106+ exit (1 );
26107}
27108
28- // @TODO: "sentryagent" with a 5 in front, it's a unused "user port": https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=5148
29- // Maybe there is a better way to select a port to use but for now this is fine.
30- $ listenAddress = ($ argv [1 ] ?? '127.0.0.1 ' ) . ': ' . ($ argv [2 ] ?? 5148 );
109+ $ queueLimit = (int ) $ getOption ('queue-limit ' , 1000 );
110+
111+ if ($ queueLimit <= 0 ) {
112+ Log::error ('The queue limit must be a positive integer and at least 1. ' );
31113
32- // Configures the timeout for the connection to Sentry (in seconds), since we are running in an agent
33- // we can afford a little longer timeout then we would normally do in a regular PHP context
34- $ upstreamTimeout = (float ) ($ argv [3 ] ?? 2.0 );
114+ exit (1 );
115+ }
35116
36- // Configures the amount of concurrent requests the agent is allowed to make towards Sentry
37- $ upstreamConcurrency = ( int ) ( $ argv [ 4 ] ?? 10 );
117+ if ( $ queueLimit < $ upstreamConcurrency ) {
118+ Log:: error ( ' The queue limit must be at least equal to the upstream concurrency. ' );
38119
39- // How many envelopes we want to keep in memory before we start dropping them
40- $ queueLimit = ( int ) ( $ argv [ 5 ] ?? 1000 );
120+ exit ( 1 );
121+ }
41122
42- Log::info ("=> Starting Sentry agent, listening on {$ listenAddress } with config: " );
43- Log::info (" > upstream timeout: {$ upstreamTimeout }" );
44- Log::info (" > upstream concurrency: {$ upstreamConcurrency }" );
45- Log::info (" > queue limit: {$ queueLimit }" );
123+ Log::info ("Starting Sentry Agent ( {$ sentryAgentVersion }), listening on {$ listenAddress } (timeout: {$ upstreamTimeout }, concurrency: {$ upstreamConcurrency }, queue: {$ queueLimit }) " );
46124
47125$ forwarder = new EnvelopeForwarder (
48126 $ upstreamTimeout ,
@@ -57,9 +135,9 @@ function (Psr\Http\Message\ResponseInterface $response) {
57135 $ eventId = '<unknown> ' ;
58136 }
59137
60- Log::info ("Envelope sent successfully (ID: {$ eventId }, http status: {$ response ->getStatusCode ()}). " );
138+ Log::debug ("Envelope sent successfully (ID: {$ eventId }, http status: {$ response ->getStatusCode ()}). " );
61139 } else {
62- Log::info ("Envelope sent successfully (http status: {$ response ->getStatusCode ()}). " );
140+ Log::debug ("Envelope sent successfully (http status: {$ response ->getStatusCode ()}). " );
63141 }
64142 } else {
65143 Log::error ("Envelope send error: {$ response ->getStatusCode ()} {$ response ->getReasonPhrase ()}" );
@@ -97,7 +175,7 @@ function (Throwable $exception) {
97175 Log::error ("Incoming connection error: {$ exception ->getMessage ()}" );
98176 },
99177 function (Envelope $ envelope ) use ($ queue ) {
100- Log::info ('Envelope received, queueing forward to Sentry... ' );
178+ Log::debug ('Envelope received, queueing forward to Sentry... ' );
101179
102180 $ queue ->enqueue ($ envelope );
103181 }
0 commit comments