Skip to content

Commit 6a34579

Browse files
committed
initial commit
1 parent a785ccd commit 6a34579

8 files changed

Lines changed: 331 additions & 0 deletions

File tree

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
*.lock
2+
package.xml
3+
/vendor
4+
.idea
5+
.php_cs.cache
6+
docs/_build
7+
.phpunit.result.cache

composer.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "mamikos/tikus",
3+
"description": "An abstract layer for remote error reporting",
4+
"keywords": ["mamikos", "tikus"],
5+
"license": "MIT",
6+
"type": "project",
7+
"require": {
8+
"php": "^7.4",
9+
"bugsnag/bugsnag-laravel": "^2.0",
10+
"sentry/sentry-laravel": "^2.12"
11+
},
12+
"require-dev": {
13+
"phpunit/phpunit": "^8.5",
14+
"mockery/mockery": "^1.5"
15+
},
16+
"autoload": {
17+
"psr-4": {
18+
"Mamikos\\Tikus\\": "src/"
19+
}
20+
},
21+
"autoload-dev": {
22+
"psr-4": {
23+
"Tests\\": "tests/"
24+
}
25+
},
26+
"config": {
27+
"optimize-autoloader": true,
28+
"sort-packages": true
29+
}
30+
}

phpunit.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit backupGlobals="false"
3+
backupStaticAttributes="false"
4+
bootstrap="vendor/autoload.php"
5+
colors="true"
6+
convertErrorsToExceptions="true"
7+
convertNoticesToExceptions="true"
8+
convertWarningsToExceptions="true"
9+
processIsolation="true"
10+
stopOnError="false"
11+
stopOnFailure="false"
12+
verbose="true"
13+
>
14+
<testsuites>
15+
<testsuite name="Test Suite">
16+
<directory>./tests/</directory>
17+
</testsuite>
18+
</testsuites>
19+
<filter>
20+
<whitelist>
21+
<directory>./src</directory>
22+
</whitelist>
23+
</filter>
24+
</phpunit>

