指定 AWS Cloudwatch 日志客户端的凭证

问题描述 投票:0回答:2

您好,我正在尝试在 AWS cloudwatch 中创建我的 java 应用程序代码的异常日志,因为我已使用 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 的凭据吗? 预先感谢

java spring-boot amazon-cloudwatch aws-cloudwatch-log-insights aws-java-sdk-2.x
2个回答
2
投票

从跟踪中我们可以看到此实例中的 sdk 客户端

CloudWatchLogsClient.builder()
无法找到凭据,因此无法构建。
客户端将在以下默认位置

查找凭据

出于多种原因,最好将代码设置为从环境变量中读取凭据。

出现这种情况有很多原因。

AWS 鼓励使用环境变量作为凭证

在某种容器集群(例如 Kubernetes)中运行应用程序的需求日益增长。

在容器化环境中,访问文件系统通常可能会出现问题。

在许多容器工具(例如 docker-compose)中,将环境变量传递到容器很简单。

在链接

默认位置 中,它精确指定了如何为 CloudWatchLogsClient.builder()

 操作提供凭据的选项,并且出于上述原因,建议您采用环境变量解决方案,并且可以使用 `
测试它们是否设置正确

Map<String, String> mapOfEnvironmentVariables = System.getenv();
检索它们。

更新2023年12月20日 更改了“默认位置”的 AWS 文档链接,查找“凭证设置检索顺序”子标题下的第 2 部分


1
投票
下面的代码工作正常,我可以使用 CloudWatchLogsClient 在 cloudwatch 中编写异常,仅供参考,我已附加代码

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(); } }
    
© www.soinside.com 2019 - 2024. All rights reserved.