6

Amazon Cloud Watch サービスを使用して、アプリケーション用の小さなログ トラッカーを構築しています。アイデアは、ファイルのログ出力を追跡し、aws コンソールから検索エンジンを使用してログ情報を見つけることではありません。

私は使っている:

  • IDEとしてのEclipse
  • Java 8
  • 依存関係: aws-java-sdk-core / aws-java-sdk-cloudwatch V 1.10.49

一方、次の AWS 構成があります。

  • アクセスと秘密鍵
  • 地域 : カリフォルニア
  • ロググループ: demo1
  • ログストリーム: stream1

簡単な機能テストを行うために、次のコードを書いていました。

package com.test.pe.cloudwatch;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.logs.AWSLogsClient;
import com.amazonaws.services.logs.model.InputLogEvent;
import com.amazonaws.services.logs.model.PutLogEventsRequest;
import com.amazonaws.services.logs.model.PutLogEventsResult;
import com.test.pe.base.CredentialBuilder; 

public class RegisterLog {
    private static String LOG_GROUP = "demo1";
    private static String LOG_STREAM = "stream1";

    public static void main(String[] args) throws ParseException {
        // building my credential and calendar instances
        AWSCredentials credential = CredentialBuilder.getCredential();
        Calendar calendar = Calendar.getInstance();
        // building a cloud watch log client
        AWSLogsClient cloudWatchlog = new AWSLogsClient(credential);
        cloudWatchlog.setRegion(Region.getRegion(Regions.US_WEST_1));
        // building a put request log
        PutLogEventsRequest request = new PutLogEventsRequest();
        request.setLogGroupName(LOG_GROUP);
        request.setLogStreamName(LOG_STREAM);
        // building my log event
        InputLogEvent log = new InputLogEvent();
        log.setMessage("Some message for a test");
        log.setTimestamp(calendar.getTimeInMillis());
        // building the array list log event
        ArrayList<InputLogEvent> logEvents = new ArrayList<InputLogEvent>();
        logEvents.add(log);
        // setting the error array list
        request.setLogEvents(logEvents);
        // make the request
        cloudWatchlog.putLogEvents(request);

        System.out.println("done!");
    }
}

初めてコードを実行すると、すべて問題なく、メッセージが正常に保存されます。

ここに画像の説明を入力

ただし、コードを 2 回目に実行すると、次の例外が発生します。

Exception in thread "main" com.amazonaws.services.logs.model.InvalidSequenceTokenException: The given sequenceToken is invalid. The next expected sequenceToken is: xxxxxxxxxxxxxxxxxxxxxxxxxxx (Service: AWSLogs; Status Code: 400; Error Code: InvalidSequenceTokenException; Request ID: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
    at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1389)

XXXXXXXXXXXX : Amazon によって生成されたトークン コードです。

Amazonのドキュメントを読んで、次の情報を見つけました。

リクエスト構文:

{
    "LogEvents": [
        {
            "Message": "string",
            "Timestamp": number
        }
    ],
    "LogGroupName": "string",
    "LogStreamName": "string",
    "SequenceToken": "string"
}

SequenceToken

A string token that must be obtained from the response of the previous PutLogEvents request.

Type: String

Length constraints: Minimum length of 1.

Required: No

クラウド ウォッチ ログ REST API に関する amazon ドキュメント

そして、次のようにコードにシーケンス トークンをハードコーディングすることにしました。

request.setSequenceToken("58523.......");

それは正常に動作します。そして、私はただテストのためにそれを作りました。

最後に、シーケンス トークンを取得する唯一の方法は次のとおりでした。

PutLogEventsResult response = cloudWatchlog.putLogEvents(request);
String token = response.getNextSequenceToken();

リクエストを行うにシーケンス コードを検証して取得するにはどうすればよいですか? ドキュメントでそれを見つけることができません。

4

3 に答える 3

5

通常、putLogEvents (getNextSequenceToken) を呼び出すと、nextToken が取得されます。複数のプロデューサーがストリームにプッシュしている場合、それらは競合しており、一度にプッシュできるのはそのうちの 1 つだけです (つまり、トークンを取得し、他の誰かがそれをプッシュした場合、トークンは無効になります)。

これが発生した場合は、ストリームを記述して新しいトークンを取得する必要があります: http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_DescribeLogStreams.html

したがって、パターンは次のとおりです。1) 有効なトークンを持っていないか、トークンをまったく持っていない場合 (開始したばかりの場合)、トークンを見つけるためにストリームを記述します。2) 取得したトークンを使用してプッシュします。プッシュが成功した場合は、トークンを更新します。3) プッシュが成功しなかった場合は、1) に進み、新しいトークンを取得して再試行します。複数のプロデューサーの場合は、複数回 (つまり、ループ) 試行する必要がある場合があります。

