调试样本在红色 drop 截止标记处终止;请求样本经过 labeldrop 后删除构建标签并保留数值 42;独立的 up 路径保持不变。

样本重新标记在入库前过滤指标

Prometheus 存在多个重新标记阶段,相似语法容易遮住不同作用。目标重新标记在采集之前处理发现目标,样本重新标记则在抓取之后、入库之前处理采集样本。前一个阶段的 drop 可以让某个端点不被抓取,后一个阶段的相同动作则从已经获取的响应中丢弃匹配样本。首先确定阶段,才能判断配置到底改变了哪一部分观测。 样本重新标记在抓取之后、入库之前处理样本。原文样例区分 drop、labeldrop 与自动生成的 up,且剩余请求身份已经唯一。本图没有重跑集成,也不证明生产迁移不会发生冲突。 先决定删除数据,还是删除标签 在 metric_relabel_configs 中,action: drop 匹配组合后的源标签值,并丢弃匹配样本。使用 __name__ 作为输入时,可以拒绝指定指标族。它不是删除这个源标签却保留样本的意思。如果对一个广泛存在的值使用过宽条件,可能丢掉远超预期的数据,所以不能仅凭动作名称中有“删除”就认为它只影响元数据。 action: labeldrop 则把正则表达式用于标签名称,从保留样本中移除匹配标签;labelkeep 只保留名称匹配的标签。两者都不会求和或生成汇总。前一类操作删除观测,后一类操作改变身份,应该按照预期数据契约选择,而不是把名称相近的动作当成可互换参数。留下数值但删掉维度,也可能比直接过滤一部分样本带来更隐蔽的问题。 重新标记表达式默认在两端锚定。替换或过滤规则需要在对应阶段使用正确的源标签与模式。发现元数据通常属于目标阶段,到样本处理阶段时,已不能继续期待使用 __meta_ 输入。需要保留的上下文应提前复制到普通目标标签,而不是假定每个导出指标都会携带内部发现字段。配置语法相同,不代表输入集合也相同。 删除维度之后仍须保持唯一身份 时间序列由指标名和完整标签集合识别。移除区分两条观测的标签,可能让它们身份重叠,产生重复样本冲突或丢失区别。Prometheus 不会自动推断这些数值该求和、取平均还是任选其一。如果真正需要服务总量,应优先采用受控维度的仪表化以及明确查询聚合,而不是把标签删除当成自动汇总机制。 ...

八月 4, 2027 · 2 分钟 · XB Field Notes
四个成员圆点位于三个分组边界内:结算服务的两个 QueueHigh 实例、结算服务的一个 DiskFull 实例,以及搜索服务的一个 QueueHigh 实例。共享分组仍保留不同实例标签。

Alertmanager 分组组织告警,静默抑制通知

一个事故可能产生很多告警,但一组告警并不能证明它们具有同一个原因。Alertmanager 根据配置的标签与路由上下文组织告警,便于一起处理通知,组内仍然保留各条告警的独立身份。静默则是另一种操作:在指定时间窗口内抑制匹配通知,并不会替应用解决故障。理解这些差异,才能准确解释告警页面与通知数量的变化。 原文接口样例预期得到三个组、四条可见告警,结算静默匹配其中三条。本轮绘图没有重跑该实验,图示是原文预期。历史实验仍受阻,未证明计时精度、抑制规则或下游送达。 分组键决定哪些细节放在一起 配置 group_by: [alertname, service] 时,两条属于结算服务的 QueueHigh 告警可以进入同组,即使实例标签不同。搜索服务的 QueueHigh 属于另一组,结算服务的 DiskFull 也因为告警名不同而单独成组。分组依据被选择的标签值,不要求所有成员具有完全相同的指纹。通知被合并后,实例级细节仍然可以从成员列表查看。 把实例加入分组键会增加组数,也可能抵消跨副本合并的目的;省略服务又可能把不同负责人或工作负载混在一起。应围绕排查方式和责任归属选择分组键,同时保留查看成员的入口。特殊值 ... 表示使用所有标签分组,实际效果接近关闭更大范围的聚合,不能把它当作自动寻找合理分组方式的通配符。 路由上下文同样重要。发往不同接收器的告警,即使所选分组标签相同,也不一定组成同一份通知。应验证路由与分组的组合行为。负责整个服务的接收器可能适合合并多个实例,另一个集成则可能需要不同分组契约。任何一种设置都不会自动证明这些告警具有相同根因,因果关系仍然需要从事件与运行证据判断。 初次等待、组内变化和重复提醒使用不同计时 group_wait 延迟新组的第一份通知,让相近时间到来的告警可以加入。某条告警若在初次等待结束前已经恢复,可能完全不产生通知。group_interval 决定之后检查组内更新的节奏,包括新增触发成员或恢复成员;它不是承诺每隔这么久无条件重发所有尚未结束的组。是否向接收端发送恢复通知,还取决于具体集成的 send_resolved 设置,不同集成的默认值并不相同。 没有新增触发或恢复的告警身份需要更新时,repeat_interval 控制重复提醒;单独改变注解文字并不一定触发新通知。是否到达重复时机是在组周期上检查的,因此应选择兼容的整数倍,而不是把它理解为完全独立且精确的闹钟。发送处理与失败还可能增加延迟。应依据响应目标设置这些参数,并将规则等待时长与通知调度分别考虑,避免只看其中一个参数就承诺发现到送达的时间。 通知历史同样存在保留边界。如果 repeat_interval 超过 Alertmanager 的数据保留时间,文档说明可能按保留边界重复发送。因此,把提醒间隔设置得很长,不保证这段时间里绝无重复消息。通知日志的保留期限,与具有明确结束时间的静默,是不同生命周期,应分别纳入运行检查。 ...

