【Azure Developer】Java代码实现获取Azure 资源的指标数据却报错 "invalid time interval input"

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
MSE Nacos/ZooKeeper 企业版试用,1600元额度,限量50份
简介: 在使用 Java 调用虚拟机 API 获取指标数据时,因本地时区设置非 UTC,导致时间格式解析错误。解决方法是在代码中手动指定时区为 UTC,使用 `ZoneOffset.ofHours(0)` 并结合 `withOffsetSameInstant` 方法进行时区转换,从而避免因时区差异引发的时间格式问题。

问题描述

在使用 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'.

 

 


 


当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!

相关文章
|
29天前
|
缓存 Java 开发者
Java 开发者必看!ArrayList 和 LinkedList 的性能厮杀:选错一次,代码慢成蜗牛
本文深入解析了 Java 中 ArrayList 和 LinkedList 的性能差异,揭示了它们在不同操作下的表现。通过对比随机访问、插入、删除等操作的效率,指出 ArrayList 在多数场景下更高效,而 LinkedList 仅在特定情况下表现优异。文章强调选择合适容器对程序性能的重要性,并提供了实用的选择法则。
102 3
|
2月前
|
人工智能 监控 安全
智慧工地解决方案,java智慧工地程序代码
智慧工地系统融合物联网、AI、大数据等技术,实现对施工现场“人、机、料、法、环”的全面智能监控与管理,提升安全、效率与决策水平。
|
Java 数据安全/隐私保护
Java代码的执行顺序和构造方法
构造方法是类的一种特殊方法,用于初始化新对象。在 Java 中,每个类默认都有一个与类名同名的构造方法,无需返回类型。构造方法不能用 static、final、synchronized、abstract 或 native 修饰。它可以重载,通过不同的参数列表实现多种初始化方式。构造方法在对象实例化时自动调用,若未显式声明,默认提供一个无参构造方法。构造代码块和静态代码块分别用于对象和类的初始化,按特定顺序执行。
114 0
|
Java
Java代码的执行顺序
Java代码的执行顺序
119 1
LearnJava(四) | Java代码块执行顺序测试
最近笔试常常遇到考察Java代码块执行顺序的题目,网上查看博客错漏百出,特地自己测试了一下。 如有错漏,希望路过的大佬指出来,以便我进行更改。   先上代码吧! public class ClassA { private static St...
1006 0
|
Java 机器学习/深度学习
JAVA代码中加了Try...Catch的执行顺序
public static String getString(){ try { //return "a" + 1/0; return "a"; } catch (Exception e) { System.
|
Java
Java基础-代码执行顺序(重要)
Java代码初始化顺序:     1.由 static 关键字修饰的(如:类变量(静态变量)、静态代码块)将在类被初始化创建实例对象之前被初始化,而且是按顺序从上到下依次被执行。静态(类变量、静态代码块)属于类本身,不依赖于类的实例。     2.没有 static 关键字修饰的(如:实例变量(非静态变量)、非静态代码块)初始化实际上是会被提取到类的构造器中被执行的,但是会比类构造器中的代码
2446 1
|
14天前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
48 0