Укажите учетные данные для AWS Журналы Cloudwatch Client - PullRequest
0 голосов
/ 06 января 2020

Привет! Я пытаюсь создать журналы исключений для моего java кода приложения в AWS cloudwatch, для этого я использовал CloudWatchLogsClient, чтобы поместить в него свои события, но я получаю сообщение об ошибке ниже

DEBUG software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain - Unable to load credentials from SystemPropertyCredentialsProvider(): Unable to load credentials from system settings. Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) or system property (aws.accessKeyId).
software.amazon.awssdk.core.exception.SdkClientException: Unable to load credentials from system settings. Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) or system property (aws.accessKeyId).
    at software.amazon.awssdk.core.exception.SdkClientException$BuilderImpl.build(SdkClientException.java:97)
    at software.amazon.awssdk.auth.credentials.internal.SystemSettingsCredentialsProvider.resolveCredentials(SystemSettingsCredentialsProvider.java:58)
    at software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain.resolveCredentials(AwsCredentialsProviderChain.java:91)
    at software.amazon.awssdk.auth.credentials.internal.LazyAwsCredentialsProvider.resolveCredentials(LazyAwsCredentialsProvider.java:52)
    at software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider.resolveCredentials(DefaultCredentialsProvider.java:100)
    at software.amazon.awssdk.awscore.client.handler.AwsClientHandlerUtils.createExecutionContext(AwsClientHandlerUtils.java:71)
    at software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler.createExecutionContext(AwsSyncClientHandler.java:68)
    at software.amazon.awssdk.core.client.handler.BaseSyncClientHandler.execute(BaseSyncClientHandler.java:68)
    at software.amazon.awssdk.core.client.handler.SdkSyncClientHandler.execute(SdkSyncClientHandler.java:44)
    at software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler.execute(AwsSyncClientHandler.java:55)
    at software.amazon.awssdk.services.cloudwatchlogs.DefaultCloudWatchLogsClient.describeLogStreams(DefaultCloudWatchLogsClient.java:1168)
    at com.WorkingwithS3.WorkingwithS3.PutLogEvents.main(PutLogEvents.java:58)

Вот мой пример кода

package com.WorkingwithS3.WorkingwithS3;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClient;
import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClientBuilder;
import software.amazon.awssdk.services.cloudwatchlogs.model.DescribeLogStreamsRequest;
import software.amazon.awssdk.services.cloudwatchlogs.model.DescribeLogStreamsResponse;
import software.amazon.awssdk.services.cloudwatchlogs.model.InputLogEvent;
import software.amazon.awssdk.services.cloudwatchlogs.model.PutLogEventsRequest;

import java.util.Arrays;
// snippet-end:[cloudwatch.java2.put_log_events.import]

/**
 * Puts a sample CloudWatch log event
 */
public class PutLogEvents {
    public static void main(String[] args) {
        BasicAWSCredentials creds = new BasicAWSCredentials("xxxx",
                "xxxxx");

//        BasicAWSCredentials creds = new BasicAWSCredentials("xxxxxxxx",
//                "xxxx");

        String regionId = "xxx";
        String logGroupName = "xxxx";
        String streamName = "xxxxx";


        // snippet-start:[cloudwatch.java2.put_log_events.main]

        CloudWatchLogsClient logsClient = CloudWatchLogsClient.builder().region(Region.of(regionId)).build();

        // A sequence token is required to put a log event in an existing stream.
        // Look up the stream to find its sequence token.

        // First describe all streams in the log group.
        DescribeLogStreamsRequest logStreamRequest = DescribeLogStreamsRequest.builder()
                .logGroupName(logGroupName)
                .logStreamNamePrefix(streamName)
                .build();
        DescribeLogStreamsResponse describeLogStreamsResponse = logsClient.describeLogStreams(logStreamRequest);

        // Assume that a single stream is returned since a specific stream name was specified in the previous request.
        String sequenceToken = describeLogStreamsResponse.logStreams().get(0).uploadSequenceToken();

        // Build an input log message to put to CloudWatch.
        InputLogEvent inputLogEvent = InputLogEvent.builder()
                .message("{ \"key1\": \"value1\", \"key2\": \"value2\" }")
                .timestamp(System.currentTimeMillis())
                .build();

        // Specify the request parameters.
        PutLogEventsRequest putLogEventsRequest = PutLogEventsRequest.builder()
                .logEvents(Arrays.asList(inputLogEvent))
                .logGroupName(logGroupName)
                .logStreamName(streamName)
                // Sequence token is required so that the log can be written to the
                // latest location in the stream.
                .sequenceToken(sequenceToken)
                .build();
        logsClient.putLogEvents(putLogEventsRequest);
        // snippet-end:[cloudwatch.java2.put_log_events.main]

        System.out.println("Successfully put CloudWatch log event");
    }
}

