Commit b75ea5d5 authored by Judah Wright's avatar Judah Wright

Initial commit

parents
/vendor/
{
"name": "judahnator/blockchain-logger",
"description": "A logging interface using the judahnator/blockchain library",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Judah Wright",
"email": "judah@servercanyon.com"
}
],
"require": {
"psr/log": "^1.0",
"judahnator/blockchain": "^0.5.2"
},
"autoload": {
"files": [
"src/tailCustom.php"
],
"psr-4": {
"judahnator\\BlockchainLogger\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"judahnator\\BlockchainLogger\\Tests\\": "tests/"
}
}
}
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"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": "ed9c9a274e4091711bb11f1ee6796423",
"packages": [
{
"name": "judahnator/blockchain",
"version": "v0.5.2",
"source": {
"type": "git",
"url": "https://gitlab.com/judahnator/blockchain.git",
"reference": "4aa73dbf017db6a93c3233db6d314f304f7cf204"
},
"dist": {
"type": "zip",
"url": "https://gitlab.com/api/v4/projects/judahnator%2Fblockchain/repository/archive.zip?sha=4aa73dbf017db6a93c3233db6d314f304f7cf204",
"reference": "4aa73dbf017db6a93c3233db6d314f304f7cf204",
"shasum": ""
},
"require-dev": {
"phpunit/phpunit": "^7.0"
},
"type": "library",
"autoload": {
"files": [
"helpers/functions.php"
],
"psr-4": {
"judahnator\\BlockChain\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Judah Wright",
"email": "judah@servercanyon.com"
}
],
"description": "A simple blockchain library written in PHP",
"time": "2018-03-05T19:31:53+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"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
<?php
namespace judahnator\BlockchainLogger;
use judahnator\BlockChain\BlockChain;
use judahnator\BlockchainLogger\Drivers\LinearBlockchainFileDriver;
use Psr\Log\LoggerInterface;
class BlockchainLogger implements LoggerInterface
{
private $blockchain, $driver;
public function __construct(string $logPath)
{
$this->driver = new LinearBlockchainFileDriver($logPath);
$this->blockchain = BlockChain::load($this->driver);
}
/**
* System is unusable.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function emergency($message, array $context = array())
{
$this->log('emergency', $message, $context);
}
/**
* Action must be taken immediately.
*
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function alert($message, array $context = array())
{
$this->log('alert', $message, $context);
}
/**
* Critical conditions.
*
* Example: Application component unavailable, unexpected exception.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function critical($message, array $context = array())
{
$this->log('critical', $message, $context);
}
/**
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function error($message, array $context = array())
{
$this->log('error', $message, $context);
}
/**
* Exceptional occurrences that are not errors.
*
* Example: Use of deprecated APIs, poor use of an API, undesirable things
* that are not necessarily wrong.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function warning($message, array $context = array())
{
$this->log('warning', $message, $context);
}
/**
* Normal but significant events.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function notice($message, array $context = array())
{
$this->log('notice', $message, $context);
}
/**
* Interesting events.
*
* Example: User logs in, SQL logs.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function info($message, array $context = array())
{
$this->log('info', $message, $context);
}
/**
* Detailed debug information.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function debug($message, array $context = array())
{
$this->log('debug', $message, $context);
}
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string $message
* @param array $context
*
* @return void
*/
public function log($level, $message, array $context = array())
{
$this->driver->getMostRecentEntry()->createChild((object)[
'level' => $level,
'message' => $message,
'context' => $context
]);
}
}
\ No newline at end of file
<?php
namespace judahnator\BlockchainLogger\Drivers;
use judahnator\BlockChain\Block;
use judahnator\BlockChain\BlockChain;
use function judahnator\BlockChain\createOriginBlock;
use judahnator\BlockChain\Drivers\BlockStorageInterface;
use judahnator\BlockChain\Exceptions\BlockNotFoundException;
class LinearBlockchainFileDriver implements BlockStorageInterface
{
private $logFilePath;
public function __construct(string $logFilePath)
{
$this->logFilePath = $logFilePath;
}
private static function parseLogEntry(string $entry)
{
$blockJson = json_decode($entry);
if (json_last_error() !== JSON_ERROR_NONE || !$blockJson) {
return null;
}
return new Block(
$blockJson->height,
$blockJson->previousHash,
(new \DateTime())->setTimestamp($blockJson->created_at),
$blockJson->data
);
}
public function children(Block $block): array
{
$blocks = [];
$handle = fopen("inputfile.txt", "r");
while (($line = fgets($handle)) !== false) {
$thisblock = self::parseLogEntry($line);
if ($thisblock->hash === $block->hash) {
$blocks[] = $thisblock;
}
}
fclose($handle);
return $blocks;
}
public function delete(Block $block): void
{
throw new \LogicException('You are trying to erase a log entry?');
}
public function find(string $blockHash): Block
{
$handle = fopen($this->logFilePath, "r");
while (($line = fgets($handle)) !== false) {
$block = self::parseLogEntry($line);
if ($block->hash === $blockHash) {
return $block;
}
}
fclose($handle);
throw new BlockNotFoundException('The given block could not be found');
}
public function getMostRecentEntry(): Block
{
return self::parseLogEntry(tailCustom($this->logFilePath)) ?: BlockChain::originBlock();
}
public function originBlock(\stdClass $defaultData = null): Block
{
return createOriginBlock($defaultData ?: (object)[
'level' => 'info',
'message' => 'log opened',
'context' => []
]);
}
public function save(Block $block): void
{
file_put_contents(
$this->logFilePath,
json_encode([
'height' => $block->height,
'previousHash' => $block->previous->hash ?? '',
'created_at' => $block->created_at->getTimestamp(),
'data' => $block->data
]) . PHP_EOL,
FILE_APPEND
);
}
}
<?php
/**
* Slightly modified version of http://www.geekality.net/2011/05/28/php-tail-tackling-large-files/
* @author Torleif Berger, Lorenzo Stanco
* @link http://stackoverflow.com/a/15025877/995958
* @license http://creativecommons.org/licenses/by/3.0/
*/
function tailCustom($filepath, $lines = 1, $adaptive = true) {
// Open file
$f = @fopen($filepath, "rb");
if ($f === false) return false;
// Sets buffer size, according to the number of lines to retrieve.
// This gives a performance boost when reading a few lines from the file.
if (!$adaptive) $buffer = 4096;
else $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096));
// Jump to last character
fseek($f, -1, SEEK_END);
// Read it and adjust line number if necessary
// (Otherwise the result would be wrong if file doesn't end with a blank line)
if (fread($f, 1) != "\n") $lines -= 1;
// Start reading
$output = '';
$chunk = '';
// While we would like more
while (ftell($f) > 0 && $lines >= 0) {
// Figure out how far back we should jump
$seek = min(ftell($f), $buffer);
// Do the jump (backwards, relative to where we are)
fseek($f, -$seek, SEEK_CUR);
// Read a chunk and prepend it to our output
$output = ($chunk = fread($f, $seek)) . $output;
// Jump back to where we started reading
fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);
// Decrease our line counter
$lines -= substr_count($chunk, "\n");
}
// While we have too many lines
// (Because of buffer size we might have read too many)
while ($lines++ < 0) {
// Find first newline and remove all text before that
$output = substr($output, strpos($output, "\n") + 1);
}
// Close file and return
fclose($f);
return trim($output);
}
?>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment