On Sentry.io I am seeing the following interface:

However when looking at the JSON for that event (it only has a single event) I can see the User-Agent is sent and being stored.

I would assume that would extract the browser correctly. I have a lot of other User-Agents also not being recognized, I have yet to see a correct one being recognized.
Language: PHP
(Noticed the icons are round now since I took the screenshots yesterday but that has not changed the detection)
This only happens if the contexts fields is preset as well.
If the contexts field is omitted, the browser is detected correctly (with the same User-Agent).
In the PHP SDK we sent the PHP version in the contexts.runtime is there a way to still sent the PHP version? But let Sentry decide the browser / OS?
Can also confirm I'm getting these. Disabling the 'runtime' context shows the correct operating system and OS as a tag, but not in the 'big three' of "user, browser, runtime" at the top. Disabling runtime causes this bar you've got in your first screenshot to disappear completely.
Re-enabling runtime context brings the bar back, yet the 'Browser' still shows as 'Unknown' despite displaying a valid User-Agent header.
I've managed to display OS and browser info by manually adding $data['contexts'] entries:

It is not documented, but array of data sent to Sentry should contains entries like this under context index to has browser/OS/runtime info properly displayed:
<?php
$data['contexts'] = [
'runtime' => [
'version' => '7.2.7',
'name' => 'php'
],
'os' => [
'name' => 'Linux'
],
'browser' => [
'version' => '62.0',
'name' => 'Firefox'
]
];
I've managed to achieve this by some dirty-fix. First, I am adding required data in custom processor:
class SessionRequestProcessor {
...
public function process(array $record) {
if (null !== $this->browserVersion) {
$record['contexts']['browser'] = [
'version' => $this->browserVersion,
'name' => $this->browserName,
];
$record['contexts']['os'] = ['name' => $this->osName];
}
}
...
}
then, I've modified write method in Monolog\Handler\RavenHandler (I am using Monolog approach) to add also contexts index to record:
if (!empty($record['contexts'])) {
$options['contexts'] = $record['contexts'];
}
I am going to add PR for this changes.
Yes, however I would like to not have the user or sentry-php parse the user agent string if possible. So it would be nice if there is a way we can let sentry decide about the User-Agent stuff but still keep the php version context.
馃憤 Same issue here
+1
Same here!
Faced the same problem. I followed the instructions from @mleczakm but improved the following part:
then, I've modified
writemethod inMonolog\Handler\RavenHandler(I am using Monolog approach) to add alsocontextsindex to record:if (!empty($record['contexts'])) { $options['contexts'] = $record['contexts']; }
Instead of that I used a more neat approach and created my own class that extends Monolog\Handler\RavenHandler and correctly processes the contexts field:
use Monolog\Logger;
class DFYRavenHandler extends Monolog\Handler\RavenHandler
{
/**
* Translates Monolog log levels to Raven log levels.
*/
protected $logLevels = array(
Logger::DEBUG => Raven_Client::DEBUG,
Logger::INFO => Raven_Client::INFO,
Logger::NOTICE => Raven_Client::INFO,
Logger::WARNING => Raven_Client::WARNING,
Logger::ERROR => Raven_Client::ERROR,
Logger::CRITICAL => Raven_Client::FATAL,
Logger::ALERT => Raven_Client::FATAL,
Logger::EMERGENCY => Raven_Client::FATAL,
);
/**
* {@inheritdoc}
*/
public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true)
{
parent::__construct($ravenClient, $level, $bubble);
}
/**
* {@inheritdoc}
*/
protected function write(array $record)
{
$previousUserContext = false;
$options = array();
$options['level'] = $this->logLevels[$record['level']];
$options['tags'] = array();
if (!empty($record['extra']['tags'])) {
$options['tags'] = array_merge($options['tags'], $record['extra']['tags']);
unset($record['extra']['tags']);
}
if (!empty($record['context']['tags'])) {
$options['tags'] = array_merge($options['tags'], $record['context']['tags']);
unset($record['context']['tags']);
}
if (!empty($record['context']['fingerprint'])) {
$options['fingerprint'] = $record['context']['fingerprint'];
unset($record['context']['fingerprint']);
}
if (!empty($record['context']['logger'])) {
$options['logger'] = $record['context']['logger'];
unset($record['context']['logger']);
} else {
$options['logger'] = $record['channel'];
}
foreach ($this->getExtraParameters() as $key) {
foreach (array('extra', 'context') as $source) {
if (!empty($record[$source][$key])) {
$options[$key] = $record[$source][$key];
unset($record[$source][$key]);
}
}
}
if (!empty($record['context'])) {
$options['extra']['context'] = $record['context'];
if (!empty($record['context']['user'])) {
$previousUserContext = $this->ravenClient->context->user;
$this->ravenClient->user_context($record['context']['user']);
unset($options['extra']['context']['user']);
}
}
if (!empty($record['extra'])) {
$options['extra']['extra'] = $record['extra'];
}
if (!empty($record['contexts'])) {
$options['contexts'] = $record['contexts'];
unset($record['contexts']);
}
if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
$options['extra']['message'] = $record['formatted'];
$this->ravenClient->captureException($record['context']['exception'], $options);
} else {
$this->ravenClient->captureMessage($record['formatted'], array(), $options);
}
if ($previousUserContext !== false) {
$this->ravenClient->user_context($previousUserContext);
}
}
}
I see the PR that @mleczakm created, but then he closed it himself. It's a pity. It could be a good contribution for all users!
fyi @HazAT is working on this.
Most helpful comment
Yes, however I would like to not have the user or sentry-php parse the user agent string if possible. So it would be nice if there is a way we can let sentry decide about the User-Agent stuff but still keep the php version context.