七月 27, 2027 · 3 分钟 · XB Field Notes
带有一个已有 cluster 标签的本地序列跨过对外通信边界。同一个 cluster 标签保留在输出序列中,同时补入两个用不同颜色表示的缺失标签。

外部标签标识 Prometheus 对外发送的数据

多个 Prometheus 向同一系统提供数据时,下游需要知道信息来自哪个采集器或环境。全局 external_labels 可以在与外部系统通信时补充这些上下文。但它不会重写每条本地存储序列,也不会覆盖对外序列中已经存在的同名标签。理解这两条边界,才能避免用错误的查询位置判断配置是否生效,也能避免误以为全局值一定压过目标值。 外部标签在相关对外边界补充缺少的名称,不重写本地存储序列,也不替换已有值。具体标签值来自源端联邦样例。历史集成执行缺口保持不变,本轮绘图不构成新的联邦、远端写入、告警送达或去重验证。 本地存储与对外身份并不相同 本地查询 up 通常看到抓取和重新标记产生的标签,外部标签 prom_region 并不一定出现。它没有出现在本地查询中,不能证明配置失败。应将适当的对外接口与本地结果比较;联邦接口提供了一种直接观察差异的方法,无需为了验证这个行为先接入远端存储系统。检查位置必须与希望验证的机制对应。 配置契约也涉及远端存储和告警等外部通信,但各条下游路径还可能有自己的重新标记与处理步骤。验证某条路径时,需要观察它实际到达的消费者。本地评估的记录规则不会因为保存了一条新序列,就自动获得所有外部标签。外部标签在相关通信边界补充,不是统一改写所有本地查询结果的机制。 序列已有的标签优先 如果目标序列已经具有 cluster="target-cluster",全局外部标签配置为 cluster="collector-cluster",不会把目标值替换掉。外部标签补充的是缺少的标签名称。这是已定义的行为,不能编造成新版本遇到冲突必定拒绝或记录错误。因此,本地指标对外导出时保留的集群值,可能不同于操作人员以为全局配置会强制设置的值。 需要区分目标身份与采集器身份时,应约定独立的采集器标签名,并检查导出器和重新标记规则是否与之冲突。联邦场景中,目标端的 honor_labels 还决定如何处理源标签与本端抓取标签的冲突。这个接收端行为,与源端如何向联邦响应补充外部标签是两件事,不能因为一侧正确便跳过另一侧检查。 稳定标签不会自动实现去重 改变全局标签值,会改变之后导出序列的身份。已经保存在下游的历史仍在旧标签下,不会被重写。修改选择器和面板时,应考虑这条历史边界。添加很多标签也不必然有益:固定标签提供上下文,不同采集器的不同取值则增加消费者需要处理的身份区别,应根据实际查询需求决定,而不是把能写的字段都写进去。 两个采集器抓取相同目标时,可能在不同副本标签下导出重复观测。直接跨副本求和,会让流量看起来翻倍。外部标签让这些副本可以被区分,却不会替下游配置高可用去重。标签也不是租户授权边界;如果存在隔离要求,应核对存储系统真实的权限和查询行为,不能仅依赖名称看起来来自不同环境。 告警重新标记发生在补充外部标签之后。因此,高可用采集器可以在发送等价告警前仅去掉副本区分字段,同时为需要它的存储链路保留该指标标签。仍须核对最终告警标签确实等价,不能把真正区分责任或环境的字段也删掉。度量副本去重与告警身份归一化属于不同路径,需要分别验收。 坏掉的样子 团队可能在本地查询中寻找外部标签,找不到便反复修改本来有效的配置。相反,也可能看到联邦输出带有预期标签,就认为远端写入和告警路由都已验证。应检查具体路径和最终标签,包括下游重新标记的影响,而不是把一个接口的结果当成全部集成已经成功的证据。目标标签与全局值相同的测试,还会掩盖真正的冲突优先级。 ...

