问题描述
在使用 Java 代码调用虚拟机(VM)API获取指标数据时,出现时间格式解析错误。
错误信息:
'{
"code": "BadRequest",
"message": "Detected invalid time interval input: 2024-03-13T13:33:05.123 15:00/2024-03-13T13:48:05.233 15:00, supported Iso 8601 time interval format: (Datetime/Datetime, Datetime/Duration, Duration/Datetime, Duration)"
}'
JAVA 代码:
static void query() { MetricsQueryClient metricsQueryClient = new MetricsQueryClientBuilder() .endpoint("https://management.chinacloudapi.cn") .credential(new DefaultAzureCredentialBuilder().build()) .buildClient(); String resourceId = "<resource id>"; Response<MetricsQueryResult> metricsResponse = metricsQueryClient .queryResourceWithResponse(resourceId, Arrays.asList("CpuTime", "Requests"), new MetricsQueryOptions() .setGranularity(Duration.ofHours(1)) .setTimeInterval(new QueryTimeInterval(OffsetDateTime.now().minusDays(1), OffsetDateTime.now())) .setAggregations(Arrays.asList(AggregationType.AVERAGE, AggregationType.COUNT)), Context.NONE); MetricsQueryResult metricsQueryResult = metricsResponse.getValue(); for (MetricResult metric : metricsQueryResult.getMetrics()) { System.out.println("Metric name " + metric.getMetricName()); for (TimeSeriesElement timeSeriesElement : metric.getTimeSeries()) { System.out.println("Dimensions " + timeSeriesElement.getMetadata()); for (MetricValue metricValue : timeSeriesElement.getValues()) { System.out.println(metricValue.getTimeStamp() + " " + metricValue.getTotal()); } } } }
这个会是什么原因导致的呢?
问题解答
添加日志,对比代码生成的时间格式字符串后,发现问题根源于本地执行环境的时区设置相关!
因为 Java SDK中timespan参数仅支持UTC的ZoneOffset。如果本地环境设置为非UTC的时区,例如:export TZ="/usr/share/zoneinfo/Hongkong" 就可以复现此问题。
鉴于此种情况,如果不修改本地电脑环境的情况下,可以在代码中进行指定时间为UTC时区。
添加代码:ZoneOffset zoneOffsetUTC = ZoneOffset.ofHours(0);, 然后在设置 setTimeInterval 中指定时区 OffsetDateTime.now().withOffsetSameInstant(zoneOffsetUTC)。这样就可以解决时间格式因时区不同而产生的问题!
修改后的代码为:
static void query() { MetricsQueryClient metricsQueryClient = new MetricsQueryClientBuilder() .endpoint("https://management.chinacloudapi.cn") .credential(new DefaultAzureCredentialBuilder().build()) .buildClient(); String resourceId = "<resource id>"; ZoneOffset zoneOffsetUTC = ZoneOffset.ofHours(0); Response<MetricsQueryResult> metricsResponse = metricsQueryClient .queryResourceWithResponse(resourceId, Arrays.asList("CpuTime", "Requests"), new MetricsQueryOptions() .setGranularity(Duration.ofHours(1)) .setTimeInterval(new QueryTimeInterval(OffsetDateTime.now().minusDays(1).withOffsetSameInstant(zoneOffsetUTC), OffsetDateTime.now().withOffsetSameInstant(zoneOffsetUTC))) .setAggregations(Arrays.asList(AggregationType.AVERAGE, AggregationType.COUNT)), Context.NONE); MetricsQueryResult metricsQueryResult = metricsResponse.getValue(); for (MetricResult metric : metricsQueryResult.getMetrics()) { System.out.println("Metric name " + metric.getMetricName()); for (TimeSeriesElement timeSeriesElement : metric.getTimeSeries()) { System.out.println("Dimensions " + timeSeriesElement.getMetadata()); for (MetricValue metricValue : timeSeriesElement.getValues()) { System.out.println(metricValue.getTimeStamp() + " " + metricValue.getTotal()); } } } }
参考资料
Azure Resource Metrics - List :https://learn.microsoft.com/en-us/rest/api/monitor/metrics/list?view=rest-monitor-2023-10-01&tabs=HTTP
timespan :The timespan of the query. It is a string with the following format 'startDateTime_ISO/endDateTime_ISO'.
当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!