src/Facades/TikusFacade.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Mamikos\Tikus\Facades;
4+
5+
use Illuminate\Support\Facades\Facade;
6+
7+
class TikusFacade extends Facade
8+
{
9+
protected static function getFacadeAccessor()
10+
{
11+
return 'tikus';
12+
}
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Mamikos\Tikus\Providers;
4+
5+
use Mamikos\Tikus\Tikus;
6+
use Illuminate\Support\ServiceProvider;
7+
8+
class TikusServiceProvider extends ServiceProvider
9+
{
10+
public function register()
11+
{
12+
$this->app->singleton('tikus', function () {
13+
return app()->make(Tikus::class);
14+
});
15+
}
16+
}

src/Tikus.php

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
3+
namespace Mamikos\Tikus;
4+
5+
use Throwable;
6+
use Exception;
7+
use Bugsnag\BugsnagLaravel\Facades\Bugsnag;
8+
use Sentry\Laravel\Facade as Sentry;
9+
10+
class Tikus
11+
{
12+
public function reportException(Throwable $throwable, Array $metadata = [])
13+
{
14+
try {
15+
if (empty($metadata) === false)
16+
{
17+
Sentry::configureScope(function ($scope) use ($metadata) {
18+
try {
19+
$scope->setContext('metadata', $metadata);
20+
}
21+
catch (Exception $e)
22+
{
23+
$scope->setContext('metadata', [
24+
'error in set metadata' => $e->getMessage()
25+
]);
26+
}
27+
});
28+
}
29+
30+
Sentry::captureException($throwable);
31+
}
32+
catch (Exception $e) {}
33+
34+
try {
35+
// Bugsnag
36+
if (empty($metadata) === true)
37+
{
38+
Bugsnag::notifyException($throwable);
39+
}
40+
else
41+
{
42+
Bugsnag::notifyException($throwable, function ($report) use ($metadata) {
43+
try {
44+
$report->setMetaData($metadata);
45+
}
46+
catch (Exception $e)
47+
{
48+
$report->setMetaData([
49+
'error in set metadata' => $e->getMessage()
50+
]);
51+
}
52+
});
53+
}
54+
}
55+
catch (Exception $e) {}
56+
}
57+
58+
public function reportError($name, $message, Array $metadata = [])
59+
{
60+
try {
61+
// Sentry
62+
if (empty($metadata) === false)
63+
{
64+
Sentry::configureScope(function ($scope) use ($metadata) {
65+
try {
66+
$scope->setContext('metadata', $metadata);
67+
}
68+
catch (Exception $e)
69+
{
70+
$scope->setContext('metadata', [
71+
'error in set metadata' => $e->getMessage()
72+
]);
73+
}
74+
});
75+
}
76+
Sentry::captureMessage("[{$name}] {$message}");
77+
}
78+
catch (Exception $e) {}
79+
80+
try {
81+
// Bugsnag
82+
if (empty($metadata) === true)
83+
{
84+
Bugsnag::notifyError($name, $message);
85+
}
86+
else
87+
{
88+
Bugsnag::notifyError($name, $message, function ($report) use ($metadata) {
89+
try {
90+
$report->setMetaData($metadata);
91+
}
92+
catch (Exception $e)
93+
{
94+
$report->setMetaData([
95+
'error in set metadata' => $e->getMessage()
96+
]);
97+
}
98+
});
99+
}
100+
}
101+
catch (Exception $e) {}
102+
}
103+
}

tests/TestCase.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Tests;
4+
5+
class TestCase extends \PHPUnit\Framework\TestCase
6+
{
7+
public function getNonPublicMethodFromClass($className, $classMethod)
8+
{
9+
$reflector = new \ReflectionClass($className);
10+
11+
$dummyMethod = $reflector->getMethod($classMethod);
12+
$dummyMethod->setAccessible(true);
13+
14+
return $dummyMethod;
15+
}
16+
17+
/**
18+
* Call a non public method $classMethod from $className with $args and return the result.
19+
*
20+
* @param object $class/Name of class which owned the method
21+
* @param string $classMethod Name of the method in the class
22+
* @param array $args Arguments to pass to method
23+
*
24+
* @return mixed
25+
*/
26+
public function callNonPublicMethod($class, string $classMethod, array $args)
27+
{
28+
$method = $this->getNonPublicMethodFromClass($class, $classMethod);
29+
30+
$object = !is_object($class) ? $this->app->make($class) : $class;
31+
32+
return $method->invokeArgs($object, $args);
33+
}
34+
35+
/**
36+
* Call a static non public method $classMethod from $className with $args and return the result.
37+
*
38+
* @param string $className Name of the class the method belongs to
39+
* @param string $classMethod Name of the method in the class
40+
* @param array $args Arguments to pass to method
41+
*
42+
* @return mixed
43+
*/
44+
public function callStaticNonPublicMethod(string $className, string $classMethod, array $args)
45+
{
46+
$method = $this->getNonPublicMethodFromClass($className, $classMethod);
47+
48+
return $method->invokeArgs(null, $args);
49+
}
50+
51+
public function getNonPublicAttributeFromClass($attributeName, $classObject)
52+
{
53+
$reflector = new \ReflectionObject($classObject);
54+
55+
$attribute = $reflector->getProperty($attributeName);
56+
$attribute->setAccessible(true);
57+
58+
return $attribute->getValue($classObject);
59+
}
60+
}

tests/TikusTest.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
namespace Tests;
4+
5+
use Tests\TestCase;
6+
use Mamikos\Tikus\Tikus;
7+
use Bugsnag\BugsnagLaravel\Facades\Bugsnag;
8+
use Sentry\Laravel\Facade as Sentry;
9+
use Exception;
10+
11+
class TikusTest extends TestCase
12+
{
13+
public function testReportException()
14+
{
15+
$tikus = new Tikus();
16+
17+
Bugsnag::spy();
18+
Sentry::spy();
19+
20+
$tikus->reportException(new Exception());
21+
22+
Bugsnag::shouldHaveReceived('notifyException')->once();
23+
Sentry::shouldHaveReceived('captureException')->once();
24+
25+
$this->assertTrue(true);
26+
}
27+
28+
public function testReportExceptionWithMetadata()
29+
{
30+
$tikus = new Tikus();
31+
32+
Bugsnag::spy();
33+
Sentry::spy();
34+
35+
$metadata = [ 'data' => 1 ];
36+
$tikus->reportException(new Exception(), $metadata);
37+
38+
Bugsnag::shouldHaveReceived('notifyException')->once();
39+
40+
Sentry::shouldHaveReceived('captureException')->once();
41+
Sentry::shouldHaveReceived('configureScope')->once();
42+
43+
$this->assertTrue(true);
44+
}
45+
46+
public function testReportExceptionWithEmptyMetadata()
47+
{
48+
$tikus = new Tikus();
49+
50+
Bugsnag::spy();
51+
Sentry::spy();
52+
53+
$metadata = [];
54+
$tikus->reportException(new Exception(), $metadata);
55+
56+
Bugsnag::shouldHaveReceived('notifyException')->once();
57+
58+
Sentry::shouldHaveReceived('captureException')->once();
59+
Sentry::shouldNotHaveReceived('configureScope');
60+
61+
$this->assertTrue(true);
62+
}
63+
64+
public function testReportError()
65+
{
66+
$tikus = new Tikus();
67+
68+
Bugsnag::spy();
69+
Sentry::spy();
70+
71+
$tikus->reportError('name', 'message');
72+
73+
Bugsnag::shouldHaveReceived('notifyError')->once();
74+
Sentry::shouldHaveReceived('captureMessage')->once();
75+
76+
$this->assertTrue(true);
77+
}
78+
}

0 commit comments

Comments
 (0)