日志服务数据加工最佳实践: 日期时间处理

本文涉及的产品
对象存储 OSS,20GB 3个月
阿里云盘企业版 CDE,企业版用户数5人 500GB空间
日志服务 SLS,月写入数据量 50GB 1个月
简介: 本文介绍日志服务数据加工最佳实践: 日期时间处理, 覆盖日志互转实践, 时区转换, 日期偏移等

场景1:Unix时间戳、日期时间字符串和日期时间对象的相互转换

LOG DSL语法中的日期时间处理主要涉及三种数据类型:Unix时间戳、日期时间字符串和日期时间对象。它们的相互转换方式如下图:
image

子场景1:日期时间对象和Unix时间戳的相互转换

1)日期时间对象转为Unix时间戳

  • dt_parsetimestamp智能转换函数,可以将日期时间对象或日期时间字符串转化为Unix时间戳。
  • dt_totimestamp,只支持将日期时间对象转化为Unix时间戳。

2)Unix时间戳转为日期时间对象

  • dt_parse智能转换函数,可以将Unix时间戳或日期时间字符串转化为日期时间对象
  • dt_fromtimestamp,只支持将Unix时间戳转化为日期时间对象。

子场景2:日期时间对象和日期时间字符串的相互转换

1)日期时间对象转为日期时间字符串

  • dt_str智能转换函数,可以将日期时间对象、Unix时间戳和日期时间字符串转化为制定格式的日期时间字符串。
  • dt_strftime,只支持将日期时间对象转化为日期时间字符串。

2)日期时间字符串转为日期时间对象

  • dt_parse智能转换函数,可以将日期时间字符串或Unix时间戳转化为日期时间对象。
  • dt_strptime,只支持将日期时间字符串转化为日期时间对象。

子场景3:日期时间字符串和Unix时间戳的相互转换

1)日期时间字符串转为Unix时间戳

  • dt_parsetimestamp智能转换函数,可以将日期时间字符串或日期时间对象转化为Unix时间戳。

2)Unix时间戳转为日期时间字符串

  • dt_str智能转换函数,可以将Unix时间戳、日期时间对象和日期时间字符串转化为制定格式的日期时间字符串。
  • dt_strftimestamp,只支持将Unix时间戳转化为日期时间字符串。

子场景4: 理解dt_parse等智能转换函数的应用场景

上述的转化过程中,大多数转化都有两种方式,一种使用智能转换函数,另一种使用该转换的专用函数。以dt_parse为代表的智能转换函数(参考日期时间函数)可以接受Unix时间戳、日期时间对象以及日期时间字符串等不同类型的参数,实现智能转换,例如:

原始日志1

time1: 1562741899
time2: 2019-07-10 06:58:19

LOG DSL编排