Может кто-нибудь подсказать, как указать учетные данные для CloudWatchLogsClient? Заранее спасибо

Ответы [ 2 ]

1 голос
/ 07 января 2020

Из трассировки видно, что клиент sdk в этом случае CloudWatchLogsClient.builder() не может найти учетные данные и, следовательно, не может создать.
Клиент будет искать учетные данные в следующих местоположениях по умолчанию

По многим причинам хорошо настроить код для чтения учетных данных из переменных среды.

Это следует по многим причинам.

AWS поощряют использование переменных среды для учетных данных .

Растущая потребность запускать ваше приложение в каком-то кластере контейнеров, например, Kubernetes.

Часто в контейнерной среде доступ к файловой системе может быть проблематичным c.

Во многих инструментах-контейнерах, таких как docker -составьте его тривиально, чтобы передавали переменные окружения в контейнер .

В ссылке местоположения по умолчанию он определяет параметры, как точно указывать учетные данные для операции CloudWatchLogsClient.builder(), и по вышеуказанным причинам предлагает принять решение для переменных среды, и вы можете проверить, что они установлены правильно с помощью `

       Map<String, String> mapOfEnvironmentVariables = System.getenv();

для их получения.

0 голосов
/ 20 января 2020

Ниже кода работает нормально, я могу написать исключение в cloudwatch, используя CloudWatchLogsClient просто для справки, я приложил код

package com.example.DynamoDB;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClient;
import software.amazon.awssdk.services.cloudwatchlogs.model.DescribeLogStreamsRequest;
import software.amazon.awssdk.services.cloudwatchlogs.model.DescribeLogStreamsResponse;
import software.amazon.awssdk.services.cloudwatchlogs.model.InputLogEvent;
import software.amazon.awssdk.services.cloudwatchlogs.model.PutLogEventsRequest;

import java.util.Arrays;

@ControllerAdvice
public class ExceptionControllerAdvice {
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> exceptionHandler(Exception ex) {
        ErrorResponse error = new ErrorResponse();
        error.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
        error.setMessage(ex.getMessage());
        error.setController(ex.getStackTrace()[0].getClassName());
        error.setService(ex.getStackTrace()[0].getClassName());
        error.setTimestamp(System.currentTimeMillis());
        PutLogEvents(error);
        return new ResponseEntity<ErrorResponse>(error, HttpStatus.OK);
    }

    public static void PutLogEvents(ErrorResponse Er)
    {
        String regionId = "us-east-1";
        String logGroupName = "xxxxxxxxx";
        String logStreamName = "xxxxxxxxx";

        CloudWatchLogsClient logsClient = CloudWatchLogsClient.builder().region(Region.of(regionId)).build();

        // A sequence token is required to put a log event in an existing stream.
        // Look up the stream to find its sequence token.
        String sequenceToken = getNextSequenceToken(logsClient, logGroupName, logStreamName);

        // Build a JSON log using the EmbeddedMetricFormat.

        String message = "[{" +
                "  \"Timestamp\": " + Er.getTimestamp()  + "," +
                "  \"ErrorCode\": " + Er.getErrorCode()  + "," +
                "  \"ControllerName\": " + Er.getErrorCode()  + "," +
                "  \"ServiceName\": " + Er.getErrorCode()  + "," +
                "  \"ErrorMsg\": " + Er.getErrorCode()   + "" +
                "}]";
        InputLogEvent inputLogEvent = InputLogEvent.builder()
                .message(message)
                .timestamp(Er.getTimestamp())
                .build();

        // Specify the request parameters.
        PutLogEventsRequest putLogEventsRequest = PutLogEventsRequest.builder()
                .logEvents(Arrays.asList(inputLogEvent))
                .logGroupName(logGroupName)
                .logStreamName(logStreamName)
                // Sequence token is required so that the log can be written to the
                // latest location in the stream.
                .sequenceToken(sequenceToken)
                .build();

        logsClient.putLogEvents(putLogEventsRequest);
    }

    private static String getNextSequenceToken(CloudWatchLogsClient logsClient, String logGroupName, String logStreamName) {
        DescribeLogStreamsRequest logStreamRequest = DescribeLogStreamsRequest.builder()
                .logGroupName(logGroupName)
                .logStreamNamePrefix(logStreamName)
                .build();

        DescribeLogStreamsResponse describeLogStreamsResponse = logsClient.describeLogStreams(logStreamRequest);

        // Assume that a single stream is returned since a specific stream name was
        // specified in the previous request.
        return describeLogStreamsResponse.logStreams().get(0).uploadSequenceToken();
    }

}
...