从 EC2 实例记录到 CloudWatch

Logging to CloudWatch from EC2 instances

我的 EC2 服务器目前正在托管一个网站,该网站将每个注册用户的 activity 记录在本地 EC2 实例上他们自己的单独日志文件中,比如 username.log。我正在尝试找出一种方法,使用 PHP SDK 将这些日志事件推送到 CloudWatch,而不会降低应用程序的速度,同时仍然能够为我网站的每个注册会员维护一个单独的日志文件。

我这辈子都想不通:

选项 1:如何使用 CloudWatch SDK 异步 登录到 CloudWatch?我的 PHP 应用程序运行非常缓慢,因为每个日志行需要大约 100 毫秒才能直接推送到 CloudWatch。代码示例如下。

选项 2:或者,我如何在 EC2 上配置已安装的 CloudWatch 代理来简单地观察我的所有日​​志文件,这基本上会在一个单独的进程中为我将它们异步上传到 CloudWatch? CloudWatch EC2 日志记录代理需要您的服务器上的静态 "configuration file" (AWS documentation),据我所知,它需要提前列出所有日志文件 ("log streams"),我在服务器启动时将无法预测。有什么办法解决这个问题(即,只需观察目录中的所有日志文件)?配置文件示例如下。

这里欢迎所有想法,但我不希望我的解决方案只是 "throw all your logs into a single file, so that your log names are always predictable"。

提前致谢!!!


选项 1:通过 SDK 记录(需要 ~100 毫秒/logEvent):

// Configuration to use for the CloudWatch client
$sharedConfig = [
    'region'  => 'us-east-1',
    'version' => 'latest',
    'http'    => [
        'verify' => false
    ]
];

// Create a CloudWatch client
$cwClient = new Aws\CloudWatchLogs\CloudWatchLogsClient($sharedConfig);

// DESCRIBE ANY EXISTING LOG STREAMS / FILES
$create_new_stream = true;
$next_sequence_id = "0";
$result = $cwClient->describeLogStreams([
        'Descending' => true,
        'logGroupName' => 'user_logs',
        'LogStreamNamePrefix' => $stream,
]);
// Iterate through the results, looking for a stream that already exists with the intended name
// This is so that we can get the next sequence id ('uploadSequenceToken'), so we can add a line to an existing log file
foreach ($result->get("logStreams") as $stream_temp) {
    if ($stream_temp['logStreamName'] == $stream) {
        $create_new_stream = false;
        if (array_key_exists('uploadSequenceToken', $stream_temp)) {
            $next_sequence_id = $stream_temp['uploadSequenceToken'];
        }
        break;
    }
}   

// CREATE A NEW LOG STREAM / FILE IF NECESSARY
if ($create_new_stream) { 
    $result = $cwClient->createLogStream([
        'logGroupName' => 'user_logs',
        'logStreamName' => $stream,
    ]);
}

// PUSH A LINE TO THE LOG *** This step ALONE takes 70-100ms!!! ***

$result = $cwClient->putLogEvents([
    'logGroupName' => 'user_logs',
    'logStreamName' => $stream,
    'logEvents' => [
        [
            'timestamp' => round(microtime(true) * 1000),
            'message' => $msg,
        ],
    ],
    'sequenceToken' => $next_sequence_id
]);

选项 2:通过安装的 CloudWatch 代理进行日志记录(请注意,据我所知,下面的配置文件仅允许硬编码的、预先确定的日志名称):

[general]
state_file = /var/awslogs/state/agent-state  

[applog]
file = /var/www/html/logs/applog.log
log_group_name = PP
log_stream_name = applog.log
datetime_format = %Y-%m-%d %H:%M:%S

看来我们现在有一些好消息......不确定是否为时已晚!

CloudWatch Log Configuration

所以要回答这个问题,

Is there any way around this (ie, simply observe ALL log files in a directory)?

是的,我们可以使用通配符提及日志文件和文件路径,这可以帮助您灵活地配置从何处获取日志并将其推送到日志流。