e_set("time3", dt_parse(v("time1"), tz="Asia/Shanghai"))
e_set("time4", dt_parse(v("time2"), tz="Asia/Shanghai")

编排后日志

time1: 1562741899
time2: 2019-07-10 06:58:19
time3: 2019-07-10 06:58:19+08:00
time4: 2019-07-10 06:58:19+08:00

但是有一些场景下,智能转换函数就无法满足用户的需求。如对于用户自定义的特殊日期格式,dt_parse等智能转换函数无法自动解析日志,此时需要使用dt_strptime来进行指定格式的解析。如下:

原始日志2

time1: 2019-07-10 06:58:19
time2: 2019/07/10 06-58-19

LOG DSL编排

e_set("time3", dt_parsetimestamp(v("time1")))
e_set("time4", dt_parsetimestamp(dt_strptime(v("time2"), fmt="%Y/%m/%d %H-%M-%S")))

编排后日志

time1: 2019-07-10 06:58:19
time2: 2019/07/10 06-58-19
time3: 1562741899
time4: 1562741899

结论

  • 智能转换函数可以对不同类型的参数进行自动转换,因此默认推荐使用智能转换函数。
  • 智能转换函数也有缺点,对于一些特殊的用户自定义日期格式,智能转换函数无法自动解析,需要使用dt_strptime来进行解析。

场景2: 理解时区的概念

子场景1: 理解时间字符串的含义

LOG DSL语法中的日期时间字符串主要分为两种形式:

  • 带有时区信息的日期时间字符串,如2019-06-02 18:41:26+08:00
  • 不带时区信息的日期施时间字符串,如2019-06-02 10:41:26

带有时区信息的日期时间字符串通过在日期时间后添加额外的时差信息来表达时区:

  • 2019-06-02 18:41:26+08:00表示该时间是东8区时区下的2019-06-02 18:41:26
  • 2019-06-02 18:41:26-07:00表示该时间是西7区时区下的2019-06-02 18:41:26

对于不带有时区信息的日期时间字符串,如果时区信息不同,该时间字符串表达的时间也不同。如果没有传递时区参数,默认为UTC时区下的时间。以2019-06-02 18:41:26为例:

  • 默认情况下是UTC时区下的时间,即该时间字符串表达的时间是UTC时区下的时间,等价于2019-06-02 18:41:26+00:00
  • 如果交代了时区是东8区,该时间字符串表达的时间是东8区下的时间,等价于2019-06-02 18:41:26+08:00

子场景2: 将日期时间转化为Unix时间戳

不带时区信息的日期时间

对于不带时区信息的日期时间字符串(如'2019-06-02 18:41:26'),将给定日期时间转化为Unix时间戳,需要指定该日期时间是哪个时区下的时间,不同的时区转化得到的Unix时间戳的值是不一样的。

原始日志

{ 'time': '2019-06-02 18:41:26''}

LOG DSL编排

e_set("Shanghai_timestamp", dt_parsetimestamp(v("time"), tz="Asia/Shanghai"))
e_set("Los_Angeles_timestamp", dt_parsetimestamp(v("time"), tz="America/Los_Angeles"))
e_set("UTC_timestamp", dt_parsetimestamp(v("time")))
  • 指定tz="Asia/Shanghai"表示time字段所表达的时间是上海所在时区对应的时间。
  • 如果不指定时区,默认将给定日期时间当做UTC时区下的日期时间。
  • 时区参数tz=时区字符串中所有可选时区字符串的值参考所有时区列表。可使用Ctrl + F搜索目标时区字符串。

加工后日志

{
  'Shanghai_timestamp': '1559472086',
  'Los_Angeles_timestamp': '1559526086',
  'UTC_timestamp': '1559500886'
}

带有时区信息的日期时间

对于带有时区信息的日期时间字符串(如'2019-06-02 18:41:26+08:00'),则无须指定时区参数。

原始日志

{ 'China_time': '2019-06-02 18:41:26+08:00',
  'America_time': '2019-06-02 3:41:26-07:00',
  'UTC_time': '2019-06-02 10:41:26+00:00'
}

LOG DSL编排

e_set("timestamp1", dt_parsetimestamp(v("China_time")))
e_set("timestamp2", dt_parsetimestamp(v("America_time")))
e_set("timestamp3", dt_parsetimestamp(v("UTC_time")))

加工后日志

{
  "timestamp1": "1559472086",
  "timestamp2": "1559472086",
  "timestamp3": "1559472086"
}

子场景3: 不同时区下的日期时间相互转换

不带时区信息的日期时间

对于不带时区信息的日期时间字符串(如'2019-06-02 18:41:26'),可以通过Unix时间戳为媒介,实现不同时区下的日期时间的相互转换。

加工需求

  • 将洛杉矶时区下的日期时间转换为上海时区下的日期时间

原始日志

#已知time字段的值的时间是洛杉矶时间
{'time': '2019-06-04 2:41:26'}

LOG DSL编排

e_set("timestamp", dt_parsetimestamp(v("time"), tz="America/Los_Angeles"))
e_set("Shanghai_time", dt_parse(v("timestamp"), tz="Asia/Shanghai"))

加工后日志

{
  'time': '2019-06-04 2:41:26',
  'Shanghai_time': '2019-06-04 17:41:26+08:00'
}

带有时区信息的日期时间

对于带有时区信息的日期时间字符串(如'2019-06-02 18:41:26+08:00''),可直接通过dt_astimezone实现不同时区下的日期时间的相互转换。

原始日志

{'time': '2019-06-04 2:41:26+08:00'}

LOG DSL编排

e_set("new_time", dt_astimezone(v("time"), tz="America/Los_Angeles"))

加工后日志

{
  'time': '2019-06-04 2:41:26+08:00',
  'new_time': '2019-06-03 11:41:26-07:00'
}

场景3: 理解日期时间和Unix时间戳的应用场景

LOG DSL编排中涉及到的日期时间主要有两种形式Unix时间戳日期时间(字符串或对象)

日期时间

日期时间形式主要是为了便于展示以及提升用户可读性等。

unix_time: 1562741899
date_time: 2019-07-10 06:58:19

Unix时间戳

Unix时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,它的主要应用场景有:

1. 表示系统时间

  • 如日志事件中表示日志产生时间的元字段__time__,表示日志接收时间的字段__receieve_time__等,这些字段的值都使用Unix时间戳来表示对应的系统时间。
__source__:  1.2.3.4
__tag__:__receive_time__:  1562741899
__topic__: 
__time__: 1562731122

2. 便于时间相关的计算。

  • 由于Unix时间戳是从1970年1月1日开始所经过的秒数,因此在很多场景下便于直接进行日期时间相关的计算。

原始日志

time1: 1562741899
time2: 1562731122

LOG DSL编排

e_set("time3", op_sub(v("time1"), v("time2")))

加工后日志

time1: 1562741899
time2: 1562731122
time_diff: 10777

场景4: 使用dt_add做灵活的日期偏移

dt_add函数支持在特定时间粒度上修改(增加、减少、覆盖)日期时间的值。dt_add的参数如下

dt_add(字段名, dt1=None, dt2=None, year(s)=None, month(s)=None, day(s)=None, hour(s)=None, minute(s)=None, second(s)=None, microsecond(s)=None, weeks(s)=None, weekday=None)

子场景1:理解year(s),month(s)区别

  • year(s), month(s),day(s)等参数的后面都带有(s),表示这些参数可以有两种形式,即yearyearsmonthmonths等。
  • yearyears为例,如果参数传递的是year,表示在年份粒度上覆盖为year参数的值;如果传递的是years,表示在年份粒度上增加years参数的值。(可参考下面的例子)

原始日志

"time1": "2019-06-04 2:41:26"

LOG DSL编排1

e_set("time2", dt_add(v("time1"), year=2018))

编排后日志

"time1": "2019-06-04 2:41:26"
"time2": "2018-06-04 02:41:26"

LOG DSL编排2

e_set("time2", dt_add(v("time1"), years=2018))

编排后日志

"time1": "2019-06-04 2:41:26"
"time2": "4037-06-04 02:41:26"

子场景2:理解weekday参数用法

  • weekday参数通常和dt_MO,dt_TU等参数一起使用,表示特定星期几的偏移。具体可参考dt_MO

原始日志

#2019-06-04是周二

"time1": "2019-06-04 2:41:26"

LOG DSL编排

#time1的下一个星期一对应的日期
e_set("nex_Monday", dt_add(v("time1"), weekday=dt_MO(1)))

#time1的上一个星期二对应的日期
e_set("previous_Tuesday", dt_add(v("time1"), weekday=dt_TU(op_neg(1))))

#time1的下下一个星期六对应的日期
e_set("nex_next_Saturday", dt_add(v("time1"), weekday=dt_SA(2)))

#time1的上上一个星期日对应的日期
e_set("previous_previous_Sunday", dt_add(v("time1"), weekday=dt_SU(op_neg(2))))

编排后日志

"time1": "2019-06-04 2:41:26",
"next_Monday": "2019-06-10 02:41:26",
"previous_Tuesday": "2019-06-04 2:41:26",
"next_next_Saturday": "2019-06-15 02:41:26",
"previous_previous_Sunday": "2019-05-26 02:41:26"
  • 需要注意的是,如果time1对应的日期是周二,那么它的上一个周二和下一个周二都是time1本身。

进一步参考

欢迎扫码加入官方钉钉群获得实时更新与阿里云工程师的及时直接的支持:
image

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
15天前
|
XML JSON 监控
告别简陋:Java日志系统的最佳实践
【10月更文挑战第19天】 在Java开发中,`System.out.println()` 是最基本的输出方法,但它在实际项目中往往被认为是不专业和不足够的。本文将探讨为什么在现代Java应用中应该避免使用 `System.out.println()`,并介绍几种更先进的日志解决方案。
40 1
|
1月前
|
数据采集 机器学习/深度学习 存储
使用 Python 清洗日志数据
使用 Python 清洗日志数据
32 2
|
2月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
44 2
|
2月前
|
开发者 Python
基于Python的日志管理与最佳实践
日志是开发和调试过程中的重要工具,然而,如何高效地管理和利用日志常常被忽略。本文通过Python中的logging模块,探讨如何使用日志来进行调试、分析与问题排查,并提出了一些实际应用中的优化建议和最佳实践。
|
2月前
|
SQL 人工智能 运维
在阿里云日志服务轻松落地您的AI模型服务——让您的数据更容易产生洞见和实现价值
您有大量的数据,数据的存储和管理消耗您大量的成本,您知道这些数据隐藏着巨大的价值,但是您总觉得还没有把数据的价值变现出来,对吗?来吧,我们用一系列的案例帮您轻松落地AI模型服务,实现数据价值的变现......
182 3
|
3月前
|
SQL 数据库 Java
Hibernate 日志记录竟藏着这些秘密?快来一探究竟,解锁调试与监控最佳实践
【8月更文挑战第31天】在软件开发中,日志记录对调试和监控至关重要。使用持久化框架 Hibernate 时,合理配置日志可帮助理解其内部机制并优化性能。首先,需选择合适的日志框架,如 Log4j 或 Logback,并配置日志级别;理解 Hibernate 的多级日志,如 DEBUG 和 ERROR,以适应不同开发阶段需求;利用 Hibernate 统计功能监测数据库交互情况;记录自定义日志以跟踪业务逻辑;定期审查和清理日志避免占用过多磁盘空间。综上,有效日志记录能显著提升 Hibernate 应用的性能和稳定性。
49 0
|
3月前
|
数据库 Java 监控
Struts 2 日志管理化身神秘魔法师,洞察应用运行乾坤,演绎奇幻篇章!
【8月更文挑战第31天】在软件开发中,了解应用运行状况至关重要。日志管理作为 Struts 2 应用的关键组件,记录着每个动作和决策,如同监控摄像头,帮助我们迅速定位问题、分析性能和使用情况,为优化提供依据。Struts 2 支持多种日志框架(如 Log4j、Logback),便于配置日志级别、格式和输出位置。通过在 Action 类中添加日志记录,我们能在开发过程中获取详细信息,及时发现并解决问题。合理配置日志不仅有助于调试,还能分析用户行为,提升应用性能和稳定性。
53 0
|
3月前
|
开发者 前端开发 编解码
Vaadin解锁移动适配新境界:一招制胜,让你的应用征服所有屏幕!
【8月更文挑战第31天】在移动互联网时代,跨平台应用开发备受青睐。作为一款基于Java的Web应用框架,Vaadin凭借其组件化设计和强大的服务器端渲染能力,助力开发者轻松构建多设备适应的Web应用。本文探讨Vaadin与移动设备的适配策略,包括响应式布局、CSS媒体查询、TouchKit插件及服务器端优化,帮助开发者打造美观且实用的移动端体验。通过这些工具和策略的应用,可有效应对屏幕尺寸、分辨率及操作系统的多样性挑战,满足广大移动用户的使用需求。
55 0
|
3天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
77 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
30天前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
182 3

相关产品

  • 日志服务