diff --git a/monitoring/README.md b/monitoring/README.md new file mode 100644 index 0000000000..16d17f3d65 --- /dev/null +++ b/monitoring/README.md @@ -0,0 +1,99 @@ +Stackdriver Monitoring PHP Samples +================================== + +This directory contains samples for Stackdriver Monitoring. +[Stackdriver Monitoring][monitoring] collects metrics, events, and metadata from +Google Cloud Platform, Amazon Web Services (AWS), hosted uptime probes, +application instrumentation, and a variety of common application components +including Cassandra, Nginx, Apache Web Server, Elasticsearch and many others. + +[monitoring]: https://cloud.google.com/monitoring/docs + +## Setup + +### Authentication + +Authentication is typically done through [Application Default Credentials][adc] +which means you do not have to change the code to authenticate as long as +your environment has credentials. You have a few options for setting up +authentication: + +1. When running locally, use the [Google Cloud SDK][google-cloud-sdk] + + gcloud auth application-default login + +1. When running on App Engine or Compute Engine, credentials are already + set-up. However, you may need to configure your Compute Engine instance + with [additional scopes][additional_scopes]. + +1. You can create a [Service Account key file][service_account_key_file]. This file can be used to + authenticate to Google Cloud Platform services from any environment. To use + the file, set the ``GOOGLE_APPLICATION_CREDENTIALS`` environment variable to + the path to the key file, for example: + + export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service_account.json + +[adc]: https://cloud.google.com/docs/authentication#getting_credentials_for_server-centric_flow +[additional_scopes]: https://cloud.google.com/compute/docs/authentication#using +[service_account_key_file]: https://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatinganaccount + +## Install Dependencies + +1. Ensure the [gRPC PHP Extension][php_grpc] is installed and enabled on your machine. +1. [Enable the Stackdriver Monitoring API](https://console.cloud.google.com/flows/enableapi?apiid=monitoring.googleapis.com). + +1. **Install dependencies** via [Composer](http://getcomposer.org/doc/00-intro.md). + Run `php composer.phar install` (if composer is installed locally) or `composer install` + (if composer is installed globally). + +1. Create a service account at the +[Service account section in the Cloud Console](https://console.cloud.google.com/iam-admin/serviceaccounts/) + +1. Download the json key file of the service account. + +1. Set `GOOGLE_APPLICATION_CREDENTIALS` environment variable pointing to that file. + +## Samples + +To run the Stackdriver Monitoring Samples: + + $ php monitoring.php + + Stackdriver Monitoring + + Usage: + command [options] [arguments] + + Options: + -h, --help Display this help message + -q, --quiet Do not output any message + -V, --version Display this application version + --ansi Force ANSI output + --no-ansi Disable ANSI output + -n, --no-interaction Do not ask any interactive question + -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug + + Available commands: + create-metric Creates a logging metric. + delete-metric Deletes a logging metric. + get-descriptor Gets a logging descriptor. + help Displays help for a command + list Lists commands + list-descriptors Lists logging descriptors. + read-timeseries-align Aggregates metrics for each timeseries. + read-timeseries-fields Reads Timeseries fields. + read-timeseries-reduce Aggregates metrics across multiple timeseries. + read-timeseries-simple Reads a timeseries. + write-timeseries Writes a timeseries. + +## The client library + +This sample uses the [Google Cloud Client Library for PHP][google-cloud-php]. +You can read the documentation for more details on API usage and use GitHub +to [browse the source][google-cloud-php-source] and [report issues][google-cloud-php-issues]. + +[php_grpc]: http://cloud.google.com/php/grpc +[google-cloud-php]: https://googlecloudplatform.github.io/google-cloud-php +[google-cloud-php-source]: https://github.com/GoogleCloudPlatform/google-cloud-php +[google-cloud-php-issues]: https://github.com/GoogleCloudPlatform/google-cloud-php/issues +[google-cloud-sdk]: https://cloud.google.com/sdk/ diff --git a/monitoring/composer.json b/monitoring/composer.json index 8d9eac5c38..d2a4e014b0 100644 --- a/monitoring/composer.json +++ b/monitoring/composer.json @@ -1,9 +1,23 @@ { "require": { - "google/cloud-monitoring": "^0.4" + "google/cloud-monitoring": "^0.4", + "symfony/console": "^3.3" + }, + "autoload": { + "files": [ + "src/create_metric.php", + "src/delete_metric.php", + "src/get_descriptor.php", + "src/list_descriptors.php", + "src/read_timeseries_align.php", + "src/read_timeseries_fields.php", + "src/read_timeseries_reduce.php", + "src/read_timeseries_simple.php", + "src/write_timeseries.php" + ] }, "require-dev": { - "phpunit/phpunit": "4.8.*", - "squizlabs/php_codesniffer": "2.*" + "phpunit/phpunit": "^4", + "google/cloud-tools": "^0.6" } } diff --git a/monitoring/composer.lock b/monitoring/composer.lock index 6a63a7447d..1e747437a2 100644 --- a/monitoring/composer.lock +++ b/monitoring/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "af3d3990e6d429812aa9e055464e3408", + "content-hash": "c8c2ea6ecb321239de558ce69ea15f04", "packages": [ { "name": "firebase/php-jwt", @@ -264,16 +264,16 @@ }, { "name": "grpc/grpc", - "version": "v1.4.1", + "version": "v1.4.2", "source": { "type": "git", "url": "https://github.com/grpc/grpc.git", - "reference": "844d5940035b6d96022076f89d6602faab464390" + "reference": "5cb6a1f86129fc2833de9a27cfe174260934342b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/grpc/grpc/zipball/844d5940035b6d96022076f89d6602faab464390", - "reference": "844d5940035b6d96022076f89d6602faab464390", + "url": "https://api.github.com/repos/grpc/grpc/zipball/5cb6a1f86129fc2833de9a27cfe174260934342b", + "reference": "5cb6a1f86129fc2833de9a27cfe174260934342b", "shasum": "" }, "require": { @@ -301,7 +301,7 @@ "keywords": [ "rpc" ], - "time": "2017-06-27T19:46:01+00:00" + "time": "2017-07-11T21:11:30+00:00" }, { "name": "guzzlehttp/guzzle", @@ -579,6 +579,237 @@ "response" ], "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/log", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10T12:19:37+00:00" + }, + { + "name": "symfony/console", + "version": "v3.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "a97e45d98c59510f085fa05225a1acb74dfe0546" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/a97e45d98c59510f085fa05225a1acb74dfe0546", + "reference": "a97e45d98c59510f085fa05225a1acb74dfe0546", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/debug": "~2.8|~3.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.3", + "symfony/dependency-injection": "~3.3", + "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/filesystem": "~2.8|~3.0", + "symfony/http-kernel": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/filesystem": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com/", + "time": "2017-07-03T13:19:36+00:00" + }, + { + "name": "symfony/debug", + "version": "v3.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "63b85a968486d95ff9542228dc2e4247f16f9743" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/63b85a968486d95ff9542228dc2e4247f16f9743", + "reference": "63b85a968486d95ff9542228dc2e4247f16f9743", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/http-kernel": "~2.8|~3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com/", + "time": "2017-07-05T13:02:37+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "f29dca382a6485c3cbe6379f0c61230167681937" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937", + "reference": "f29dca382a6485c3cbe6379f0c61230167681937", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2017-06-09T14:24:12+00:00" } ], "packages-dev": [ @@ -636,6 +867,56 @@ ], "time": "2015-06-14T21:17:01+00:00" }, + { + "name": "google/cloud-tools", + "version": "v0.6.3", + "source": { + "type": "git", + "url": "https://github.com/GoogleCloudPlatform/php-tools.git", + "reference": "90ecc5e371673078cf0fc71d442fd21415c277c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GoogleCloudPlatform/php-tools/zipball/90ecc5e371673078cf0fc71d442fd21415c277c3", + "reference": "90ecc5e371673078cf0fc71d442fd21415c277c3", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~5.3|~6.0", + "php": ">=5.5", + "phpunit/phpunit": "~4|~5", + "symfony/browser-kit": "~2|~3", + "symfony/process": "~2|~3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Google\\Cloud\\TestUtils\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Takashi Matsuo", + "email": "tmatsuo@google.com", + "homepage": "https://wp.gaeflex.ninja/" + } + ], + "description": "PHP tools for Google Cloud Platform", + "homepage": "https://github.com/GoogleCloudPlatform/php-tools", + "keywords": [ + "appengine", + "gcp", + "test" + ], + "time": "2017-02-23T22:19:51+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "1.0", @@ -1594,82 +1875,166 @@ "time": "2015-06-21T13:59:46+00:00" }, { - "name": "squizlabs/php_codesniffer", - "version": "2.9.1", + "name": "symfony/browser-kit", + "version": "v3.3.4", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" + "url": "https://github.com/symfony/browser-kit.git", + "reference": "3a4435e79a8401746e8525e98039199d0924b4e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/3a4435e79a8401746e8525e98039199d0924b4e5", + "reference": "3a4435e79a8401746e8525e98039199d0924b4e5", "shasum": "" }, "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.1.2" + "php": ">=5.5.9", + "symfony/dom-crawler": "~2.8|~3.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "symfony/css-selector": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" }, - "bin": [ - "scripts/phpcs", - "scripts/phpcbf" + "suggest": { + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } ], + "description": "Symfony BrowserKit Component", + "homepage": "https://symfony.com/", + "time": "2017-06-24T09:29:48+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v3.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "fc2c588ce376e9fe04a7b8c79e3ec62fe32d95b1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/fc2c588ce376e9fe04a7b8c79e3ec62fe32d95b1", + "reference": "fc2c588ce376e9fe04a7b8c79e3ec62fe32d95b1", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0" + }, + "suggest": { + "symfony/css-selector": "" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "3.3-dev" } }, "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Greg Sherwood", - "role": "lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com/", + "time": "2017-05-25T23:10:31+00:00" + }, + { + "name": "symfony/process", + "version": "v3.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "5ab8949b682b1bf9d4511a228b5e045c96758c30" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/5ab8949b682b1bf9d4511a228b5e045c96758c30", + "reference": "5ab8949b682b1bf9d4511a228b5e045c96758c30", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } ], - "time": "2017-05-22T02:43:20+00:00" + "description": "Symfony Process Component", + "homepage": "https://symfony.com/", + "time": "2017-07-03T08:12:02+00:00" }, { "name": "symfony/yaml", diff --git a/monitoring/monitoring.php b/monitoring/monitoring.php new file mode 100644 index 0000000000..bfce086a3a --- /dev/null +++ b/monitoring/monitoring.php @@ -0,0 +1,137 @@ +add(new Command('create-metric')) + ->setDefinition($inputDefinition) + ->setDescription('Creates a logging metric.') + ->setCode(function ($input, $output) { + create_metric( + $input->getArgument('project_id') + ); + }); + +$application->add(new Command('delete-metric')) + ->setDefinition(clone $inputDefinition) + ->addArgument('metric_id', InputArgument::REQUIRED, 'The metric descriptor id') + ->setDescription('Deletes a logging metric.') + ->setCode(function ($input, $output) { + delete_metric( + $input->getArgument('project_id'), + $input->getArgument('metric_id') + ); + }); + +$application->add(new Command('get-descriptor')) + ->setDefinition(clone $inputDefinition) + ->addArgument('metric_id', InputArgument::REQUIRED, 'The metric descriptor id') + ->setDescription('Gets a logging descriptor.') + ->setCode(function ($input, $output) { + get_descriptor( + $input->getArgument('project_id'), + $input->getArgument('metric_id') + ); + }); + +$application->add(new Command('list-descriptors')) + ->setDefinition($inputDefinition) + ->setDescription('Lists logging descriptors.') + ->setCode(function ($input, $output) { + list_descriptors( + $input->getArgument('project_id') + ); + }); + +$application->add(new Command('read-timeseries-align')) + ->setDefinition(clone $inputDefinition) + ->addOption('minutes-ago', null, InputOption::VALUE_REQUIRED, 20, + 'How many minutes in the past to start the time series.') + ->setDescription('Aggregates metrics for each timeseries.') + ->setCode(function ($input, $output) { + read_timeseries_align( + $input->getArgument('project_id'), + $input->getOption('minutes-ago') + ); + }); + +$application->add(new Command('read-timeseries-fields')) + ->setDefinition(clone $inputDefinition) + ->addOption('minutes-ago', null, InputOption::VALUE_REQUIRED, 20, + 'How many minutes in the past to start the time series.') + ->setDescription('Reads Timeseries fields.') + ->setCode(function ($input, $output) { + read_timeseries_fields( + $input->getArgument('project_id'), + $input->getOption('minutes-ago') + ); + }); + +$application->add(new Command('read-timeseries-reduce')) + ->setDefinition(clone $inputDefinition) + ->addOption('minutes-ago', null, InputOption::VALUE_REQUIRED, 20, + 'How many minutes in the past to start the time series.') + ->setDescription('Aggregates metrics across multiple timeseries.') + ->setCode(function ($input, $output) { + read_timeseries_reduce( + $input->getArgument('project_id'), + $input->getOption('minutes-ago') + ); + }); + +$application->add(new Command('read-timeseries-simple')) + ->setDefinition(clone $inputDefinition) + ->addOption('minutes-ago', null, InputOption::VALUE_REQUIRED, 20, + 'How many minutes in the past to start the time series.') + ->setDescription('Reads a timeseries.') + ->setCode(function ($input, $output) { + read_timeseries_simple( + $input->getArgument('project_id'), + $input->getOption('minutes-ago') + ); + }); + +$application->add(new Command('write-timeseries')) + ->setDefinition($inputDefinition) + ->setDescription('Writes a timeseries.') + ->setCode(function ($input, $output) { + write_timeseries( + $input->getArgument('project_id') + ); + }); + +// for testing +if (getenv('PHPUNIT_TESTS') === '1') { + return $application; +} + +$application->run(); diff --git a/monitoring/phpunit.xml.dist b/monitoring/phpunit.xml.dist index 70fd0bed56..9d297ccb03 100644 --- a/monitoring/phpunit.xml.dist +++ b/monitoring/phpunit.xml.dist @@ -25,4 +25,7 @@ quickstart.php + + + diff --git a/monitoring/src/create_metric.php b/monitoring/src/create_metric.php new file mode 100644 index 0000000000..0080b8b0c9 --- /dev/null +++ b/monitoring/src/create_metric.php @@ -0,0 +1,68 @@ + $projectId, + ]); + + $projectName = $metrics->formatProjectName($projectId); + + $descriptor = new MetricDescriptor(); + $descriptor->setDescription('Daily sales records from all branch stores.'); + $descriptor->setDisplayName('Daily Sales'); + $descriptor->setType('custom.googleapis.com/stores/daily_sales'); + $descriptor->setMetricKind(MetricDescriptor_MetricKind::GAUGE); + $descriptor->setValueType(MetricDescriptor_ValueType::DOUBLE); + $descriptor->setUnit('{USD}'); + $label = new LabelDescriptor(); + $label->setKey('store_id'); + $label->setValueType(LabelDescriptor_ValueType::STRING); + $label->setDescription('The ID of the store.'); + $labels = [$label]; + $descriptor->setLabels($labels); + + $descriptor = $metrics->createMetricDescriptor($projectName, $descriptor); + printf('Created a metric: ' . $descriptor->getName() . PHP_EOL); +} +// [END monitoring_create_metric] diff --git a/monitoring/src/delete_metric.php b/monitoring/src/delete_metric.php new file mode 100644 index 0000000000..884d3eee46 --- /dev/null +++ b/monitoring/src/delete_metric.php @@ -0,0 +1,50 @@ + $projectId, + ]); + + $metricPath = $metrics->formatMetricDescriptorName($projectId, $metricId); + $ret = $metrics->deleteMetricDescriptor($metricPath); + + printf('Deleted a metric: ' . $metricPath . PHP_EOL); +} +// [END monitoring_delete_metric] diff --git a/monitoring/src/get_descriptor.php b/monitoring/src/get_descriptor.php new file mode 100644 index 0000000000..a481e01c5b --- /dev/null +++ b/monitoring/src/get_descriptor.php @@ -0,0 +1,62 @@ + $projectId, + ]); + + $metricName = $metrics->formatMetricDescriptorName($projectId, $metricId); + $descriptor = $metrics->getMetricDescriptor($metricName); + + printf('Name: ' . $descriptor->getDisplayName() . PHP_EOL); + printf('Description: ' . $descriptor->getDescription() . PHP_EOL); + printf('Type: ' . $descriptor->getType() . PHP_EOL); + printf('Metric Kind: ' . $descriptor->getMetricKind() . PHP_EOL); + printf('Value Type: ' . $descriptor->getValueType() . PHP_EOL); + printf('Unit: ' . $descriptor->getUnit() . PHP_EOL); + printf('Labels:' . PHP_EOL); + foreach ($descriptor->getLabels() as $labels) { + printf(' %s (%s) - %s' . PHP_EOL, + $labels->getKey(), + $labels->getValueType(), + $labels->getDescription()); + } +} +// [END monitoring_get_descriptor] diff --git a/monitoring/src/list_descriptors.php b/monitoring/src/list_descriptors.php new file mode 100644 index 0000000000..72a606f649 --- /dev/null +++ b/monitoring/src/list_descriptors.php @@ -0,0 +1,52 @@ + $projectId, + ]); + + $projectName = $metrics->formatProjectName($projectId); + $descriptors = $metrics->listMetricDescriptors($projectName); + + printf('Metric Descriptors:' . PHP_EOL); + foreach ($descriptors->iterateAllElements() as $descriptor) { + printf($descriptor->getName() . PHP_EOL); + } +} +// [END monitoring_list_descriptors] diff --git a/monitoring/src/read_timeseries_align.php b/monitoring/src/read_timeseries_align.php new file mode 100644 index 0000000000..f1efe1a90f --- /dev/null +++ b/monitoring/src/read_timeseries_align.php @@ -0,0 +1,88 @@ + $projectId, + ]); + + $projectName = $metrics->formatProjectName($projectId); + $filter = 'metric.type="compute.googleapis.com/instance/cpu/utilization"'; + + $startTime = new Timestamp(); + $startTime->setSeconds(time() - (60 * $minutesAgo)); + $endTime = new Timestamp(); + $endTime->setSeconds(time()); + + $interval = new TimeInterval(); + $interval->setStartTime($startTime); + $interval->setEndTime($endTime); + + $alignmentPeriod = new Duration(); + $alignmentPeriod->setSeconds(600); + $aggregation = new Aggregation(); + $aggregation->setAlignmentPeriod($alignmentPeriod); + $aggregation->setPerSeriesAligner(Aggregation_Aligner::ALIGN_MEAN); + + $view = ListTimeSeriesRequest_TimeSeriesView::FULL; + + $result = $metrics->listTimeSeries( + $projectName, + $filter, + $interval, + $view, + ['aggregation' => $aggregation]); + + printf('CPU utilization:' . PHP_EOL); + foreach ($result->iterateAllElements() as $timeSeries) { + printf($timeSeries->getMetric()->getLabels()['instance_name'] . PHP_EOL); + printf(' Now: '); + printf($timeSeries->getPoints()[0]->getValue()->getDoubleValue() . PHP_EOL); + if (count($timeSeries->getPoints()) > 1) { + printf(' 10 minutes ago: '); + printf($timeSeries->getPoints()[1]->getValue()->getDoubleValue() . PHP_EOL); + } + } +} +// [END monitoring_read_timeseries_align] diff --git a/monitoring/src/read_timeseries_fields.php b/monitoring/src/read_timeseries_fields.php new file mode 100644 index 0000000000..19f2c2fc0c --- /dev/null +++ b/monitoring/src/read_timeseries_fields.php @@ -0,0 +1,72 @@ + $projectId, + ]); + + $projectName = $metrics->formatProjectName($projectId); + $filter = 'metric.type="compute.googleapis.com/instance/cpu/utilization"'; + + $startTime = new Timestamp(); + $startTime->setSeconds(time() - (60 * $minutesAgo)); + $endTime = new Timestamp(); + $endTime->setSeconds(time()); + + $interval = new TimeInterval(); + $interval->setStartTime($startTime); + $interval->setEndTime($endTime); + + $view = ListTimeSeriesRequest_TimeSeriesView::HEADERS; + + $result = $metrics->listTimeSeries( + $projectName, + $filter, + $interval, + $view); + + printf('Found data points for the following instances:' . PHP_EOL); + foreach ($result->iterateAllElements() as $timeSeries) { + printf($timeSeries->getMetric()->getLabels()['instance_name'] . PHP_EOL); + } +} +// [END monitoring_read_timeseries_fields] diff --git a/monitoring/src/read_timeseries_reduce.php b/monitoring/src/read_timeseries_reduce.php new file mode 100644 index 0000000000..6680fac5a6 --- /dev/null +++ b/monitoring/src/read_timeseries_reduce.php @@ -0,0 +1,88 @@ + $projectId, + ]); + + $projectName = $metrics->formatProjectName($projectId); + $filter = 'metric.type="compute.googleapis.com/instance/cpu/utilization"'; + + $startTime = new Timestamp(); + $startTime->setSeconds(time() - (60 * $minutesAgo)); + $endTime = new Timestamp(); + $endTime->setSeconds(time()); + + $interval = new TimeInterval(); + $interval->setStartTime($startTime); + $interval->setEndTime($endTime); + + $alignmentPeriod = new Duration(); + $alignmentPeriod->setSeconds(600); + $aggregation = new Aggregation(); + $aggregation->setAlignmentPeriod($alignmentPeriod); + $aggregation->setCrossSeriesReducer(Aggregation_Reducer::REDUCE_MEAN); + $aggregation->setPerSeriesAligner(Aggregation_Aligner::ALIGN_MEAN); + + $view = ListTimeSeriesRequest_TimeSeriesView::FULL; + + $result = $metrics->listTimeSeries( + $projectName, + $filter, + $interval, + $view, + ['aggregation' => $aggregation]); + + $reductions = $result->iterateAllElements()->current()->getPoints(); + printf('Average CPU utilization across all GCE instances:' . PHP_EOL); + printf(' Last 10 minutes: '); + printf($reductions[0]->getValue()->getDoubleValue() . PHP_EOL); + if (count($reductions) > 1) { + printf(' 10-20 minutes ago: '); + printf($reductions[1]->getValue()->getDoubleValue() . PHP_EOL); + } +} +// [END monitoring_read_timeseries_reduce] diff --git a/monitoring/src/read_timeseries_simple.php b/monitoring/src/read_timeseries_simple.php new file mode 100644 index 0000000000..bdc94f4c44 --- /dev/null +++ b/monitoring/src/read_timeseries_simple.php @@ -0,0 +1,77 @@ + $projectId, + ]); + + $projectName = $metrics->formatProjectName($projectId); + $filter = 'metric.type="compute.googleapis.com/instance/cpu/utilization"'; + + // Limit results to the last 20 minutes + $startTime = new Timestamp(); + $startTime->setSeconds(time() - (60 * $minutesAgo)); + $endTime = new Timestamp(); + $endTime->setSeconds(time()); + + $interval = new TimeInterval(); + $interval->setStartTime($startTime); + $interval->setEndTime($endTime); + + $view = ListTimeSeriesRequest_TimeSeriesView::FULL; + + $result = $metrics->listTimeSeries( + $projectName, + $filter, + $interval, + $view); + + printf('CPU utilization:' . PHP_EOL); + foreach ($result->iterateAllElements() as $timeSeries) { + $instanceName = $timeSeries->getMetric()->getLabels()['instance_name']; + printf($instanceName . ':' . PHP_EOL); + foreach ($timeSeries->getPoints() as $point) { + printf(' ' . $point->getValue()->getDoubleValue() . PHP_EOL); + } + } +} +// [END monitoring_read_timeseries_simple] diff --git a/monitoring/src/write_timeseries.php b/monitoring/src/write_timeseries.php new file mode 100644 index 0000000000..62103f24e9 --- /dev/null +++ b/monitoring/src/write_timeseries.php @@ -0,0 +1,88 @@ + $projectId, + ]); + + $projectName = $metrics->formatProjectName($projectId); + $filter = 'metric.type="compute.googleapis.com/instance/cpu/utilization"'; + + $endTime = new Timestamp(); + $endTime->setSeconds(time()); + $interval = new TimeInterval(); + $interval->setEndTime($endTime); + + $value = new TypedValue(); + $value->setDoubleValue(123.45); + + $point = new Point(); + $point->setValue($value); + $point->setInterval($interval); + $points = [$point]; + + $metric = new Metric(); + $metric->setType('custom.googleapis.com/stores/daily_sales'); + $labels = ['store_id' => 'Pittsburg']; + $metric->setLabels($labels); + + $resource = new MonitoredResource(); + $resource->setType('global'); + $labels = ['project_id' => $projectId]; + $resource->setLabels($labels); + + $timeSeries = new TimeSeries(); + $timeSeries->setMetric($metric); + $timeSeries->setResource($resource); + $timeSeries->setPoints($points); + + $result = $metrics->createTimeSeries( + $projectName, + [$timeSeries]); + + printf('Done writing time series data.' . PHP_EOL); +} +// [END monitoring_write_timeseries] diff --git a/monitoring/test/monitoringTest.php b/monitoring/test/monitoringTest.php new file mode 100644 index 0000000000..3410af3673 --- /dev/null +++ b/monitoring/test/monitoringTest.php @@ -0,0 +1,141 @@ +runCommand('create-metric'); + $this->assertContains('Created a metric', $output); + $this->assertContains(self::$metricId, $output); + + // ensure the metric gets created + $this->eventuallyConsistentRetryCount = 20; + $this->runEventuallyConsistentTest(function () { + $output = $this->runCommand('get-descriptor', [ + 'metric_id' => self::$metricId, + ]); + $this->assertContains(self::$metricId, $output); + }); + } + + /** @depends testCreateMetric */ + public function testGetDescriptor() + { + $output = $this->runCommand('get-descriptor', [ + 'metric_id' => self::$metricId, + ]); + $this->assertContains(self::$metricId, $output); + } + + /** @depends testCreateMetric */ + public function testListDescriptors() + { + $output = $this->runCommand('list-descriptors'); + $this->assertContains(self::$metricId, $output); + } + + /** @depends testCreateMetric */ + public function testDeleteMetric() + { + $output = $this->runCommand('delete-metric', [ + 'metric_id' => self::$metricId, + ]); + $this->assertContains('Deleted a metric', $output); + $this->assertContains(self::$metricId, $output); + } + + public function testWriteTimeseries() + { + $output = $this->runCommand('write-timeseries'); + $this->assertContains('Done writing time series data', $output); + } + + /** @depends testWriteTimeseries */ + public function testReadTimeseriesAlign() + { + $output = $this->runCommand('read-timeseries-align', [ + '--minutes-ago' => self::$minutesAgo + ]); + $this->assertContains('Now', $output); + } + + /** @depends testWriteTimeseries */ + public function testReadTimeseriesFields() + { + $output = $this->runCommand('read-timeseries-fields', [ + '--minutes-ago' => self::$minutesAgo + ]); + $this->assertContains('Found data points', $output); + $this->assertGreaterThanOrEqual(2, substr_count($output, "\n")); + } + + /** @depends testWriteTimeseries */ + public function testReadTimeseriesReduce() + { + $output = $this->runCommand('read-timeseries-reduce', [ + '--minutes-ago' => self::$minutesAgo + ]); + $this->assertContains('Last 10 minutes', $output); + } + + /** @depends testWriteTimeseries */ + public function testReadTimeseriesSimple() + { + $output = $this->runCommand('read-timeseries-simple', [ + '--minutes-ago' => self::$minutesAgo + ]); + $this->assertContains('CPU utilization:', $output); + $this->assertGreaterThanOrEqual(2, substr_count($output, "\n")); + } + + private function runCommand($commandName, $args = []) + { + $application = require __DIR__ . '/../monitoring.php'; + $command = $application->get($commandName); + $commandTester = new CommandTester($command); + + ob_start(); + $commandTester->execute( + ['project_id' => self::$projectId] + $args, + ['interactive' => false]); + + return ob_get_clean(); + } +}