Amazon Cloud Watch Log - PutLogEventsRequest - La secuencia dadaToken no es válida

Estoy creando un pequeño rastreador de registros para mi aplicación con el servicio Amazon Cloud Watch. La idea no es rastrear las salidas de registro en los archivos y usar el motor de búsqueda desde la consola de aws para encontrar información de registro.

Estoy usando:

  • Eclipse como IDE
  • Java 8
  • Dependencias: aws-java-sdk-core / aws-java-sdk-cloudwatch V 1.10.49

Por otro lado, tengo la siguiente configuración de AWS:

  • Acceso y claves privadas
  • Región: California
  • Grupo de registro: demo1
  • Secuencia de registro: stream1

Estaba escribiendo el siguiente código para hacer una prueba funcional simple:

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

Cuando ejecuto el código por primera vez, todo está bien, el mensaje se guarda correctamente.

ingrese la descripción de la imagen aquí

Sin embargo, cuando ejecuto el código por segunda vez, aparece la siguiente excepción:

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: son códigos de token generados por Amazon.

Leyendo la documentación de Amazon y encontré la siguiente información:

Solicitar sintaxis:

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

Secuencia Tomada

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

documentación de Amazon sobre API REST de registro de observación en la nube

Y decidí codificar el token de secuencia en mi código de la siguiente manera:

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

Funciona bien. Y lo hice solo para prueba.

Finalmente, la única forma en que encontré para obtener el token de secuencia fue.

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

¿Cómo puedo validar y obtener el código de secuencia antes de hacer una solicitud? No puedo encontrar eso en la documentación.

Respuesta 1

Normalmente obtienes el nextToken cuando haces una llamada a putLogEvents (getNextSequenceToken). Si hay más de un productor empujando a la transmisión, están compitiendo y solo uno de ellos puede empujar a la vez (es decir: si obtienes un token y alguien más lo empuja, invalida tu token).

Si esto sucede, debe describir la transmisión y obtener un nuevo token: http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_DescribeLogStreams.html

Entonces, el patrón es: 1) Si no tiene un token válido o no tiene un token (está comenzando) describa la secuencia para descubrir el token. 2) Presione usando el token que tiene. Si el envío es exitoso, actualice el token 3) Si el envío no es exitoso, vaya a 1), obtenga un nuevo token e intente nuevamente. Es posible que deba probar varias veces (es decir, bucle) si hay varios productores.

Respuesta: 2

Tuve el mismo problema y lo resolví usando:

String token = logStream.getUploadSequenceToken();

El código fuente completo:

 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); 
     }       
 }
Respuesta: 3

Estoy usando Spring 3 e Hibernate 4 JPA. Estoy confundido con respecto a javax.persistence JAR. Encontré a continuación dos dependencias de Maven en Google. ¿Dime cuál se requiere en las dos dependencias siguientes? ...

Tengo Map <Integer, Integer> pickupMap = new HashMap <Integer, Integer> (); Mapa como este. Había insertado valores como este if (null! = Qty_1000 &&! "". Equals (qty_1000)) ...

Tengo algunos JSON extraños como: [{"type": "0", "value": "my string"}, {"type": "1", "value": 42}, {"type": "2 "," value ": {}}] Basado en algún campo, el objeto ...

Estoy confundido con el polimorfismo y me pregunto si esto se considera polimorfismo. Siento que se ve un poco raro, pero aún se compila correctamente. Familia de clase pública {void FamilyInfo () {...