六月 9, 2027 · 2 分钟 · XB Field Notes
短批任务把指标推送给 Pushgateway,Prometheus 则独立发起抓取。任务结束后数据托盘仍保留,需要主动清理,不会自动过期。

Pushgateway 保留批任务指标,直到生命周期被主动处理

短生命周期任务可能在 Prometheus 下一次抓取之前就结束。Pushgateway 提供中间层,保留任务推送的指标以供后续抓取,但它不是每个短进程的默认方案。Prometheus 主要建议把它用于适当的服务级批任务结果。保留数据的生命周期与任务自身独立,因此抓取成功不能证明任务最近运行过,也不能证明业务工作已经成功完成。 Pushgateway 指标生命周期独立于任务。稳定分组键控制额外分组,却不建立并发运行顺序;负责人仍须处理替换、新鲜度和精确分组删除。原文未改动的 HTTP 实验仍受阻,本轮绘图未执行。 为稳定的批任务结果建立身份 夜间对账这样的服务级任务,可以把最近结果发布到稳定分组键下。如果把新的运行编号、时间戳或机器身份放进键中,每次运行都可能创建额外分组,而不是更新同一份结果。Pushgateway 没有自动清理旧分组的过期时间机制,负责人需要明确替换或删除相关数据,不能假定退出任务后数据也会跟着消失。 与具体机器相关的批任务,往往可以使用节点导出器的文本文件采集器。共享网关本身也增加了可用性依赖。它的 up 表示 Prometheus 能否抓取网关,不表示每个原始推送任务都健康。应根据观测事件与清理责任选择采集方式,而不是把推送当成绕过服务发现或网络策略的通用办法。任务语义没有确定时,先增加网关并不会自动解决监控定义。 替换范围由 HTTP 方法决定 URL 路径定义分组键,包括任务名称与其他标签对。HTTP PUT 替换这个精确分组中的指标;POST 则替换本次请求包含的同名指标族,同时保留组内其他指标族。POST 不表示给原值递增,也不是向持久事件日志追加一条记录。如果一次报告把数值从七写成九,结果是九,而不是自动累加成十六。 DELETE 删除 URL 标识的精确分组。仅删除任务名构成的分组键,不会删除所有同时包含该任务名和额外标签的分组。网关文档规定的方法顺序允许后续成功推送排在先前已入队的删除之后,这可以用于验证清理结果。不能只看到删除请求被接受,就认定所有名称相似的序列都已经被处理,尤其不能把分组键误当成标签子集查询。 抓取时间不等于最近成功时间 网关通过 push_time_seconds 导出某组最近成功推送的时间。读取指标端点不会推进这个值。Prometheus 为采集样本赋予抓取时间戳,所以刚刚抓到的样本仍可能描述很久以前的任务结果。如果真正关心任务何时成功完成,应把最近成功时间作为独立的仪表值导出,并按任务计划检查其新鲜度。Prometheus 抓取网关时,应设置 honor_labels: true,保留推送数据中的 job 与 instance;否则发生冲突的值会被改名为 exported_job 与 exported_instance。下方实验并未验证这项抓取配置。 ...

五月 13, 2027 · 3 分钟 · XB Field Notes
接口目标通过 keep 关卡进入抓取,discard 候选目标沿红色分支到达停止栏。选择目标发生在抓取之前。

