在收集数据时,管道的任何地方可能都没有入口点重要,因为入口点是任何数据管道中最上游的位置。我们将入口点定义为来自外部世界的数据进入数据管道的初始接触点。如果你熟悉Docker容器化,可能也会熟悉ENTRYPOINT这个关键字。这是我们在启动容器时所运行的初始命令。同样,软件工程用语中的“入口点”通常是指程序执行时的初始点,例如,主方法。在数据工程中也是如此。
在入口点的数据是最原始的,因为它包含了其所建模的外部世界的所有典型噪声和不规则性。此类数据可能来自应用程序或服务日志、点击流源或实时传感器。你的数据可能是高度异构的——也就是说,它可能是结构化的,也可能是非结构化的,而这可能会导致数据未来在管道中出现问题。
我们收集数据的来源很少由数据工程师决定。在大多数情况下,它们都依赖于某些业务目标或上游工具,例如分析服务或API。数据来源主要分为三种类型,我们将在这里逐一介绍。在设计处理解决方案时,了解每种类型的独特优劣势可能会有所帮助。
应用程序日志是指对某些软件应用程序进行操作时所产生的数据。应用程序可以是面向客户的或内部的,而操作可以是用户发起的,也可以是编程式自动产生的。除了通常带有时间戳的事件描述外,你还可能会发现应用软件产生的错误或警告消息。重要的是,与系统日志可能随着操作系统的启动而记录事件序列不同,应用程序日志中的内容包括什么是由该应用程序的开发人员来决定的。因此,日志可能无法代表应用程序使用的详尽历史记录。尽管如此,它们仍然是许多业务用途的关键数据源。
以下是一些示例,用来说明数据收集的用例:
· 一名用户在网页上花费了10min来阅读博客,单击了博客文本中的三个外部链接,并一直滚动到页面的底部。
· 工程师在云计算服务上创建了一个虚拟机实例。他们选择了具有6个虚拟处理器(virtual Central Processing Unit,vCPU)的实例类型,但该类型在其所在地区不可用,因此他们不得不返回并更改配置。
· 机器学习模型与数据集相匹配。日志记录了不同的训练期、当前的准确性,以及指向外部仪表板的链接,其中绘制了损失的情况。
企业可能会以多种不同格式从各种来源收集应用程序日志。在处理日志数据时需要考虑的一些要素包括:
结构
你可能会使用美国信息交换标准码(American Standard Code for Information Interchange,ASCII)或二进制格式的应用程序日志,因为它们是简单的可序列化文本。这对应用程序日志的结构和长度(以及由此带来的日志文件大小)几乎没有限制。由于应用程序的程序员会决定哪些内容将写入日志,因此它们的结构可能是高度可变的。
时间戳
大多数应用程序日志文本是离散事件,带有描述,由\n字符分隔。如果程序员正确地完成了他们的工作,这些事件将被加上时间戳。与事件描述不同,时间戳应该是高度标准化的,通常采用ISO标准格式(yyyy-mm-ddThh:mm:ss[.mmm])或其他类似的格式。
日志级别
好的应用程序日志会使用级别来大致编码每个事件的日志类型。常用的日志级别包括:INFO(信息):该日志包含的是纯粹的描述性信息;WARN(警告):该日志是应用程序警告,但不是失败错误;ERROR(错误):该日志代表应用程序中的编程故障。
目的
应用程序日志并不会被随意收集。推送这些数据是需要花钱的,所以应当确定日志在某些情况下是有用的才会进行推送。一般来说,你可能出于以下两个原因而收集应用程序日志:
诊断
该请求超时的频率如何?页面加载的速度变慢了吗?我们是否使用了已被弃用的库函数呢?所有这些问题都涉及诊断标准,并通过智能收集和解析日志来回答。如果你出于诊断目的而收集日志数据,那么问题的答案或许能在非常具体的WARN或ERROR级别的日志中找到。此外,你收集的绝大多数内容可能与你现在遇到的特定问题无关。
审计
谁发出了这个请求?发出了多少次?系统是如何响应的?这种行为是否也发生在周末,还是模式有所不同?与诊断日志记录不同,审计日志记录就是记录应用程序中的事件历史。许多INFO级别的日志对于审计来说很有用,审计的力量通常来自应用程序会话的大量聚合。
你自己的应用程序不可能完成所有事情,这就是为什么我们要将某些功能分发给不同的应用程序。执行此操作的标准方法是使用应用程序编程接口(Application Programming Interface,API)。API是两个程序之间的中介,它们需要特定格式的请求才会提供响应,就我们的目的而言,这些响应只是半结构化数据。
除了应用程序日志之外,你还可以存储从API端点提取的数据。这些数据类型的格式有一些重要的差异需要我们关注。在使用API数据时,你需要注意以下几个方面:
结构
API响应对象是可以序列化的对象,例如日志,但它们可以分解为结构化或半结构化格式。我们经常看到的一种对象格式(尤其是在Web API中)是JSON。JSON对象非常灵活,但它们会在一些重要方面受到结构的约束。JSON对象(或文件)中的所有内容要么是键值对,要么是值列表。这和日志数据有很大的不同,因为日志数据可以只是一个文本流。其他API响应类型具有类似的格式,例如HTTP响应规范,如HTTP/1.1,它也可能在HTTP请求或响应正文中包含JSON或XML。
响应代码
由于API请求可能成功也可能失败,因此大多数API规范都有针对不同类型响应的代码。我们最常接触到的是HTTP状态码(200 OK、404 Not Found、500 Internal Server Error),但还有其他的代码标准(例如,可以使用HTTP或其他传输协议的SOAP API)。这些代码很有意义,例如,HTTP 500响应的比率是服务器是否出现中断的关键指标。如果你想存储API响应数据,则应考虑此类代码可能存在的相应规范。
目的
API用例的数量是非常庞大的,因此我们无法预测一个人可能遇到的所有用例。不过API的使用方式多种多样,具体的使用细节将影响所存储数据的含义。例如,HTTP响应通常包括响应码、一些键值对信息,有时还包括一个很长的“主体”,即请求的内容。如果我们对服务器错误率感兴趣的话,应该从根本上关心响应码。相反,如果我们只是通过API从外部服务器提取数据,则响应码可能无关紧要,因为我们只想要数据本身。简而言之,用例会影响API响应对象中的哪些信息是有用的,而传输的某些信息在特定环境中可能是无用的。
你可能收集的第三种形式的数据来自传感器,例如物联网设备或研究设备。传感器不一定是应用程序,因为它们的内部逻辑可能非常简单。例如,温度传感器只是通过一些硬件来记录温度并将其发送出去用于收集,这个过程并没有INFO级别日志的一些额外好处。如果你要使用传感器数据,则需要注意以下重要事项:
噪声
从现实世界传感器中收集到的数据可能非常嘈杂,这不一定是收集阶段需要关注的事情。但是,它强调了处理传感器时吞吐量的重要性。简单来说,有些传感器数据可能完全是无用的。下游处理将对传感器数据进行大量异常值去除、平滑和其他转换,因此稳定一致的数据流几乎总是必不可少的。我们将在下一节对下游处理进行讨论。
故障模式
传感器不像应用程序那样智能,这意味着它们可能不会在出现问题时通知你。例如,损坏的温度传感器不会发送“错误:设备离线”这样的信息,而是可能会开始发送疯狂的温度值,或者根本什么也不发送。这使得处理传感器数据比处理应用程序数据更具挑战性。你不能像依赖应用程序一样依赖传感器,你甚至可能需要用更聪明的方式检查接收到的数据数量,或批数据之间的时间差。
目的
与应用程序日志和API响应类似,传感器数据被用于许多下游任务。当前的许多传感器数据都被用于机器学习系统,所以,收集的数据量可能会是一个重要的影响因素。最好的机器学习系统通常会消耗最大的数据集并与其拟合。因此,用于机器学习的传感器数据的吞吐量非常重要。此外,你也要注意传感器数据何时开始被用于基于推理的任务。例如,当家门口有动静时应提醒用户。在这些情况下,缩短延迟应当是最重要的目标。
在正确收集数据后,接下来对其进行清洗。