2016-04-26 23 views
3

Ich baue einen kleinen Protokoll-Tracker für meine Anwendung mit Amazon Cloud Watch-Dienst. Die Idee ist nicht Track-Log-Ausgaben auf Dateien und verwenden Sie die Suchmaschine von AWS-Konsole, um Log-Informationen zu finden.Amazon Cloud Watch-Protokoll - PutLogEventsRequest - Die angegebene SequenzToken ist ungültig

Ich verwende:

  • Eclipse als IDE
  • Java 8
  • Abhängigkeiten: aws-java-sdk-core/aws-java-sdk-Cloudwatch V 1.10.49

In der anderen Seite habe ich folgende AWS-Konfiguration:

  • A ccess und private Schlüssel
  • Region: California
  • Log Gruppe: demo1
  • Log-Stream: stream1

ich den folgenden Code zu schreiben einen einfachen Funktionstest zu machen:

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!"); 
    } 
} 

Wenn ich den Code zum ersten Mal ausführe, ist alles ok, die Nachricht wird erfolgreich gespeichert.

enter image description here

Allerdings, wenn ich den Code für eine zweite Mal, dass ich die folgende Ausnahme erhalten ausführen:

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) 

XXXXXXXXXXX: Sind Token von amazon erzeugten Codes.

Lesen der amazon Dokumentation und ich fand das folgende Info:

anfordern Syntax:

{ 
    "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 

amazon documentation about cloud watch log REST API

und ich beschlossen, hart Code der Sequenz Token auf meinem Code wie folgt:

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

Es funktioniert gut. Und ich habe es nur zum Testen gemacht.

Schließlich war die einzige Möglichkeit, die ich gefunden, um die Sequenz Token zu bekommen war.

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

Wie kann ich überprüfen, und erhalten Sie den Sequenzcode vor eine Anfrage machen ?. Ich kann das auf der Dokumentation nicht finden.

Antwort

2

Normalerweise erhalten Sie das nextToken, wenn Sie einen Aufruf von putLogEvents (getNextSequenceToken) ausführen. Wenn es mehr als einen Produzenten gibt, der an den Stream drängt, konkurrieren sie und nur einer von ihnen kann zu einem Zeitpunkt pushen (dh wenn du einen Token bekommst und jemand anderer ihn schubst, wird dein Token ungültig).

In diesem Fall müssen Sie den Strom beschreiben und ein neues Token erhalten: http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_DescribeLogStreams.html

So ist das Muster: 1) Wenn Sie nicht über ein gültiges Token oder verfügen nicht über ein Token überhaupt (Sie beginnen gerade) beschreiben Sie den Stream, um das Token herauszufinden. 2) Drücken Sie mit dem Token Sie haben. Wenn der Push erfolgreich ist, aktualisieren Sie das Token 3) Wenn der Push nicht erfolgreich ist, gehen Sie zu 1), erhalten Sie ein neues Token und versuchen Sie es erneut. Sie müssen möglicherweise mehrmals (dh Schleife) versuchen, wenn mehrere Produzenten.

2

hatte ich das gleiche Problem und löste es mit:

String token = logStream.getUploadSequenceToken(); 

Der vollständige Quellcode:

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); 
    }  
} 
+0

ist es auch ein guter Weg – afym

0

ich mit dem Code einige Probleme noch hatte zur Zeit geschrieben, damit ich meine Arbeits hinzufügen Lösung zur Fehlersuche:

"logStream.getLogStreamName()" lieferte mehr als nur den Namen des Streams, also habe ich den Stream mit der 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);