LogRecordIterator.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. namespace Aws\CloudTrail;
  3. use Aws\S3\S3Client;
  4. /**
  5. * The `Aws\CloudTrail\LogRecordIterator` provides an easy way to iterate over
  6. * log records from log files generated by AWS CloudTrail.
  7. *
  8. * CloudTrail log files contain data about your AWS API calls and are stored in
  9. * Amazon S3 at a predictable path based on a bucket name, a key prefix, an
  10. * account ID, a region, and date information. The files are gzipped and
  11. * contain structured data in JSON format. This class allows you to specify
  12. * options via its factory methods, including a date range, and emits each log
  13. * record from any log files that match the provided options.
  14. *
  15. * A log record containing data about an AWS API call is yielded for each
  16. * iteration on this object.
  17. */
  18. class LogRecordIterator implements \OuterIterator
  19. {
  20. /** @var LogFileReader */
  21. private $logFileReader;
  22. /** @var \Iterator */
  23. private $logFileIterator;
  24. /** @var array */
  25. private $records;
  26. /** @var int */
  27. private $recordIndex;
  28. /**
  29. * @param S3Client $s3Client
  30. * @param CloudTrailClient $cloudTrailClient
  31. * @param array $options
  32. *
  33. * @return LogRecordIterator
  34. */
  35. public static function forTrail(
  36. S3Client $s3Client,
  37. CloudTrailClient $cloudTrailClient,
  38. array $options = []
  39. ) {
  40. $logFileIterator = LogFileIterator::forTrail(
  41. $s3Client,
  42. $cloudTrailClient,
  43. $options
  44. );
  45. return new self(new LogFileReader($s3Client), $logFileIterator);
  46. }
  47. /**
  48. * @param S3Client $s3Client
  49. * @param string $s3BucketName
  50. * @param array $options
  51. *
  52. * @return LogRecordIterator
  53. */
  54. public static function forBucket(
  55. S3Client $s3Client,
  56. $s3BucketName,
  57. array $options = []
  58. ) {
  59. $logFileReader = new LogFileReader($s3Client);
  60. $iter = new LogFileIterator($s3Client, $s3BucketName, $options);
  61. return new self($logFileReader, $iter);
  62. }
  63. /**
  64. * @param S3Client $s3Client
  65. * @param string $s3BucketName
  66. * @param string $s3ObjectKey
  67. *
  68. * @return LogRecordIterator
  69. */
  70. public static function forFile(
  71. S3Client $s3Client,
  72. $s3BucketName,
  73. $s3ObjectKey
  74. ) {
  75. $logFileReader = new LogFileReader($s3Client);
  76. $logFileIterator = new \ArrayIterator([[
  77. 'Bucket' => $s3BucketName,
  78. 'Key' => $s3ObjectKey,
  79. ]]);
  80. return new self($logFileReader, $logFileIterator);
  81. }
  82. /**
  83. * @param LogFileReader $logFileReader
  84. * @param \Iterator $logFileIterator
  85. */
  86. public function __construct(
  87. LogFileReader $logFileReader,
  88. \Iterator $logFileIterator
  89. ) {
  90. $this->logFileReader = $logFileReader;
  91. $this->logFileIterator = $logFileIterator;
  92. $this->records = array();
  93. $this->recordIndex = 0;
  94. }
  95. /**
  96. * Returns the current log record as an array.
  97. *
  98. * @return array|false
  99. */
  100. #[\ReturnTypeWillChange]
  101. public function current()
  102. {
  103. return $this->valid() ? $this->records[$this->recordIndex] : false;
  104. }
  105. #[\ReturnTypeWillChange]
  106. public function next()
  107. {
  108. $this->recordIndex++;
  109. // If all the records have been exhausted, get more records from the
  110. // next log file.
  111. while (!$this->valid()) {
  112. $this->logFileIterator->next();
  113. $success = $this->loadRecordsFromCurrentLogFile();
  114. if (!$success) {
  115. // The objects iterator is exhausted as well, so stop trying
  116. break;
  117. }
  118. }
  119. }
  120. #[\ReturnTypeWillChange]
  121. public function key()
  122. {
  123. if ($logFile = $this->logFileIterator->current()) {
  124. return $logFile['Key'] . '.' . $this->recordIndex;
  125. }
  126. return null;
  127. }
  128. #[\ReturnTypeWillChange]
  129. public function valid()
  130. {
  131. return isset($this->records[$this->recordIndex]);
  132. }
  133. #[\ReturnTypeWillChange]
  134. public function rewind()
  135. {
  136. $this->logFileIterator->rewind();
  137. $this->loadRecordsFromCurrentLogFile();
  138. }
  139. #[\ReturnTypeWillChange]
  140. public function getInnerIterator()
  141. {
  142. return $this->logFileIterator;
  143. }
  144. /**
  145. * Examines the current file in the `logFileIterator` and attempts to read
  146. * it and load log records from it using the `logFileReader`. This method
  147. * expects that items pulled from the iterator will take the form:
  148. *
  149. * [
  150. * 'Bucket' => '...',
  151. * 'Key' => '...',
  152. * ]
  153. *
  154. * @return bool Returns `true` if records were loaded and `false` if no
  155. * records were found
  156. */
  157. private function loadRecordsFromCurrentLogFile()
  158. {
  159. $this->recordIndex = 0;
  160. $this->records = array();
  161. $logFile = $this->logFileIterator->current();
  162. if ($logFile && isset($logFile['Bucket']) && isset($logFile['Key'])) {
  163. $this->records = $this->logFileReader->read(
  164. $logFile['Bucket'],
  165. $logFile['Key']
  166. );
  167. }
  168. return (bool) $logFile;
  169. }
  170. }