为 AWS Cloudwatch 日志客户端指定凭据
Specify credentials to AWS Cloudwatch logs Client
您好,我正在尝试在 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 指定凭据?
提前致谢
从跟踪中我们可以看到此实例中的 sdk 客户端 CloudWatchLogsClient.builder()
无法找到凭据,因此无法构建。
客户端将在以下 defaults locations
中查找凭据
出于很多原因,最好设置代码以从环境变量中读取凭据。
这有很多原因。
AWS 鼓励使用 environment variables for credentials。
越来越需要 运行 您的应用程序在某种容器集群中,例如 Kubernetes。
通常在容器化环境中访问文件系统可能会出现问题。
在许多容器工具中,例如 docker-将其琐碎的内容组合成 pass environment variables to the container。
在 link defaults locations 中,它精确地指定了如何为 CloudWatchLogsClient.builder()
操作提供凭据的选项,并且出于上述原因,建议您采用环境变量解决方案,您可以使用 `
测试它们是否设置正确
Map<String, String> mapOfEnvironmentVariables = System.getenv();
检索它们。
下面的代码工作正常我可以使用 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();
}
}
您好,我正在尝试在 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 指定凭据? 提前致谢
从跟踪中我们可以看到此实例中的 sdk 客户端 CloudWatchLogsClient.builder()
无法找到凭据,因此无法构建。
客户端将在以下 defaults locations
出于很多原因,最好设置代码以从环境变量中读取凭据。
这有很多原因。
AWS 鼓励使用 environment variables for credentials。
越来越需要 运行 您的应用程序在某种容器集群中,例如 Kubernetes。
通常在容器化环境中访问文件系统可能会出现问题。
在许多容器工具中,例如 docker-将其琐碎的内容组合成 pass environment variables to the container。
在 link defaults locations 中,它精确地指定了如何为 CloudWatchLogsClient.builder()
操作提供凭据的选项,并且出于上述原因,建议您采用环境变量解决方案,您可以使用 `
Map<String, String> mapOfEnvironmentVariables = System.getenv();
检索它们。
下面的代码工作正常我可以使用 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();
}
}