目标重新标记在抓取前选择目标并整理标签

服务发现产生候选目标及其元数据,目标重新标记在 Prometheus 抓取之前处理这些候选项。它可以保留或过滤目标、改变访问地址,并创建随采集序列一起保存的标签。这与改写单个抓取样本发生在不同阶段。先弄清操作阶段,才能避免本来只想去掉一个指标,却因为配置位置错误而把整个目标从采集范围中移除。 目标重新标记发生在抓取前。本例先保留 role 为 api 的目标,再把文件名捕获值复制到 discovery_file;不匹配目标由 keep 排除,不是被抓取后得到 up=0。图中存储标签来自原文样例,并非本轮 Prometheus 实测。 定义规则前先查看发现输入 发现结果包含 __address__ 等内部标签,以及由具体发现机制提供的 __meta_ 字段。文件发现中的 __meta_filepath 指明目标来自哪个文件。这些元数据在目标重新标记期间可以使用,但内部标签会在该阶段结束后从最终目标标签集中移除。如果后续查询需要某个值,应明确把它复制到普通标签中,不能假定所有发现信息都会自动入库。 ...

四月 6, 2027 · 2 分钟 · XB Field Notes
原文样本出现在第零分钟。第一分钟的失效标记终止即时选择,但旧样本仍可能保留在三分钟范围内。第三分钟范围缺失成立,独立的两分钟等待在第五分钟达到触发。

Prometheus 序列失效与告警等待是不同机制

指标缺失不等于数值为零。Prometheus 会区分具有近期值的序列、已经标记失效的序列,以及找不到可用样本的选择器;告警又在查询结果之上使用自己的评估和等待规则。如果把这些机制统称为一个宽限时间,就可能漏掉被移除的目标,或者没有弄清到底缺少什么数据便宣布服务故障。准确的缺失告警首先需要准确描述观测对象。 图中是原文明示的合成样本,不是所有抓取失败或发现移除场景的统一时间表。第三分钟的 (0m,3m] 范围排除第零分钟样本;for: 2m 属于独立的告警层。历史本地 promtool 证据保持不变。真实采集、预期成员关系和通知送达仍需分别验证。 失效标记不是统一的五分钟计时器 即时选择器通常使用回看范围内最新的合格样本,默认回看范围是五分钟。失效标记会告诉引擎:在标记之后,不再让这条序列出现在即时选择结果中。它不要求旧值再保留五分钟。历史样本仍然存在于存储中,也可能继续参与范围查询;因此,即时查询已经看不到某条序列,与历史窗口里完全没有样本,并不是同一件事。 具体采集路径会影响行为。导出器不再输出某个指标、目标从服务发现消失,以及导出器自己提供样本时间戳,不一定遵循相同的时间过程。显式时间戳和失效跟踪配置也会改变结果。在依据抓取周期推测消失时刻之前,应先确认导出器使用哪条路径。可配置的回看范围本质上是查询选择规则,不是能够统一判定所有服务故障的计时器。 先确定要询问哪一种缺失 absent(selector) 在选择器没有任何元素时返回一;只要仍有匹配数据,即使数值为零,也返回空向量。absent_over_time(selector[3m]) 则询问所选三分钟范围内是否存在样本。失效标记之前的真实样本,可能继续留在这个范围内,使范围缺失表达式保持为空,直到该样本移出窗口。这不是查询互相矛盾,而是问题的时间范围不同。 告警规则的 for 又是一层机制:相关标签集必须在连续的评估中持续由表达式返回,经过等待时长后才进入触发状态。它不会配置序列失效,也不会延长查询回看范围。把三分钟缺失窗口再配上额外等待时间,会进一步延后通知,评估节奏和采集时机也影响最终延迟。选择这些参数时,应从允许的发现时间反推,而不是只把它们当作降噪旋钮。 坏掉的样子 absent(up{job="api"}) 不是抓取失败告警。若已配置目标仍存在,只是 up=0,选择器仍有元素,缺失条件便不成立。与零比较才能检查这个场景。但如果目标彻底从发现清单消失,只检查零又可能在其序列消失之后漏报。对目标是否应当存在有要求时,需要另行监测预期成员关系,不能让一个表达式混合承担所有职责。 宽泛的选择器也不会自动列举所有缺少的成员。一个副本仍有数据时,对整个任务求 absent 仍为空,即使其他几个预期副本已消失。可以匹配明确已知的身份,或者将观测序列与权威清单比较。标签被改名同样可能使旧匹配条件看起来像发生故障,而进程其实正在以新身份正常工作,所以规则与标签变更需要一起审阅。 快速验证 保存为 stale.py,运行 python3 stale.py。环境需要已经安装的 promtool,可以从 PATH 找到,或用 PROMTOOL 指定其可执行文件路径。此前记录的执行使用 Python 3.12.14 与 promtool 3.14.0;本轮文章复核没有重新运行该引擎。真实查询引擎在临时目录中评估合成样本,不启动服务器、监听端口或容器,也不联系外部服务。 ...

