AWS-CloudWatch:InvalidSequenceTokenException

AWS-CloudWatch: InvalidSequenceTokenException

我有一个 php 工作人员,我将事件记录到 AWS 可以观看。 不幸的是,我在尝试提交时遇到了以下错误。

InvalidSequenceTokenException Error executing "PutLogEvents" on "https://logs.eu-west-1.amazonaws.com"; AWS HTTP error: Client error: POST https://logs.eu-west-1.amazonaws.com resulted in a 400 Bad Request response: {"__type":"InvalidSequenceTokenException","expectedSequenceToken":"999999999999990356407851919528174 (truncated...) InvalidSequenceTokenException (client): The given sequenceToken is invalid. The next expected sequenceToken is: 495599999999988500356407851919528174642 - {"__type":"InvalidSequenceTokenException","expectedSequenceToken":"495573099999999900356407851919528174642","message":"The given sequenceToken is invalid. The next expected sequenceToken is: 495579999999900356407851919528174642"}

这是我的代码

 $date = new DateTime();
 $instance= = new CloudWatchLogsClient([
                'region' => 'eu-west-1',
                'version' => 'latest',
                'credentials' => [
                    'key' => 'XXX',
                    'secret' => 'XXXX'
                ]
            ]);
        $instance->putLogEvents([
                'logGroupName' => "WorkerLog",
                'logStreamName' => "log",
                'logEvents' => [
                    [
                        'timestamp' => $date->getTimestamp(),
                        'message' => "test log"
                    ]
                ]
            ]);

http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html

您必须在请求中包含序列标记。如果您没有,则必须使用 describeLogStreams (http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_DescribeLogStreams.html) 来获取流序列。

当您调用 putLogEvents 时,您将在响应中获得 nextToken。您还必须为其他人推送到流并使 nextToken 无效的情况做好准备。 (在这种情况下,您需要再次描述流以获取更新的令牌)。

这是我的工作解决方案:在发送新的 putLogEvents 之前,您必须获取最后一个 uploadSequenceToken。

    try {
        $client = \Aws\CloudWatchLogs\CloudWatchLogsClient::factory($configCloudWatch);

        $logStreamName = 'testLogStream';
        $logGroupName = 'testGroupName';

        $result = $client->describeLogStreams([
            'logGroupName' => $logGroupName,
            'logStreamNamePrefix' => $logStreamName,
        ]);
        $logStreams=$result->get('logStreams');
        if (!$logStreams)
            throw new \Exception('No log stream found');
        if (count($logStreams)!=1)
            throw new \Exception('Multiple log stream found');
        $uploadSequenceToken = $logStreams[0]['uploadSequenceToken'];

        $client->putLogEvents([
            'logGroupName' => $logGroupName,
            'logStreamName' => $logStreamName,
            'logEvents' => [
                [
                    'timestamp' => round(microtime(true) * 1000),
                    // message is required
                    'message' => json_encode([ ... ]
                    ),
                ],
            ],
            'sequenceToken' => $uploadSequenceToken,
        ]);
    } catch (\Exception $e) {
        \Log::error(__METHOD__, ['exception' => $e]);
    }

DescribeLogStreams不支持与PutLogEvent相同的音量调用。频繁调用可能会被限流

推荐的方法是直接调用 PutLogEvents 并捕获 InvalidSequenceTokenException。然后在 InvalidSequenceTokenException 消息中使用 Sequence Token 重试 PutLogEvents

可以在 InvalidSequenceTokenException

expectedSequenceToken 字段中找到正确的序列标记
    try {
        $result = $client->describeLogStreams([
            'logGroupName' => $logGroupName,
            'logStreamNamePrefix' => $logStreamName,
        ]);

        $uploadSequenceToken = $logStreams[0]['uploadSequenceToken'];

        $client->putLogEvents([
            'logGroupName' => $logGroupName,
            'logStreamName' => $logStreamName,
            'logEvents' => [
                [
                    'timestamp' => $timestamp,
                    'message' => $message
                ],
            ],
            'sequenceToken' => $uploadSequenceToken,
        ]);
    } catch (\InvalidSequenceTokenException $e) {
        $client->putLogEvents([
            'logGroupName' => $logGroupName,
            'logStreamName' => $logStreamName,
            'logEvents' => [
                [
                    'timestamp' => $timestamp,
                    'message' => $message
                ],
            ],
            'sequenceToken' => $e->expectedSequenceToken,
        ]);
    }