Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 99 additions & 2 deletions src/Stackify/Log/Builder/MessageBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
use Stackify\Log\Entities\Api\LogMsgGroup;
use Stackify\Log\Entities\Agent\AgentMessage;
use Stackify\Exceptions\InitializationException;
use Stackify\Log\Filters\LogMsg\ErrorStackTraceMaskFilter;
use Stackify\Log\Filters\LogMsgFilterable;
use Stackify\Log\Transport\Config\Agent;

class MessageBuilder implements BuilderInterface
{
Expand All @@ -20,8 +23,20 @@ class MessageBuilder implements BuilderInterface
protected $appName;
protected $environmentName;
protected $logServerVariables;
/**
* Log message filters
*
* @var LogMsgFilterable[]
*/
protected $logMessageFilters;
/**
* Agent config
*
* @var Agent
*/
protected $agentConfig;

public function __construct($loggerName, $appName, $environmentName = null, $logServerVariables = false)
public function __construct($loggerName, $appName, $environmentName = null, $logServerVariables = false, $config = null)
{
if (!function_exists('json_encode')) {
throw new InitializationException('JSON extension is required for Stackify logger');
Expand All @@ -32,6 +47,10 @@ public function __construct($loggerName, $appName, $environmentName = null, $log
$this->logServerVariables = $logServerVariables;
// set state for environment details
EnvironmentDetail::getInstance()->init($appName, $environmentName);
$this->agentConfig = !empty($config) ? $config : Agent::getInstance();
$this->logMessageFilters = array();

$this->addLogMessageFiltersFromConfig();
}

public function getAgentMessage(LogMsg $logMsg)
Expand Down Expand Up @@ -64,6 +83,7 @@ public function createLogMsg(LogEntryInterface $logEntry)
$logEntry->getMessage(),
$logEntry->getMilliseconds()
);

$errorWrapper = null;
if ($exception = $logEntry->getException()) {
$errorWrapper = new ErrorWrapper($exception);
Expand All @@ -72,16 +92,19 @@ public function createLogMsg(LogEntryInterface $logEntry)
} elseif ($logEntry->isErrorLevel()) {
$errorWrapper = new ErrorWrapper($logEntry);
}

if (null !== $errorWrapper) {
$error = new StackifyError($this->appName, $this->environmentName, $this->logServerVariables);
$error->OccurredEpochMillis = $logEntry->getMilliseconds();
$error->Error = $this->getErrorItem($errorWrapper);
$logMsg->setError($error);
}

if (null !== $logEntry->getContext()) {
$logMsg->data = $this->encodeJSON($logEntry->getContext());
}
return $logMsg;

return $this->filterMessage($logMsg);
}

/**
Expand Down Expand Up @@ -127,4 +150,78 @@ protected function validateNotEmpty($name, $value)
return $result;
}

/**
* Filter log message
*
* @param LogMsg $logMsg Log message instance
*
* @return LogMsg
*/
protected function filterMessage(LogMsg $logMsg)
{
if (count($this->logMessageFilters)) {
foreach ($this->logMessageFilters as $filterable) {
$logMsg = $filterable->filter($logMsg);
}
}

return $logMsg;
}

/**
* Add log message filter
*
* @param string $filterClass Filter class string
*
* @return void
*/
protected function addLogMessageFilter($filterClass)
{
if (!is_string($filterClass)) {
return;
}

if (!class_exists($filterClass)) {
return;
}

if (!is_subclass_of($filterClass, LogMsgFilterable::class)) {
return;
}

$this->logMessageFilters[$filterClass] = new $filterClass();
}

/**
* Add log message filters from config
*
* @return void
*/
public function addLogMessageFiltersFromConfig()
{
if (!$this->agentConfig) {
return;
}

$configLogMessageFilters = $this->agentConfig->getLogMessageFilters();
if ($configLogMessageFilters && count($configLogMessageFilters)) {
foreach ($configLogMessageFilters as $filterClass) {
$this->addLogMessageFilter($filterClass);
}
}

if ($this->agentConfig->isMaskErrorStackTraceArguments()) {
$this->addLogMessageFilter(ErrorStackTraceMaskFilter::class);
}
}

/**
* Get log message filters
*
* @return LogMsgFilterable[]
*/
public function getLogMessageFilters()
{
return $this->logMessageFilters;
}
}
37 changes: 36 additions & 1 deletion src/Stackify/Log/Entities/Api/LogMsg.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,40 @@ public function setError(StackifyError $error)
}
}
}