二月 3, 2027 · 2 分钟 · XB Field Notes
两个实例的累计桶阶梯先合并为总体阶梯,再估计 p99。合并时保留匹配的 le 桶身份。

Prometheus 直方图保留分桶后的分布信息

延迟平均值可能隐藏一部分特别慢的请求。直方图通过记录落入不同桶的观测数量,保留更多分布信息,但仍然丢弃桶内部的细节。Prometheus 可以从这些计数估计分位数,无需保存每次请求的原始耗时。估计结果取决于桶边界与聚合方式,不能称为完整恢复了原始延迟分布,也不能因为输出包含小数就认为测量具有同样精度。 经典直方图先对每条计数器求速率,再合并兼容桶、保留 le,最后估计分位数。原文合成样例的总体 p99 为 4.94 秒,两秒阈值占比为 50%,平均值为 2.085 秒。正无穷桶返回值不是测得的最大值,也不是阈值保证。本轮绘图没有运行 promtool 或服务器。 经典直方图由多条相关序列组成 经典直方图导出累计的 _bucket 计数器,以及 _count 与 _sum。le 标签表示每个桶包含的上界。一点五秒的观测会增加两秒桶和所有更大的桶,所以这些桶不是互不重叠的区间,不能直接相加得到总请求数。正无穷桶包含全部观测,与总计数对应。一个经典直方图因此不是一条可以单独理解的普通序列。 对于非负延迟观测,分别对总和与总计数应用 rate,可以得到每秒累计的耗时和每秒观测数量;两者相除就是以秒为单位的平均延迟。桶速率则描述选定时间范围内的分布。应该先对各条计数器求速率,再合并实例,这样各序列已经观测到的重置能够独立处理,不会在求和时被另一实例的增长掩盖。 先合并桶,再估计总体分位数 需要整个服务的一个分位数时,应在保留 le 的前提下合并桶速率,再调用 histogram_quantile。查询需要区分服务等维度时,也应保留相应标签。参与合并的桶边界要兼容,事件定义也要一致。如果先把 le 消掉,就丢失了经典分位数函数所需的桶身份,留下的数值无法继续表达累计分布。 ...

一月 6, 2027 · 2 分钟 · XB Field Notes
同一个二百五十毫秒输入分为两条路径。除以一千得到零点二五零秒;只改后缀仍保留数值二百五十,错误地将其解释为秒。上方换算路径与下方仅改名路径明确分开。

把单位写进指标名里

