Skip to content

Commit f660e72

Browse files
author
Jamie Hannaford
committed
Merge pull request rackspace#518 from Rvanlaak/logger-injection
Inject Logger in service when available in Client
2 parents c8e2de1 + 29cfa91 commit f660e72

7 files changed

Lines changed: 102 additions & 7 deletions

File tree

docs/getting-started.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ You can see in the first example that the constant `Rackspace::US_IDENTITY_ENDPO
5555
Rackspace's identity endpoint (`https://identity.api.rackspacecloud.com/v2.0/`). Another difference is that Rackspace
5656
uses API key for authentication, whereas OpenStack uses a generic password.
5757

58+
#### 1.2 Logger injection
59+
As the `Rackspace` client extends the `OpenStack` client, they both support passing `$options` as an array via the constructor's third parameter. The options are passed as a config to the `Guzzle` client, but also allow to inject your own `Logger`.
60+
61+
Prerequisities and usage example can be found in [the Clients userguide](/docs/userguide/Clients.md#12-logger-injection)
62+
5863
### 2. Pick what service you want to use
5964

6065
In this case, we want to use the Compute (Nova) service:
@@ -175,4 +180,4 @@ $callback = function($server) {
175180
$server->waitFor(ServerState::ACTIVE, 600, $callback);
176181
```
177182
So, the server will be polled until it is in an `ACTIVE` state, with a timeout of 600 seconds. When the poll happens, the
178-
callback function is executed - which in this case just logs some output.
183+
callback function is executed - which in this case just logs some output.

docs/userguide/Clients.md

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Users have access to two types of client: `OpenCloud\OpenStack` and `OpenCloud\R
1111
3. `OpenCloud\OpenStack`
1212
4. `OpenCloud\Rackspace`
1313

14-
## Initializing a client
14+
## 1. Initializing a client
1515

1616
### Rackspace
1717

@@ -44,7 +44,29 @@ $client = new OpenStack('http://identity.my-openstack.com/v2.0', array(
4444
));
4545
```
4646

47-
## Authentication
47+
#### 1.2 Logger injection
48+
As the `Rackspace` client extends the `OpenStack` client, they both support passing `$options` as an array via the constructor's third parameter. The options are passed as a config to the `Guzzle` client, but also allow to inject your own `Logger`.
49+
50+
Your logger should implement the `Psr\Log\LoggerInterface` [as defined in PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md). Example of a compatible logger is [`Monolog`](https://github.com/Seldaek/monolog). When the client does create a service, it will inject the logger if one is available.
51+
52+
To inject a `LoggerInterface` compatible logger into a new `Client`:
53+
54+
```php
55+
use Monolog\Logger;
56+
use OpenCloud\OpenStack;
57+
58+
// create a log channel
59+
$log = new Logger('name');
60+
61+
$client = new OpenStack('http://identity.my-openstack.com/v2.0', array(
62+
'username' => 'foo',
63+
'password' => 'bar'
64+
), array(
65+
'logger' => $log,
66+
));
67+
```
68+
69+
## 2. Authentication
4870

4971
The Client does not automatically authenticate against the API on object creation - it waits for an API call. When this happens, it checks whether the current "token" has expired, and (re-)authenticates if necessary.
5072

@@ -56,7 +78,7 @@ $client->authenticate();
5678

5779
If the credentials are incorrect, a `401` error will be returned. If credentials are correct, a `200` status is returned with your Service Catalog.
5880

59-
## Service Catalog
81+
## 3. Service Catalog
6082

6183
The Service Catalog is returned on successful authentication, and is composed of all the different API services available to the current tenant. All of this functionality is encapsulated in the `Catalog` object, which allows you greater control and interactivity.
6284

@@ -86,14 +108,14 @@ foreach ($catalog->getItems() as $catalogItem) {
86108

87109
As you can see, you have access to each Service's name, type and list of endpoints. Each endpoint provides access to the specific region, along with its public and private endpoint URLs.
88110

89-
## Default HTTP headers
111+
## 4. Default HTTP headers
90112

91113
To set default HTTP headers:
92114

93115
```php
94116
$client->setDefaultOption('headers/X-Custom-Header', 'FooBar');
95117
```
96118

97-
## Other functionality
119+
## 5. Other functionality
98120

99-
For a full list of functionality provided by Guzzle, please consult the [official documentation](http://docs.guzzlephp.org/en/latest/http-client/client.html).
121+
For a full list of functionality provided by Guzzle, please consult the [official documentation](http://docs.guzzlephp.org/en/latest/http-client/client.html).

lib/OpenCloud/Common/Base.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,14 @@ public function getLogger()
264264
return $this->logger;
265265
}
266266

267+
/**
268+
* @return bool
269+
*/
270+
public function hasLogger()
271+
{
272+
return (null !== $this->logger);
273+
}
274+
267275
/**
268276
* @deprecated
269277
*/

lib/OpenCloud/Common/Service/CatalogService.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
use Guzzle\Http\ClientInterface;
2121
use Guzzle\Http\Exception\BadResponseException;
2222
use Guzzle\Http\Url;
23+
use OpenCloud\Common\Base;
2324
use OpenCloud\Common\Exceptions;
2425
use OpenCloud\Common\Http\Message\Formatter;
26+
use OpenCloud\OpenStack;
2527
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
2628

2729
abstract class CatalogService extends AbstractService
@@ -71,6 +73,10 @@ abstract class CatalogService extends AbstractService
7173
*/
7274
public function __construct(ClientInterface $client, $type = null, $name = null, $region = null, $urlType = null)
7375
{
76+
if (($client instanceof Base || $client instanceof OpenStack) && $client->hasLogger()) {
77+
$this->setLogger($client->getLogger());
78+
}
79+
7480
$this->setClient($client);
7581

7682
$this->name = $name ? : static::DEFAULT_NAME;

lib/OpenCloud/Identity/Service.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
namespace OpenCloud\Identity;
1919

2020
use Guzzle\Http\ClientInterface;
21+
use OpenCloud\Common\Base;
2122
use OpenCloud\Common\Collection\PaginatedIterator;
2223
use OpenCloud\Common\Collection\ResourceIterator;
2324
use OpenCloud\Common\Http\Message\Formatter;
2425
use OpenCloud\Common\Service\AbstractService;
2526
use OpenCloud\Identity\Constants\User as UserConst;
27+
use OpenCloud\OpenStack;
2628

2729
/**
2830
* Class responsible for working with Rackspace's Cloud Identity service.
@@ -40,6 +42,11 @@ class Service extends AbstractService
4042
public static function factory(ClientInterface $client)
4143
{
4244
$identity = new self();
45+
46+
if (($client instanceof Base || $client instanceof OpenStack) && $client->hasLogger()) {
47+
$identity->setLogger($client->getLogger());
48+
}
49+
4350
$identity->setClient($client);
4451
$identity->setEndpoint(clone $client->getAuthUrl());
4552

lib/OpenCloud/OpenStack.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ class OpenStack extends Client
7979

8080
public function __construct($url, array $secret, array $options = array())
8181
{
82+
if (isset($options['logger']) && $options['logger'] instanceof LoggerInterface) {
83+
$this->setLogger($options['logger']);
84+
}
85+
8286
$this->setSecret($secret);
8387
$this->setAuthUrl($url);
8488

@@ -286,6 +290,14 @@ public function getLogger()
286290
return $this->logger;
287291
}
288292

293+
/**
294+
* @return bool
295+
*/
296+
public function hasLogger()
297+
{
298+
return (null !== $this->logger);
299+
}
300+
289301
/**
290302
* @deprecated
291303
*/

tests/OpenCloud/Tests/OpenStackTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,39 @@ public function test_Import_Credentials_Numeric_Tenant()
184184
$this->assertEquals('{expiration}', $this->client->getExpiration());
185185
$this->assertEquals($randomNumericTenant, $this->client->getTenant());
186186
}
187+
188+
public function testLoggerServiceInjection()
189+
{
190+
// Create a new client, pass stub via constructor options argument
191+
$stubLogger = $this->getMock('Psr\Log\NullLogger');
192+
$client = new OpenStack(Rackspace::US_IDENTITY_ENDPOINT, $this->credentials, array(
193+
'logger' => $stubLogger,
194+
));
195+
$client->addSubscriber(new MockSubscriber());
196+
197+
// Test all OpenStack factory methods on proper Logger service injection
198+
$service = $client->objectStoreService('cloudFiles', 'DFW');
199+
$this->assertContains("Mock_NullLogger", get_class($service->getLogger()));
200+
201+
$service = $service->getCdnService();
202+
$this->assertContains("Mock_NullLogger", get_class($service->getLogger()));
203+
204+
$service = $client->computeService('cloudServersOpenStack', 'DFW');
205+
$this->assertContains("Mock_NullLogger", get_class($service->getLogger()));
206+
207+
$service = $client->orchestrationService(null, 'DFW');
208+
$this->assertContains("Mock_NullLogger", get_class($service->getLogger()));
209+
210+
$service = $client->volumeService('cloudBlockStorage', 'DFW');
211+
$this->assertContains("Mock_NullLogger", get_class($service->getLogger()));
212+
213+
$service = $client->identityService();
214+
$this->assertContains("Mock_NullLogger", get_class($service->getLogger()));
215+
216+
$service = $client->imageService('cloudImages', 'IAD');
217+
$this->assertContains("Mock_NullLogger", get_class($service->getLogger()));
218+
219+
$service = $client->networkingService(null, 'IAD');
220+
$this->assertContains("Mock_NullLogger", get_class($service->getLogger()));
221+
}
187222
}

0 commit comments

Comments
 (0)