Skip to content

Commit 95c1ab2

Browse files
HazATstayallive
andauthored
feat: 2.x (#373)
* feat: Add Tracing (#358) * feat: Add Tracing Middleware Record sql queries as spans * feat: Auto prepend middleware Instrument view renders * ref: Change code comments * ref: Use terminate to send transaction * Rename view engine decorator * Improve transaction context name/description * Prevent crashes when using missing defines * Do not remove all leading `/` keep 1 * Add fallback autoload + bootstrap span * Set the transaction name from the event handler * Cleanup query span * Prevent errors on Laravel 5.3 and below * CS * feat: Use correct route and add data * ref: Add name * fix: Route naming * feat: Start transaction in serviceProvider Move all renders as a child * ref: Rename to view.render * ref: Move back to starting transaction in middleware Use fromTraceparent function to start a trace * ref: Small refactor * feat: Update composer.json * ref: Add traces_sample_rate * Refactor active span retrieval * Guard against the active span not being set * Docblock updates * Correctly return rendered view without span * Move tracing related code to the Tracing namespace * Improve the route name detection order * Do not use route names ending with a `.` * Fix not wrapping the view enines when resolver is already resolved * feat: Rework code to use transaction on the hub Co-authored-by: Alex Bouma <[email protected]> * meta: Bump version 2.0.0-beta.0 * meta: Change version 2.0.0-beta1 * meta: Define beta version 3.0.0-beta1 for php sdk * meta: Changelog * Update CHANGELOG.md Co-authored-by: Alex Bouma <[email protected]> * feat: Add publish command (#379) * feat: Add publish command * fix: Typos * feat: Counterpart to PHP polish apm pr (#384) * meta: Prepare 2.x * fix: Travis * ref: Fix tests * fix: tests * ref: Master Co-authored-by: Alex Bouma <[email protected]>
1 parent b20fac1 commit 95c1ab2

16 files changed

+515
-91
lines changed

.travis.yml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,32 @@ php:
88
env:
99
matrix:
1010
# All versions below should be test on PHP ^7.1 (Sentry SDK requrement)
11-
- LARAVEL=5.1.* TESTBENCH=3.1.* PHPUNIT=5.7.* SENTRY=^2.3
12-
- LARAVEL=5.2.* TESTBENCH=3.2.* PHPUNIT=5.7.* SENTRY=^2.3
13-
- LARAVEL=5.3.* TESTBENCH=3.3.* PHPUNIT=5.7.* SENTRY=^2.3
14-
- LARAVEL=5.4.* TESTBENCH=3.4.* PHPUNIT=5.7.* SENTRY=^2.3
15-
- LARAVEL=5.5.* TESTBENCH=3.5.* PHPUNIT=6.5.* SENTRY=^2.3
16-
- LARAVEL=5.6.* TESTBENCH=3.6.* PHPUNIT=7.5.* SENTRY=^2.3
17-
- LARAVEL=5.7.* TESTBENCH=3.7.* PHPUNIT=7.5.* SENTRY=^2.3
18-
- LARAVEL=5.8.* TESTBENCH=3.8.* PHPUNIT=7.5.* SENTRY=^2.3
11+
- LARAVEL=5.1.* TESTBENCH=3.1.* PHPUNIT=5.7.* SENTRY=^3.0
12+
- LARAVEL=5.2.* TESTBENCH=3.2.* PHPUNIT=5.7.* SENTRY=^3.0
13+
- LARAVEL=5.3.* TESTBENCH=3.3.* PHPUNIT=5.7.* SENTRY=^3.0
14+
- LARAVEL=5.4.* TESTBENCH=3.4.* PHPUNIT=5.7.* SENTRY=^3.0
15+
- LARAVEL=5.5.* TESTBENCH=3.5.* PHPUNIT=6.5.* SENTRY=^3.0
16+
- LARAVEL=5.6.* TESTBENCH=3.6.* PHPUNIT=7.5.* SENTRY=^3.0
17+
- LARAVEL=5.7.* TESTBENCH=3.7.* PHPUNIT=7.5.* SENTRY=^3.0
18+
- LARAVEL=5.8.* TESTBENCH=3.8.* PHPUNIT=7.5.* SENTRY=^3.0
1919

2020
# All versions below only support PHP ^7.2 (Laravel requirement)
21-
- LARAVEL=^6.0 TESTBENCH=4.7.* PHPUNIT=8.4.* SENTRY=^2.3
22-
- LARAVEL=^7.0 TESTBENCH=5.1.* PHPUNIT=8.4.* SENTRY=^2.3
21+
- LARAVEL=^6.0 TESTBENCH=4.7.* PHPUNIT=8.4.* SENTRY=^3.0
22+
- LARAVEL=^7.0 TESTBENCH=5.1.* PHPUNIT=8.4.* SENTRY=^3.0
2323

2424
# We add one more test using the next version of Laravel which only support PHP ^7.3 (Laravel requirement)
25-
- LARAVEL=8.x-dev@dev TESTBENCH=^6.0 PHPUNIT=8.4.* SENTRY=^2.3 COMPOSER_STABILITY=dev
25+
- LARAVEL=8.x-dev@dev TESTBENCH=^6.0 PHPUNIT=8.4.* SENTRY=^3.0 COMPOSER_STABILITY=dev
2626

2727
matrix:
2828
fast_finish: true
2929
allow_failures:
3030
- php: 7.3
31-
env: LARAVEL=8.x-dev@dev TESTBENCH=^6.0 PHPUNIT=8.4.* SENTRY=^2.3 COMPOSER_STABILITY=dev
31+
env: LARAVEL=8.x-dev@dev TESTBENCH=^6.0 PHPUNIT=8.4.* SENTRY=^3.0 COMPOSER_STABILITY=dev
3232
- php: 7.4
33-
env: LARAVEL=8.x-dev@dev TESTBENCH=^6.0 PHPUNIT=8.4.* SENTRY=^2.3 COMPOSER_STABILITY=dev
33+
env: LARAVEL=8.x-dev@dev TESTBENCH=^6.0 PHPUNIT=8.4.* SENTRY=^3.0 COMPOSER_STABILITY=dev
3434
exclude:
3535
- php: 7.2
36-
env: LARAVEL=8.x-dev@dev TESTBENCH=^6.0 PHPUNIT=8.4.* SENTRY=^2.3 COMPOSER_STABILITY=dev
36+
env: LARAVEL=8.x-dev@dev TESTBENCH=^6.0 PHPUNIT=8.4.* SENTRY=^3.0 COMPOSER_STABILITY=dev
3737

3838
cache:
3939
directories:

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,29 @@
22

33
## Unreleased
44

5+
## 2.0.0
6+
7+
**Breaking Change**: This version uses the [envelope endpoint](https://develop.sentry.dev/sdk/envelopes/). If you are
8+
using an on-premise installation it requires Sentry version `>= v20.6.0` to work. If you are using
9+
[sentry.io](https://sentry.io) nothing will change and no action is needed.
10+
11+
**Tracing API / Monitor Performance**
12+
13+
In this version we released API for Tracing. `\Sentry\startTransaction` is your entry point for manual instrumentation.
14+
More information can be found in our [Performance](https://docs.sentry.io/platforms/php/guides/laravel/performance/) docs.
15+
16+
- Using `^3.0` of Sentry PHP SDK
17+
- Add support for Tracing, enable it by setting `traces_sample_rate` in the config to a value > 0 (the value should be larger than `0.0` and smaller or equal than `1.0` (to send everything))
18+
19+
## 2.0.0-beta1
20+
21+
**Breaking Change**: This version uses the [envelope endpoint](https://develop.sentry.dev/sdk/envelopes/). If you are
22+
using an on-premise installation it requires Sentry version `>= v20.6.0` to work. If you are using
23+
[sentry.io](https://sentry.io) nothing will change and no action is needed.
24+
25+
- Using `3.0.0-beta1` of Sentry PHP SDK
26+
- Add support for Tracing, enable it by setting `traces_sample_rate` in the config to a value > 0 (the value should be larger than `0.0` and smaller or equal than `1.0` (to send everything))
27+
528
## 1.9.0
629

730
- Respect the `SENTRY_ENVIRONMENT` environment variable to override the Laravel environment (#354)

composer.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
}
2222
],
2323
"require": {
24-
"php": "^7.1",
24+
"php": "^7.2",
2525
"illuminate/support": "5.0 - 5.8 | ^6.0 | ^7.0 | ^8.0",
26-
"sentry/sdk": "^2.1"
26+
"sentry/sdk": "^3.0"
2727
},
2828
"require-dev": {
2929
"phpunit/phpunit": "^8.0",
@@ -57,12 +57,13 @@
5757
},
5858
"extra": {
5959
"branch-alias": {
60-
"dev-master": "1.x-dev",
60+
"dev-master": "2.x-dev",
6161
"dev-0.x": "0.x-dev"
6262
},
6363
"laravel": {
6464
"providers": [
65-
"Sentry\\Laravel\\ServiceProvider"
65+
"Sentry\\Laravel\\ServiceProvider",
66+
"Sentry\\Laravel\\Tracing\\ServiceProvider"
6667
],
6768
"aliases": {
6869
"Sentry": "Sentry\\Laravel\\Facade"

config/sentry.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@
3030
// @see: https://docs.sentry.io/error-reporting/configuration/?platform=php#send-default-pii
3131
'send_default_pii' => false,
3232

33+
'traces_sample_rate' => \floatval(env('SENTRY_TRACES_SAMPLE_RATE', 0.0)),
3334
];

src/Sentry/Laravel/EventHandler.php

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616
use Illuminate\Queue\QueueManager;
1717
use Illuminate\Routing\Events\RouteMatched;
1818
use Illuminate\Routing\Route;
19-
use Illuminate\Support\Str;
2019
use RuntimeException;
2120
use Sentry\Breadcrumb;
2221
use Sentry\SentrySdk;
2322
use Sentry\State\Scope;
23+
use Sentry\Tracing\SpanContext;
24+
use Sentry\Tracing\Transaction;
2425

2526
class EventHandler
2627
{
@@ -194,26 +195,16 @@ public function __call($method, $arguments)
194195
*/
195196
protected function routerMatchedHandler(Route $route)
196197
{
197-
$routeName = null;
198+
$routeName = Integration::extractNameForRoute($route) ?? '<unlabeled transaction>';
198199

199-
if ($route->getName()) {
200-
// someaction (route name/alias)
201-
$routeName = $route->getName();
200+
$transaction = SentrySdk::getCurrentHub()->getTransaction();
202201

203-
// Laravel 7 route caching generates a route names if the user didn't specify one
204-
// theirselfs to optimize route matching. These route names are useless to the
205-
// developer so if we encounter a generated route name we discard the value
206-
if (Str::startsWith($routeName, 'generated::')) {
207-
$routeName = null;
208-
}
209-
}
210-
211-
if (empty($routeName) && $route->getActionName()) {
212-
// SomeController@someAction (controller action)
213-
$routeName = $route->getActionName();
214-
} elseif (empty($routeName) || $routeName === 'Closure') {
215-
// /someaction // Fallback to the url
216-
$routeName = $route->uri();
202+
if ($transaction instanceof Transaction) {
203+
$transaction->setName($routeName);
204+
$transaction->setData([
205+
'action' => $route->getActionName(),
206+
'name' => $route->getName()
207+
]);
217208
}
218209

219210
Integration::addBreadcrumb(new Breadcrumb(
@@ -287,6 +278,16 @@ private function addQueryBreadcrumb($query, $bindings, $time, $connectionName)
287278
$data['bindings'] = $bindings;
288279
}
289280

281+
$transaction = SentrySdk::getCurrentHub()->getTransaction();
282+
if (null !== $transaction) {
283+
$context = new SpanContext();
284+
$context->setOp('sql.query');
285+
$context->setDescription($query);
286+
$context->setStartTimestamp(microtime(true) - $time / 1000);
287+
$context->setEndTimestamp($context->getStartTimestamp() + $time / 1000);
288+
$transaction->startChild($context);
289+
}
290+
290291
Integration::addBreadcrumb(new Breadcrumb(
291292
Breadcrumb::LEVEL_INFO,
292293
Breadcrumb::TYPE_DEFAULT,

src/Sentry/Laravel/Integration.php

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
namespace Sentry\Laravel;
44

5+
use Illuminate\Routing\Route;
6+
use Illuminate\Support\Str;
57
use Sentry\FlushableClientInterface;
68
use Sentry\SentrySdk;
9+
use Sentry\Tracing\Span;
710
use function Sentry\addBreadcrumb;
811
use function Sentry\configureScope;
912
use Sentry\Breadcrumb;
@@ -30,7 +33,9 @@ public function setupOnce(): void
3033
return $event;
3134
}
3235

33-
$event->setTransaction($self->getTransaction());
36+
if (null === $event->getTransaction()) {
37+
$event->setTransaction($self->getTransaction());
38+
}
3439

3540
return $event;
3641
});
@@ -71,7 +76,7 @@ public static function configureScope(callable $callback): void
7176
/**
7277
* @return null|string
7378
*/
74-
public static function getTransaction()
79+
public static function getTransaction(): ?string
7580
{
7681
return self::$transaction;
7782
}
@@ -98,4 +103,78 @@ public static function flushEvents(): void
98103
$client->flush();
99104
}
100105
}
106+
107+
/**
108+
* Extract the readable name for a route.
109+
*
110+
* @param \Illuminate\Routing\Route $route
111+
*
112+
* @return string|null
113+
*/
114+
public static function extractNameForRoute(Route $route): ?string
115+
{
116+
$routeName = null;
117+
118+
if (empty($routeName) && $route->getName()) {
119+
// someaction (route name/alias)
120+
$routeName = $route->getName();
121+
122+
// Laravel 7 route caching generates a route names if the user didn't specify one
123+
// theirselfs to optimize route matching. These route names are useless to the
124+
// developer so if we encounter a generated route name we discard the value
125+
if (Str::startsWith($routeName, 'generated::')) {
126+
$routeName = null;
127+
}
128+
129+
// If the route name ends with a `.` we assume an incomplete group name prefix
130+
// we discard this value since it will most likely not mean anything to the
131+
// developer and will be duplicated by other unnamed routes in the group
132+
if (Str::endsWith($routeName, '.')) {
133+
$routeName = null;
134+
}
135+
}
136+
137+
if (empty($routeName) && $route->getActionName()) {
138+
// SomeController@someAction (controller action)
139+
$routeName = ltrim($route->getActionName(), '\\');
140+
}
141+
142+
if (empty($routeName) || $routeName === 'Closure') {
143+
// /someaction // Fallback to the url
144+
$routeName = '/' . ltrim($route->uri(), '/');
145+
}
146+
147+
return $routeName;
148+
}
149+
150+
/**
151+
* Retrieve the meta tags with tracing information to link this request to front-end requests.
152+
*
153+
* @return string
154+
*/
155+
public static function sentryTracingMeta(): string
156+
{
157+
$span = self::currentTracingSpan();
158+
159+
if ($span === null) {
160+
return '';
161+
}
162+
163+
$content = sprintf('<meta name="sentry-trace" content="%s"/>', $span->toTraceparent());
164+
// $content .= sprintf('<meta name="sentry-trace-data" content="%s"/>', $span->getDescription());
165+
166+
return $content;
167+
}
168+
169+
/**
170+
* Get the current active tracing span from the scope.
171+
*
172+
* @return \Sentry\Tracing\Span|null
173+
*
174+
* @internal This is used internally as an easy way to retrieve the current active tracing span.
175+
*/
176+
public static function currentTracingSpan(): ?Span
177+
{
178+
return SentrySdk::getCurrentHub()->getSpan();
179+
}
101180
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
namespace Sentry\Laravel;
4+
5+
use Illuminate\Console\Command;
6+
7+
class PublishConfigCommand extends Command
8+
{
9+
/**
10+
* Laravel 5.0.x: The name and signature of the console command.
11+
*
12+
* @var string
13+
*/
14+
protected $name = 'sentry:publish';
15+
16+
/**
17+
* The name and signature of the console command.
18+
*
19+
* @var string
20+
*/
21+
protected $signature = 'sentry:publish';
22+
23+
/**
24+
* The console command description.
25+
*
26+
* @var string
27+
*/
28+
protected $description = 'Publishes the Sentry Config';
29+
30+
/**
31+
* Execute the console command.
32+
*
33+
* @return mixed
34+
*/
35+
public function handle()
36+
{
37+
$this->info('[Sentry] Publishing config ...');
38+
$this->call('vendor:publish', [
39+
'--provider' => 'Sentry\Laravel\ServiceProvider'
40+
]);
41+
42+
if ($this->confirm('Enable Performance Monitoring?', true)) {
43+
$this->setEnvironmentValue(['SENTRY_TRACES_SAMPLE_RATE' => 1.0]);
44+
45+
$this->info('[Sentry] Added `SENTRY_TRACES_SAMPLE_RATE=1` to your .env file.');
46+
47+
$testCommandPrompt = 'Want to send a test Event & Transaction?';
48+
$args = ['--transaction' => true];
49+
} else {
50+
$testCommandPrompt = 'Want to send a test Event?';
51+
$args = [];
52+
}
53+
54+
if ($this->confirm($testCommandPrompt, true)) {
55+
$this->call('sentry:test', $args);
56+
}
57+
}
58+
59+
public function setEnvironmentValue(array $values)
60+
{
61+
$envFile = app()->environmentFilePath();
62+
$str = file_get_contents($envFile);
63+
64+
if (count($values) > 0) {
65+
foreach ($values as $envKey => $envValue) {
66+
67+
$str .= "\n"; // In case the searched variable is in the last line without \n
68+
$keyPosition = strpos($str, "{$envKey}=");
69+
$endOfLinePosition = strpos($str, "\n", $keyPosition);
70+
$oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition);
71+
72+
// If key does not exist, add it
73+
if (!$keyPosition || !$endOfLinePosition || !$oldLine) {
74+
$str .= "{$envKey}={$envValue}\n";
75+
} else {
76+
$str = str_replace($oldLine, "{$envKey}={$envValue}", $str);
77+
}
78+
79+
}
80+
}
81+
82+
$str = substr($str, 0, -1);
83+
if (!file_put_contents($envFile, $str)) return false;
84+
return true;
85+
}
86+
}

src/Sentry/Laravel/ServiceProvider.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Sentry\Laravel;
44

5+
use Illuminate\Contracts\Http\Kernel as HttpKernelInterface;
56
use Sentry\SentrySdk;
67
use Sentry\State\Hub;
78
use Sentry\ClientBuilder;
@@ -12,6 +13,7 @@
1213
use Sentry\Integration as SdkIntegration;
1314
use Illuminate\Foundation\Application as Laravel;
1415
use Illuminate\Support\ServiceProvider as IlluminateServiceProvider;
16+
use Illuminate\Support\Facades\Storage;
1517

1618
class ServiceProvider extends IlluminateServiceProvider
1719
{
@@ -91,6 +93,7 @@ protected function registerArtisanCommands(): void
9193
{
9294
$this->commands([
9395
TestCommand::class,
96+
PublishConfigCommand::class,
9497
]);
9598
}
9699

0 commit comments

Comments
 (0)