于 2016-04-27T21:46:52.110 に答える
3

私は同じ問題を抱えていて、次を使用して解決しました:

String token = logStream.getUploadSequenceToken();

完全なソース コード:

 public CloudWatchHandler(String logGroupName, String logStreamName) {
     credentials = new DefaultAWSCredentialsProviderChain().getCredentials();
     awsLogsClient = new AWSLogsClient(credentials);
     awsLogsClient.setRegion(Region.getRegion(Regions.US_WEST_2));
     this.logGroupName = logGroupName;
     this.logStreamName = logStreamName;
     logStreamsRequest = new DescribeLogStreamsRequest(logGroupName);
     logStreamList = new ArrayList<LogStream>();         
     putLogEventsRequest = new PutLogEventsRequest(); 
     putLogEventsResult = new PutLogEventsResult();

 }

 public void log(String message) {
     logEvents = new ArrayList<InputLogEvent>();
     log = new InputLogEvent();
     calendar = Calendar.getInstance(); 

     log.setTimestamp(calendar.getTimeInMillis());
     log.setMessage(message);
     logEvents.add(log);

     logStreamsRequest.withLimit(5);
     logStreamList= awsLogsClient.describeLogStreams(logStreamsRequest).getLogStreams(); 

     for (LogStream logStream: logStreamList) {
         if (logStream.getLogStreamName().equals(logStreamName))
             token = logStream.getUploadSequenceToken();
     }  

     if (token!=null) {
         putLogEventsRequest.setLogGroupName(logGroupName);
         putLogEventsRequest.setLogStreamName(logStreamName);
         putLogEventsRequest.setLogEvents(logEvents);

         putLogEventsRequest.setSequenceToken(token);
         putLogEventsResult = awsLogsClient.putLogEvents(putLogEventsRequest); 
     }       
 }
于 2016-05-04T15:08:48.477 に答える
1

現在投稿されているコードにはまだいくつかの問題があったため、トラブルシューティングに役立つ実用的なソリューションを追加します。

"logStream.getLogStreamName()"ストリームの名前以上のものを返していたので、を使用してストリームを取得しましたDescribeLogStreamsRequest().withLogGroupName("myCrAzYLogGroup");

//creds
        String awsAccessKey = System.getProperty("AWS_ACCESS_KEY_ID");
        String awsSecretKey = System.getProperty("AWS_SECRET_ACCESS_KEY");
        Calendar calendar = Calendar.getInstance();
        AWSCredentials credential = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
        AWSLogsClient awsLogsClient = new AWSLogsClient(credential);
        awsLogsClient.setRegion(Region.getRegion(Regions.US_WEST_2));

        //only difference in my code (i wanted to point out) is the use of BasicAWSCredentials
        //AWSCredentials credential = CredentialBuilder.getCredential();
        //AWSLogsClient cloudWatchlog = new AWSLogsClient(credential);

        PutLogEventsRequest putLogEventsRequest = new PutLogEventsRequest(); 
        putLogEventsRequest.setLogGroupName("myCrAzYLogGroup");
        putLogEventsRequest.setLogStreamName("myCrAzYLogStream");

        String token = null;
        //here's mainly what I changed 
        DescribeLogStreamsRequest logStreamsRequest = new DescribeLogStreamsRequest().withLogGroupName("myCrAzYLogGroup");
        List<LogStream> logStreamList = new ArrayList<LogStream>();
        logStreamList= awsLogsClient.describeLogStreams(logStreamsRequest).getLogStreams();

        //the answer to this question (get the token and use it)
        //keep in mind I'm not comparing because I only have one stream
        //again this is just to help get started/trouble shoot with a simplified setup
        for (LogStream logStream: logStreamList) {
            token = logStream.getUploadSequenceToken();
        }
        if(token != null)
        {
            putLogEventsRequest.setSequenceToken(token);
        }
        InputLogEvent testEvent = new InputLogEvent();
        testEvent.setMessage("let's test this log!");
        testEvent.setTimestamp(calendar.getTimeInMillis());
        ArrayList<InputLogEvent> logEvents = new ArrayList<InputLogEvent>();
        logEvents.add(testEvent);
        putLogEventsRequest.setLogEvents(logEvents);

        PutLogEventsResult putLogEventsResult = new PutLogEventsResult();
         //this will return the next token if you want to hold onto it
        putLogEventsResult = awsLogsClient.putLogEvents(putLogEventsRequest);
于 2016-05-09T23:36:46.460 に答える