/**
* Get log message
*
* @return string
*/
public function getMessage()
{
return $this->Msg;
}

/**
* Set log message
*
* @param string $message New log message
*
* @return void
*/
public function setMessage($message)
{
if (!is_string($message)) {
return;
}

$this->Msg = $message;
}

/**
* Check if log message has error
*
* @return boolean
*/
public function hasError()
{
return $this->Ex && !empty($this->Ex);
}
}
9 changes: 7 additions & 2 deletions src/Stackify/Log/Entities/Api/WebRequestDetail.php
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,12 @@ protected function getRequestUrl()
$https = filter_input(INPUT_SERVER, 'HTTPS');
$ssl = null !== $https && 'off' !== $https;
$protocol = $ssl ? 'https' : 'http';
list($url,) = explode('?', filter_input(INPUT_SERVER, 'REQUEST_URI'));
$inputServerValue = filter_input(INPUT_SERVER, 'REQUEST_URI');
$url = '';
if (is_string($inputServerValue)) {
list($url,) = explode('?', $inputServerValue);
}

$serverName = filter_input(INPUT_SERVER, 'SERVER_NAME');
if ($serverName && $url) {
return "$protocol://$serverName" . $url;
Expand Down Expand Up @@ -359,4 +364,4 @@ protected function getHeaders($blacklist = null, $whitelist = null)
return self::getRequestMap($headers, $blacklist, $whitelist);
}

}
}
12 changes: 12 additions & 0 deletions src/Stackify/Log/Entities/ErrorWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,16 @@ private function getFullPathThatContains($searchPath)
return $result;
}

/**
* Set error message
*
* @param string $message New error message
*
* @return void
*/
public function setMessage($message)
{
$this->message = $message;
}

}
73 changes: 73 additions & 0 deletions src/Stackify/Log/Filters/LogMsg/ErrorStackTraceMaskFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace Stackify\Log\Filters\LogMsg;

use Stackify\Log\Entities\Api\LogMsg;
use Stackify\Log\Filters\LogMsgFilterable;

/**
* Error Mask argument filter
*/
class ErrorStackTraceMaskFilter implements LogMsgFilterable
{
/**
* Allows filtering of log messages before uploading
*
* @param LogMsg $logMsg Log message instance
*
* @return LogMsg
*/
public function filter(LogMsg $logMsg)
{
if (!$logMsg->hasError()) {
return $logMsg;
}

if (stripos($logMsg->getMessage(), "stack trace:\n") === false) {
return $logMsg;
}

$logMsg->setMessage(
$this->mask($logMsg->getMessage())
);

return $logMsg;
}

/**
* Masked php trace
*
* @param string $message Raw message
*
* @return void
*/
protected function mask($message)
{
if (!is_string($message)) {
return $message;
}

try {
$delimeter = "\n";
$hasObject = strpos($message, 'Object(') !== false; // Checks if we can detect an object(
$messageParts = explode($delimeter, $message);

$patternObjectString = "/Object\\(([\\\w\\\\]|[^\\)])+\\)/";
$pattern = "/(.*:(?:.*))(\\((?:\\'.*\\'|[\\d]|[\\w]|,|\\s|\\(|\\)|\\\\)+\\))/";
$replacement = '$1()';
$maskedList = array();

foreach ($messageParts as $part) {
$newString = $part;
if ($hasObject) {
$newString = preg_replace($patternObjectString, '', $newString);
}
$maskedList[] = preg_replace($pattern, $replacement, $newString);
}

return implode($delimeter, $maskedList);
} catch (\Exception $ex) {
return $message;
}
}
}
20 changes: 20 additions & 0 deletions src/Stackify/Log/Filters/LogMsgFilterable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Stackify\Log\Filters;

use Stackify\Log\Entities\Api\LogMsg;

/**
* Log message filterable interface
*/
interface LogMsgFilterable
{
/**
* Allows filtering of log messages before uploading
*
* @param LogMsg $logMsg Log message instance
*
* @return LogMsg
*/
public function filter(LogMsg $logMsg);
}
Loading