加入我们,于10月8-10日参加纽约市的会议,了解关于 GraphQL 联邦和 API 平台工程的最新技巧、趋势和新闻。参加2024年纽约市 GraphQL 大会
文档
免费开始

操作签名

了解 GraphOS 如何识别等效操作


当您查看您的's 操作指标基于它们包含的,而不是基于。这意味着具有相同名称但不同字段集的操作将分别显示:

Separate operations with same name in Studio

尽管上述示例中的每个都被称为MyQuery将它们视为不同的操作,因为它们请求不同的字段

为了帮助识别功能上相同的操作,您的为每个报告给 Studio 的operation signature生成一个操作签名。这是一个具有确定性的顺序、空白和行内值的标准化表示。

为什么我们需要操作签名?

考虑到以下操作:

query GetPostDetails($postId: String!) {
post(id: $postId) {
author
content
}
}
query GetPostDetails($postId: String!) {
post(id: $postId) {
content # Different field order
author
}
}
query GetPostDetails($postId: String!) {
post(id: $postId) {
writer: author # Field alias
content
}
}

尽管有些外观上的差异(包括注释),但这些操作在特定上执行方式相同。因此,Studio 应该在显示性能指标时将它们分组。

尽管有些外观上的差异(包括注释),但这些操作在特定上执行方式相同。因此,Studio 应该在显示性能指标时将它们分组。签名算法

签名算法

注意

此签名算法可能会有所更改。这里提供它是为了信息目的,而不是作为一个规范性规范。

您可以跳转到示例查看源代码

签名算法对一个操作执行以下修改以生成其签名:

  1. 转换行内参数的值。
  2. 移除多余的字符。
  3. 重新排序定义。

1. 转换行内参数值

如果一个操作包含任何行内参数的值,算法会根据它们的类型来转换这些值:

  • 布尔值枚举值被保留。
  • 整数浮点数值被替换为0
  • 字符串、列表和对象值被替换为其“空”对应物(""[]{})。

作为 名称被保留。

注意

使用的组织可以启用增强的操作签名生成。增强的操作签名包括输入对象形状,同时仍然隐藏实际值。有关更多信息,请查看路由器配置页面

2. 移除多余的字符

算法移除了操作定义中的大多数不必要字符,包括注释和多余的空白。

如果一个操作文档包含多个操作,那么除了执行操作之外的操作都会被移除。

如果一个操作文档包含未由执行操作使用的,则这些片段将被移除(保留其他片段)。

3. 重新排序定义

任何保留的定义首先出现,按片段名称进行字母数字排序。执行操作的定义随后出现在所有片段定义之后。

注意

如果有两个排序项的名称相同,算法将保留这些项相对于彼此的原始顺序。

字段

对于给定的对象或片段的字段,字段选择按以下顺序排序:

  1. 单独列出的字段
  2. 命名片段扩展
  3. 内联片段

在这些之中,根据字段名称或片段名称进行字母数字排序。

字段别名

删除所有字段别名。如果一个操作包含相同字段的不同别名的三个实例,则该字段以非别名的名称在签名中列出三次。

注意

使用GraphOS Router的组织可以启用不删除字段别名的增强操作签名生成。有关更多信息,请参阅路由器配置页面

指令和参数

如果在操作文档的同一位置应用了多个指令,则这些指令按字母顺序排序。

如果一个字段接受多个参数,则这些参数按名称进行字母数字排序。

示例签名

考虑这个操作:

# Operation definition needs to appear after all fragment definitions
query GetUser {
user(id: "hello") {
# Replace string argument value with empty string
...NameParts # Spread fragment needs to appear after individual fields
timezone # Needs to appear alphanumerically after `name`
aliased: name # Need to remove alias
}
}
# Excessive characters (including this comment!) need to be removed
fragment NameParts on User {
firstname
lastname
}

签名算法为这个操作生成以下签名:

fragment NameParts on User {
firstname
lastname
}
query GetUser {
user(id: "") {
name
timezone
...NameParts
}
}

签名和敏感数据

签名算法的主要目的是将仅从外观上(如空格、字段顺序、别名等)有所不同的操作分组。作为额外的效果,算法会删除大部分内联参数值,理论上有助于保护数据隐私。

然而,你不应该依赖于这一点。理想情况下,你的敏感数据永远不会首先到达GraphOS Studio。尽可能使用GraphQL变量,而不是内联值作为参数,这有助于你精确控制向Apollo报告哪些值。有关详细信息,请参阅GraphOS Studio数据隐私和合规性

运行时记录签名

GraphOS Router

v1.43.1,路由器在 apollo_operation_signature 关键字处添加 以请求上下文。您还可以使用路由器的本地日志功能将上下文值作为 跟踪属性 录入,或者您可以通过 Rhai 脚本协处理器 读取上下文。

v1.49.0 及以后版本,您可以启用增强 operation signature generation 生成,该生成的包括field 别名。路由器配置页面 以获取更多信息。

Apollo 服务器

要查看您自己日志工具中的操作签名哈希值,您可以创建一个 Apollo 服务器插件,该插件可从共享的 语境 中获取哈希值。相关的值在 queryHashoperationName 属性中可用:

index.ts
const logOperationSignaturePlugin = {
async requestDidStart() {
return {
async didResolveOperation(ctx) {
console.log({
queryHash: ctx.queryHash,
operationName: ctx.operationName,
});
},
};
},
};
const server = new ApolloServer({
schema,
plugins: [logOperationSignaturePlugin],
});
index.js
const logOperationSignaturePlugin = {
async requestDidStart() {
return {
async didResolveOperation(ctx) {
console.log({
queryHash: ctx.queryHash,
operationName: ctx.operationName,
});
},
};
},
};
const server = new ApolloServer({
schema,
plugins: [logOperationSignaturePlugin],
});
上一页
将指标发送到 GraphOS
下一页
Datadog 中继
评价此文评价在 GitHub 上编辑编辑论坛Discord

版权所有2024Apollo Graph Inc.,以 Apollo GraphQL 名称运营。

隐私政策

公司