Skip to content

Commit bc4b9e5

Browse files
authored
feat: Integrate PSR LoggerInterface and add logging (#227)
- feat: Integrate PSR LoggerInterface for enhanced logging - fix: Resolve Psalm errors, CS fixes, and LogLevel import issues - feat: Update EnvironmentAwareIntegrationTest to non-static - feat: Add explicit close() method to BoltConnection, replacing reliance on __destruct - feat: Implement connection management to close all driver connections - refactor: Update consumeResults and standardize Docker auth details - fix: Ensure proper handling of boltProtocol lifecycle - fix: Refine logger tests to check SessionConfiguration type for accuracy - test: Adjust logger test for Neo4j/Bolt schemes and ignore HTTP connection logs - chore: Add named GitHub workflows for Docker Compose Action
1 parent c91a479 commit bc4b9e5

35 files changed

+636
-114
lines changed

.github/workflows/integration-test-cluster-neo4j-4.yml

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121
run: |
2222
echo "CONNECTION=neo4j://neo4j:testtest@neo4j" > .env
2323
- uses: hoverkraft-tech/[email protected]
24+
name: Start services
2425
with:
2526
compose-file: './docker-compose-neo4j-4.yml'
2627
up-flags: '--build --remove-orphans'

.github/workflows/integration-test-cluster-neo4j-5.yml

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121
run: |
2222
echo "CONNECTION=neo4j://neo4j:testtest@neo4j" > .env
2323
- uses: hoverkraft-tech/[email protected]
24+
name: Start services
2425
with:
2526
compose-file: './docker-compose.yml'
2627
up-flags: '--build --remove-orphans'

.github/workflows/integration-test-single-server.yml

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
run: |
2020
echo "CONNECTION=neo4j://neo4j:testtest@neo4j" > .env
2121
- uses: hoverkraft-tech/[email protected]
22+
name: Start services
2223
with:
2324
compose-file: './docker-compose-neo4j-4.yml'
2425
up-flags: '--build --remove-orphans'
@@ -44,6 +45,7 @@ jobs:
4445
run: |
4546
echo "CONNECTION=neo4j://neo4j:testtest@neo4j" > .env
4647
- uses: hoverkraft-tech/[email protected]
48+
name: Start services
4749
with:
4850
compose-file: './docker-compose.yml'
4951
up-flags: '--build'

composer.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
"suggest": {
4141
"ext-bcmath": "Needed to implement bolt protocol",
4242
"ext-sysvsem": "Needed for enabling connection pooling between processes",
43-
"composer-runtime-api": "Install composer 2 for auto detection of version in user agent"
43+
"composer-runtime-api": "Install composer 2 for auto detection of version in user agent",
44+
"psr/log": "Needed to enable logging"
4445
},
4546
"require-dev": {
4647
"phpunit/phpunit": "^10.0",
@@ -51,12 +52,12 @@
5152
"friendsofphp/php-cs-fixer": "3.15.0",
5253
"psalm/plugin-phpunit": "^0.18",
5354
"monolog/monolog": "^2.2",
54-
"psr/log": "^1.1",
5555
"symfony/uid": "^5.0",
5656
"symfony/var-dumper": "^5.0",
5757
"cache/integration-tests": "dev-master",
5858
"kubawerlos/php-cs-fixer-custom-fixers": "3.13.*",
59-
"rector/rector": "^1.0"
59+
"rector/rector": "^1.0",
60+
"psr/log": "^3.0"
6061
},
6162
"autoload": {
6263
"psr-4": {

phpunit.xml.dist

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
</testsuite>
1313
</testsuites>
1414
<php>
15-
<env name="CONNECTION" value="neo4j://neo4j:testtest@localhost:11687"/>
15+
<env name="CONNECTION" value="neo4j://neo4j:testtest@localhost:7687"/>
1616
</php>
1717
</phpunit>

src/Authentication/Authenticate.php

+12-11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use function explode;
1717

18+
use Laudis\Neo4j\Common\Neo4jLogger;
1819
use Laudis\Neo4j\Contracts\AuthenticateInterface;
1920
use Psr\Http\Message\UriInterface;
2021

@@ -32,47 +33,47 @@ final class Authenticate
3233
*
3334
* @pure
3435
*/
35-
public static function basic(string $username, string $password): BasicAuth
36+
public static function basic(string $username, string $password, ?Neo4jLogger $logger = null): BasicAuth
3637
{
37-
return new BasicAuth($username, $password);
38+
return new BasicAuth($username, $password, $logger);
3839
}
3940

4041
/**
4142
* Authenticate using a kerberos token.
4243
*
4344
* @pure
4445
*/
45-
public static function kerberos(string $token): KerberosAuth
46+
public static function kerberos(string $token, ?Neo4jLogger $logger = null): KerberosAuth
4647
{
47-
return new KerberosAuth($token);
48+
return new KerberosAuth($token, $logger);
4849
}
4950

5051
/**
5152
* Authenticate using a OpenID Connect token.
5253
*
5354
* @pure
5455
*/
55-
public static function oidc(string $token): OpenIDConnectAuth
56+
public static function oidc(string $token, ?Neo4jLogger $logger = null): OpenIDConnectAuth
5657
{
57-
return new OpenIDConnectAuth($token);
58+
return new OpenIDConnectAuth($token, $logger);
5859
}
5960

6061
/**
6162
* Don't authenticate at all.
6263
*
6364
* @pure
6465
*/
65-
public static function disabled(): NoAuth
66+
public static function disabled(?Neo4jLogger $logger = null): NoAuth
6667
{
67-
return new NoAuth();
68+
return new NoAuth($logger);
6869
}
6970

7071
/**
7172
* Authenticate from information found in the url.
7273
*
7374
* @pure
7475
*/
75-
public static function fromUrl(UriInterface $uri): AuthenticateInterface
76+
public static function fromUrl(UriInterface $uri, ?Neo4jLogger $logger = null): AuthenticateInterface
7677
{
7778
/**
7879
* @psalm-suppress ImpureMethodCall Uri is a pure object:
@@ -86,9 +87,9 @@ public static function fromUrl(UriInterface $uri): AuthenticateInterface
8687
$explode = explode(':', $userInfo);
8788
[$user, $pass] = $explode;
8889

89-
return self::basic($user, $pass);
90+
return self::basic($user, $pass, $logger);
9091
}
9192

92-
return self::disabled();
93+
return self::disabled($logger);
9394
}
9495
}

src/Authentication/BasicAuth.php

+8-4
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
use Bolt\protocol\V5_3;
2323
use Bolt\protocol\V5_4;
2424
use Exception;
25+
use Laudis\Neo4j\Common\Neo4jLogger;
2526
use Laudis\Neo4j\Common\ResponseHelper;
2627
use Laudis\Neo4j\Contracts\AuthenticateInterface;
2728
use Psr\Http\Message\RequestInterface;
2829
use Psr\Http\Message\UriInterface;
30+
use Psr\Log\LogLevel;
2931

3032
/**
3133
* Authenticates connections using a basic username and password.
@@ -37,14 +39,13 @@ final class BasicAuth implements AuthenticateInterface
3739
*/
3840
public function __construct(
3941
private readonly string $username,
40-
private readonly string $password
42+
private readonly string $password,
43+
private readonly ?Neo4jLogger $logger,
4144
) {}
4245

43-
/**
44-
* @psalm-mutation-free
45-
*/
4646
public function authenticateHttp(RequestInterface $request, UriInterface $uri, string $userAgent): RequestInterface
4747
{
48+
$this->logger?->log(LogLevel::DEBUG, 'Authenticating using BasicAuth');
4849
$combo = base64_encode($this->username.':'.$this->password);
4950

5051
/**
@@ -64,8 +65,10 @@ public function authenticateHttp(RequestInterface $request, UriInterface $uri, s
6465
public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $userAgent): array
6566
{
6667
if (method_exists($protocol, 'logon')) {
68+
$this->logger?->log(LogLevel::DEBUG, 'HELLO', ['user_agent' => $userAgent]);
6769
$protocol->hello(['user_agent' => $userAgent]);
6870
$response = ResponseHelper::getResponse($protocol);
71+
$this->logger?->log(LogLevel::DEBUG, 'LOGON', ['scheme' => 'basic', 'principal' => $this->username]);
6972
$protocol->logon([
7073
'scheme' => 'basic',
7174
'principal' => $this->username,
@@ -76,6 +79,7 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
7679
/** @var array{server: string, connection_id: string, hints: list} */
7780
return $response->content;
7881
} else {
82+
$this->logger?->log(LogLevel::DEBUG, 'HELLO', ['user_agent' => $userAgent, 'scheme' => 'basic', 'principal' => $this->username]);
7983
$protocol->hello([
8084
'user_agent' => $userAgent,
8185
'scheme' => 'basic',

src/Authentication/KerberosAuth.php

+8-4
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
use Bolt\protocol\V5_3;
2121
use Bolt\protocol\V5_4;
2222
use Exception;
23+
use Laudis\Neo4j\Common\Neo4jLogger;
2324
use Laudis\Neo4j\Common\ResponseHelper;
2425
use Laudis\Neo4j\Contracts\AuthenticateInterface;
2526
use Psr\Http\Message\RequestInterface;
2627
use Psr\Http\Message\UriInterface;
28+
use Psr\Log\LogLevel;
2729

2830
use function sprintf;
2931

@@ -36,14 +38,13 @@ final class KerberosAuth implements AuthenticateInterface
3638
* @psalm-external-mutation-free
3739
*/
3840
public function __construct(
39-
private readonly string $token
41+
private readonly string $token,
42+
private readonly ?Neo4jLogger $logger,
4043
) {}
4144

42-
/**
43-
* @psalm-mutation-free
44-
*/
4545
public function authenticateHttp(RequestInterface $request, UriInterface $uri, string $userAgent): RequestInterface
4646
{
47+
$this->logger?->log(LogLevel::DEBUG, 'Authenticating using KerberosAuth');
4748
/**
4849
* @psalm-suppress ImpureMethodCall Request is a pure object:
4950
*
@@ -61,8 +62,10 @@ public function authenticateHttp(RequestInterface $request, UriInterface $uri, s
6162
public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $userAgent): array
6263
{
6364
if (method_exists($protocol, 'logon')) {
65+
$this->logger?->log(LogLevel::DEBUG, 'HELLO', ['user_agent' => $userAgent]);
6466
$protocol->hello(['user_agent' => $userAgent]);
6567
$response = ResponseHelper::getResponse($protocol);
68+
$this->logger?->log(LogLevel::DEBUG, 'LOGON', ['scheme' => 'kerberos', 'principal' => '']);
6669
$protocol->logon([
6770
'scheme' => 'kerberos',
6871
'principal' => '',
@@ -73,6 +76,7 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
7376
/** @var array{server: string, connection_id: string, hints: list} */
7477
return $response->content;
7578
} else {
79+
$this->logger?->log(LogLevel::DEBUG, 'HELLO', ['user_agent' => $userAgent, 'scheme' => 'kerberos', 'principal' => '']);
7680
$protocol->hello([
7781
'user_agent' => $userAgent,
7882
'scheme' => 'kerberos',

src/Authentication/NoAuth.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
use Bolt\protocol\V5_3;
2121
use Bolt\protocol\V5_4;
2222
use Exception;
23+
use Laudis\Neo4j\Common\Neo4jLogger;
2324
use Laudis\Neo4j\Common\ResponseHelper;
2425
use Laudis\Neo4j\Contracts\AuthenticateInterface;
2526
use Psr\Http\Message\RequestInterface;
2627
use Psr\Http\Message\UriInterface;
28+
use Psr\Log\LogLevel;
2729

2830
use function sprintf;
2931

@@ -33,10 +35,15 @@
3335
final class NoAuth implements AuthenticateInterface
3436
{
3537
/**
36-
* @psalm-mutation-free
38+
* @pure
3739
*/
40+
public function __construct(
41+
private readonly ?Neo4jLogger $logger
42+
) {}
43+
3844
public function authenticateHttp(RequestInterface $request, UriInterface $uri, string $userAgent): RequestInterface
3945
{
46+
$this->logger?->log(LogLevel::DEBUG, 'Authentication disabled');
4047
/**
4148
* @psalm-suppress ImpureMethodCall Request is a pure object:
4249
*
@@ -53,8 +60,10 @@ public function authenticateHttp(RequestInterface $request, UriInterface $uri, s
5360
public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $userAgent): array
5461
{
5562
if (method_exists($protocol, 'logon')) {
63+
$this->logger?->log(LogLevel::DEBUG, 'HELLO', ['user_agent' => $userAgent]);
5664
$protocol->hello(['user_agent' => $userAgent]);
5765
$response = ResponseHelper::getResponse($protocol);
66+
$this->logger?->log(LogLevel::DEBUG, 'LOGON', ['scheme' => 'none']);
5867
$protocol->logon([
5968
'scheme' => 'none',
6069
]);
@@ -63,6 +72,7 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
6372
/** @var array{server: string, connection_id: string, hints: list} */
6473
return $response->content;
6574
} else {
75+
$this->logger?->log(LogLevel::DEBUG, 'HELLO', ['user_agent' => $userAgent, 'scheme' => 'none']);
6676
$protocol->hello([
6777
'user_agent' => $userAgent,
6878
'scheme' => 'none',

src/Authentication/OpenIDConnectAuth.php

+8-4
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
use Bolt\protocol\V5_3;
2121
use Bolt\protocol\V5_4;
2222
use Exception;
23+
use Laudis\Neo4j\Common\Neo4jLogger;
2324
use Laudis\Neo4j\Common\ResponseHelper;
2425
use Laudis\Neo4j\Contracts\AuthenticateInterface;
2526
use Psr\Http\Message\RequestInterface;
2627
use Psr\Http\Message\UriInterface;
28+
use Psr\Log\LogLevel;
2729

2830
use function sprintf;
2931

@@ -33,14 +35,13 @@ final class OpenIDConnectAuth implements AuthenticateInterface
3335
* @psalm-external-mutation-free
3436
*/
3537
public function __construct(
36-
private readonly string $token
38+
private readonly string $token,
39+
private readonly ?Neo4jLogger $logger
3740
) {}
3841

39-
/**
40-
* @psalm-mutation-free
41-
*/
4242
public function authenticateHttp(RequestInterface $request, UriInterface $uri, string $userAgent): RequestInterface
4343
{
44+
$this->logger?->log(LogLevel::DEBUG, 'Authenticating using OpenIDConnectAuth');
4445
/**
4546
* @psalm-suppress ImpureMethodCall Request is a pure object:
4647
*
@@ -58,8 +59,10 @@ public function authenticateHttp(RequestInterface $request, UriInterface $uri, s
5859
public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $userAgent): array
5960
{
6061
if (method_exists($protocol, 'logon')) {
62+
$this->logger?->log(LogLevel::DEBUG, 'HELLO', ['user_agent' => $userAgent]);
6163
$protocol->hello(['user_agent' => $userAgent]);
6264
$response = ResponseHelper::getResponse($protocol);
65+
$this->logger?->log(LogLevel::DEBUG, 'LOGON', ['scheme' => 'bearer']);
6366
$protocol->logon([
6467
'scheme' => 'bearer',
6568
'credentials' => $this->token,
@@ -69,6 +72,7 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
6972
/** @var array{server: string, connection_id: string, hints: list} */
7073
return $response->content;
7174
} else {
75+
$this->logger?->log(LogLevel::DEBUG, 'HELLO', ['user_agent' => $userAgent, 'scheme' => 'bearer']);
7276
$protocol->hello([
7377
'user_agent' => $userAgent,
7478
'scheme' => 'bearer',

src/Basic/Driver.php

+5
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,9 @@ public static function create(string|UriInterface $uri, ?DriverConfiguration $co
5757

5858
return new self($driver);
5959
}
60+
61+
public function closeConnections(): void
62+
{
63+
$this->driver->closeConnections();
64+
}
6065
}

0 commit comments

Comments
 (0)