名为 request_duration 的指标会让读者猜测,二百五十究竟表示秒、毫秒还是别的量。面向 Prometheus 的名称,例如 http_request_duration_seconds,能够把单位约定带入查询、记录规则与告警配置。但这个约定必须由正确实现支撑:给毫秒数据的名字加上秒后缀,不会自动改变数值大小,反而可能让监控产生一千倍的误差。名称提供线索,转换逻辑才决定数据是否可信。 图解依据原文的三条十进制定点输入与阈值。历史 promtool 解析及命名检查结果保持不变。名称正确不证明真实埋点正确,应沿采集、导出、查询与显示核对已知输入。 在明确的边界完成换算 每个指标族应只表示一种量和一种单位。Prometheus 建议使用秒、字节等基础单位,并在适用时把单位写为后缀。持续时间与绝对时间戳都可以用秒表示,却不是同一种量,因此不能因为名字都含秒,就把上次成功的时间戳与一次请求的耗时直接相加。帮助文本应写明测量对象、开始结束边界以及含义,让简短名称背后仍有明确的契约。 如果底层库输出毫秒,应在观测或导出边界转换一次,并保留足够精度,避免把很短的耗时截断为零。仪表盘可以按基础单位配置显示,让零点二五秒自动显示为二百五十毫秒,这只改变呈现方式,不改变存储样本。不能仅因为坐标轴显示毫秒,就在记录规则中再做一次换算,否则查询和图表会在不同环节重复缩放。 单位与类型回答不同问题 累计传输字节数通常使用字节加总量后缀,当前内存占用仪表则只使用字节后缀。两者单位相同,但只有前者表示不断累积的工作量,适合计算计数器速率。请求次数按惯例使用总量后缀,无须编造一个物理单位。直方图的桶、总和与计数,还会在耗时指标族名称后加入各自的组件后缀,因此阅读名称时也要识别指标族与导出组件之间的关系。 比例通常表示零到一之间的分数,而百分数使用另一种数值尺度,面板应明确自己期待哪种输入。计数器可以在进程重启时归零,Prometheus 的计数器速率函数会根据观测序列中的下降处理重置,并不要求额外存在创建时间序列。应先分别计算独立计数器的速率,再执行聚合,让各自的重置仍能被识别;不要先把多个实例的累计值混成一条看似连续的曲线。 坏掉的样子 名字正确的指标仍然可能承载错误数值。如果同一个标识下混入秒和毫秒,历史数据已经被污染,修改帮助文字或补一个说明标签不能修复旧样本。单位迁移应被视为契约变化,生产端、查询、告警和仪表盘需要一起核对,历史区间的比较也必须说明边界。旧序列含义不兼容时,可以采用新的指标标识,避免新旧数值被误当成同一种量连续使用。 名称后缀也不会强制执行计数器语义。一个普通运行过程中可以升降的仪表,即使名字带总量后缀,也不适合按累计计数器解释。反过来,已经得到每秒速率后再除以时间窗口,会制造另一种量。这些是维度和测量语义的问题,不能只靠显示格式解决。其他遥测体系可能把单位放在元数据中,应遵循已定义的导出映射,而不是机械重命名所有上游仪器。 快速验证 把代码保存为 units.py,使用 Python 3 执行。程序转换三条人为构造的延迟观测,并输出带帮助文字和类型声明的 Prometheus 文本格式。Decimal 十进制运算使毫秒到秒的换算清楚可见;阈值比较则展示,仅仅改名、却不转换数据的生产端,为什么不能和正确的生产端共用同一条延迟规则。 from decimal import Decimal latency_ms = [Decimal('120'), Decimal('250'), Decimal('630')] latency_seconds = [value / Decimal('1000') for value in latency_ms] threshold_seconds = Decimal('0.300') correct_good = sum(value <= threshold_seconds for value in latency_seconds) rename_only_good = sum(value <= threshold_seconds for value in latency_ms) transferred_bytes = 1024 * 1024 used_ratio = Decimal('25') / Decimal('100') assert correct_good == 2 and rename_only_good == 0 assert sum(latency_seconds) == Decimal('1.000') assert used_ratio == Decimal('0.25') print(f"# within 0.300s: converted={correct_good}/3, rename_only={rename_only_good}/3") print('# HELP demo_last_request_duration_seconds Duration of the most recent completed request.') print('# TYPE demo_last_request_duration_seconds gauge') print(f'demo_last_request_duration_seconds {latency_seconds[-1]:.3f}') print('# HELP demo_transferred_bytes_total Bytes transferred since this process started.') print('# TYPE demo_transferred_bytes_total counter') print(f'demo_transferred_bytes_total {transferred_bytes}') print('# HELP demo_capacity_used_ratio Fraction of configured capacity currently used.') print('# TYPE demo_capacity_used_ratio gauge') print(f'demo_capacity_used_ratio {used_ratio}') 首行注释说明,转换后有三分之二的观测不超过零点三秒,而把毫秒数值直接当成秒时,三条都无法满足阈值。导出的最后请求耗时为零点六三秒,累计字节数为一百零四万八千五百七十六,容量使用比例为零点二五,在百分比界面上对应百分之二十五。三个数分别对应持续时间、累计大小与无量纲比例,不能因为都能画成曲线就混用。 ...

十月 30, 2026 · 1 分钟 · XB Field Notes