Skip to main content

哨兵

通过我们的 Sentry 集成,您可以根据您的映射和定义,将 Sentry 云账户中的 "项目 "和 "问题 "导入 Port。

项目 "本质上是一个容器,可容纳与要监控的特定应用程序或服务相关的所有数据和信息。

问题 "是一组描述您症状相应问题的事件。

常见被用于情况

  • 将您监控的项目和问题映射到 Port 中。

先决条件

To install the integration, you need a Kubernetes cluster that the integration's container chart will be deployed to.

Please make sure that you have kubectl and helm installed on your machine, and that your kubectl CLI is connected to the Kubernetes cluster where you plan to install the integration.

安装

从以下安装方法中选择一种:

使用该安装选项意味着集成将能使用 webhook 实时更新 Port。

本表总结了安装时可用的参数,请在下面的脚本中按自己的需要进行设置,然后复制并在终端运行:

ParameterDescriptionRequired
port.clientIdYour port client id
port.clientSecretYour port client secret
port.baseUrlYour port base url, relevant only if not using the default port app
integration.identifierChange the identifier to describe your integration
integration.typeThe integration type
integration.eventListener.typeThe event listener type
integration.secrets.sentryTokenThe Sentry API token
integration.config.sentryHostThe Sentry host. For example https://sentry.io
integration.config.sentryOrganizationThe Sentry organization slug
scheduledResyncIntervalThe number of minutes between each resync
initializePortResourcesDefault true, When set to true the integration will create default blueprints and the port App config Mapping

To install the integration using Helm, run the following command:

helm repo add --force-update port-labs https://port-labs.github.io/helm-charts
helm upgrade --install my-sentry-integration port-labs/port-ocean \
--set port.clientId="PORT_CLIENT_ID" \
--set port.clientSecret="PORT_CLIENT_SECRET" \
--set port.baseUrl="https://api.getport.io" \
--set initializePortResources=true \
--set integration.identifier="my-sentry-integration" \
--set integration.type="sentry" \
--set integration.eventListener.type="POLLING" \
--set integration.config.sentryHost="https://sentry.io" \
--set integration.secrets.sentryToken="string" \
--set integration.config.sentryOrganization="string"

事件监听器

该集成使用轮询方式,每分钟从 Port 中提取一次配置,并检查配置是否有变化。 如果有变化,就会重新同步。

高级集成配置

有关代理或自签名证书等高级配置,click here

接收哨兵对象

Sentry 集成使用 YAML 配置来描述将数据加载到开发者门户的过程。

下面是配置中的一个示例片段,演示了从 Sentry 获取 "Issue "数据的过程:

resources:
- kind: issue
selector:
query: "true"
port:
entity:
mappings:
identifier: ".id"
title: ".title"
blueprint: '"sentryIssue"'
properties:
link: ".permalink"
status: ".status"
isUnhandled: ".isUnhandled"
relations:
project: ".project.slug"

该集成利用JQ JSON processor 对来自 Sentry API 事件的现有字段和值进行选择、修改、连接、转换和其他操作。

配置结构

集成配置决定了将从 Sentry 查询哪些资源,以及将在 Port 中创建哪些实体和属性。

支持的资源 下列资源可被用于来映射来自 Sentry 的数据,可以引用下面链接的 API 响应中出现的任何字段来进行映射配置。
  • 集成配置的根密钥是 "资源 "密钥:

    resources:
    - kind: project
    selector:
    ...
  • 类型 "键是哨兵对象的指定符:

      resources:
    - kind: project
    selector:
    ...
  • Port"、"实体 "和 "映射 "键被用来将 Sentry 对象字段映射到Port实体。要创建多个同类映射,可在 resources 数组中添加另一项;

    resources:
    - kind: project
    selector:
    query: "true"
    port:
    entity:
    mappings:
    identifier: .slug
    title: .name
    blueprint: '"sentryProject"'
    properties:
    dateCreated: .dateCreated
    platform: .platform
    status: .status
    link: .organization.links.organizationUrl + "/projects/" + .name
Blueprint key 注意 blueprint 键的值 - 如果要使用硬编码字符串,则需要用 2 组引号封装,例如使用一对单引号 ('),然后再使用一对双引号 (")。

将数据输入Port

要使用integration configuration 引用 Sentry 对象,可以按照以下步骤操作:

  1. 转到 DevPortal Builder 页面。
  2. 选择要使用 Sentry 进行引用的蓝图。
  3. 从菜单中选择采集数据选项。
  4. 在 APM 和警报类别下选择 Sentry。
  5. integration configuration 的内容添加到编辑器中。
  6. 单击 "Resync"。

示例

蓝图和相关集成配置示例:

项目

Project blueprint
{
"identifier": "sentryProject",
"title": "project",
"icon": "Sentry",
"schema": {
"properties": {
"dateCreated": {
"title": "dateCreated",
"type": "string",
"format": "date-time"
},
"platform": {
"type": "string",
"title": "platform"
},
"status": {
"title": "status",
"type": "string",
"enum": [
"active",
"disabled",
"pending_deletion",
"deletion_in_progress"
]
},
"link": {
"title": "link",
"type": "string",
"format": "url"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Integration configuration
resources:
- kind: project
selector:
query: "true"
port:
entity:
mappings:
identifier: .slug
title: .name
blueprint: '"sentryProject"'
properties:
dateCreated: .dateCreated
platform: .platform
status: .status
link: .organization.links.organizationUrl + "/projects/" + .name

问题

Issue blueprint
{
"identifier": "sentryIssue",
"title": "issue",
"icon": "Sentry",
"schema": {
"properties": {
"link": {
"title": "link",
"type": "string",
"format": "url"
},
"status": {
"title": "status",
"type": "string"
},
"isUnhandled": {
"icon": "DefaultProperty",
"title": "isUnhandled",
"type": "boolean"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {
"project": {
"title": "project",
"target": "sentryProject",
"required": false,
"many": false
}
}
}
Integration configuration
- kind: issue
selector:
query: "true"
port:
entity:
mappings:
identifier: ".id"
title: ".title"
blueprint: '"sentryIssue"'
properties:
link: ".permalink"
status: ".status"
isUnhandled: ".isUnhandled"
relations:
project: ".project.slug"

让我们来测试一下

本节包括来自 Sentry 的响应数据示例。 此外,还包括根据上一节提供的 Ocean 配置从重新同步事件中创建的实体。

有效载荷

以下是 Sentry 有效载荷结构的示例:

Project response data
{
"id": "4504931759095808",
"slug": "python-fastapi",
"name": "python-fastapi",
"platform": "python-fastapi",
"dateCreated": "2023-03-31T06:18:37.290732Z",
"isBookmarked": false,
"isMember": false,
"features": [
"alert-filters",
"minidump",
"race-free-group-creation",
"similarity-indexing",
"similarity-view",
"span-metrics-extraction",
"span-metrics-extraction-resource",
"releases"
],
"firstEvent": "2023-03-31T06:25:54.666640Z",
"firstTransactionEvent": false,
"access": [],
"hasAccess": true,
"hasMinifiedStackTrace": false,
"hasMonitors": false,
"hasProfiles": false,
"hasReplays": false,
"hasFeedbacks": false,
"hasSessions": false,
"isInternal": false,
"isPublic": false,
"avatar": {
"avatarType": "letter_avatar",
"avatarUuid": null
},
"color": "#913fbf",
"status": "active",
"organization": {
"id": "4504931754901504",
"slug": "test-org",
"status": {
"id": "active",
"name": "active"
},
"name": "Test Org",
"dateCreated": "2023-03-31T06:17:33.619189Z",
"isEarlyAdopter": false,
"require2FA": false,
"requireEmailVerification": false,
"avatar": {
"avatarType": "letter_avatar",
"avatarUuid": null,
"avatarUrl": null
},
"features": [
"performance-tracing-without-performance",
"performance-consecutive-http-detector",
"performance-large-http-payload-detector",
"escalating-issues",
"minute-resolution-sessions",
"performance-issues-render-blocking-assets-detector",
"event-attachments"
],
"links": {
"organizationUrl": "https://test-org.sentry.io",
"regionUrl": "https://us.sentry.io"
},
"hasAuthProvider": false
}
}
Issue response data
{
"id": "4605173695",
"shareId": "None",
"shortId": "PYTHON-FASTAPI-2",
"title": "ZeroDivisionError: division by zero",
"culprit": "index",
"permalink": "https://test-org.sentry.io/issues/4605173695/",
"logger": "None",
"level": "error",
"status": "unresolved",
"statusDetails": {},
"substatus": "new",
"isPublic": false,
"platform": "python",
"project": {
"id": "4504931759095808",
"name": "python-fastapi",
"slug": "python-fastapi",
"platform": "python-fastapi"
},
"type": "error",
"metadata": {
"value": "division by zero",
"type": "ZeroDivisionError",
"filename": "app.py",
"function": "index",
"display_title_with_tree_label": false,
"in_app_frame_mix": "mixed"
},
"numComments": 0,
"assignedTo": "None",
"isBookmarked": false,
"isSubscribed": false,
"subscriptionDetails": "None",
"hasSeen": false,
"annotations": [],
"issueType": "error",
"issueCategory": "error",
"isUnhandled": true,
"count": "1",
"userCount": 0,
"firstSeen": "2023-11-06T08:31:27.058163Z",
"lastSeen": "2023-11-06T08:31:27.058163Z",
"stats": {
"24h": [
[1699174800, 0],
[1699178400, 0],
[1699182000, 0],
[1699250400, 0],
[1699254000, 0],
[1699257600, 1]
]
}
}

映射结果

结合样本有效载荷和 Ocean 配置,可生成以下 Port 实体:

Project entity in Port
{
"identifier": "python-fastapi",
"title": "python-fastapi",
"icon": null,
"blueprint": "sentryProject",
"team": [],
"properties": {
"dateCreated": "2023-03-31T06:18:37.290732Z",
"platform": "python-fastapi",
"status": "active",
"link": "https://test-org.sentry.io/projects/python-fastapi"
},
"relations": {},
"createdAt": "2023-11-06T08:49:17.700Z",
"createdBy": "hBx3VFZjqgLPEoQLp7POx5XaoB0cgsxW",
"updatedAt": "2023-11-06T08:59:11.446Z",
"updatedBy": "hBx3VFZjqgLPEoQLp7POx5XaoB0cgsxW"
}
Issue entity in Port
{
"identifier": "4605173695",
"title": "ZeroDivisionError: division by zero",
"icon": null,
"blueprint": "sentryIssue",
"team": [],
"properties": {
"link": "https://test-org.sentry.io/issues/4605173695/",
"status": "unresolved",
"isUnhandled": true
},
"relations": {
"project": "python-fastapi"
},
"createdAt": "2023-11-06T08:49:20.406Z",
"createdBy": "hBx3VFZjqgLPEoQLp7POx5XaoB0cgsxW",
"updatedAt": "2023-11-06T08:49:20.406Z",
"updatedBy": "hBx3VFZjqgLPEoQLp7POx5XaoB0cgsxW"
}

通过 webhook 进行替代安装

虽然上述 Ocean 集成是推荐的安装方法,但您可能更喜欢使用 webhook 从 Sentry 引用数据。 如果是这样,请使用以下说明:

Webhook installation (click to expand)

在本例中,您将在Sentry 和 Port 之间创建一个 webhook 集成,该集成将摄取问题实体。

Port configuration

创建以下蓝图定义:

Sentry issue blueprint
{
"identifier": "sentryIssue",
"description": "This blueprint represents an issue trigger event from Sentry",
"title": "Sentry Issue Event",
"icon": "Sentry",
"schema": {
"properties": {
"level": {
"type": "string",
"title": "Level",
"enum": ["error", "info", "fatal", "warning", "debug", "sample"]
},
"platform": {
"type": "string",
"title": "Platform",
"description": "the platform name in Sentry"
},
"status": {
"type": "string",
"title": "Issue Status"
},
"projectID": {
"type": "string",
"title": "Project ID",
"description": "the ID of the project in Sentry"
},
"action": {
"type": "string",
"title": "Action",
"enum": ["created", "resolved", "assigned", "ignored"]
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}

创建以下 webhook 配置using Port UI :

Sentry issue webhook configuration
  1. 基本信息 选项卡 - 填写以下详细信息: 1.title: "Sentry 问题映射器"; 2.标识符: sentry_issue_mapper; 3.Description : 将 Sentry 问题映射到 Port 的 webhook 配置; 4.图标 : Sentry
  2. 集成配置选项卡 - 填写以下 JQ 映射:
    [
    {
    "blueprint": "sentryIssue",
    "entity": {
    "identifier": ".body.data.issue.id",
    "title": ".body.data.issue.title",
    "properties": {
    "action": ".body.action",
    "level": ".body.data.issue.level",
    "platform": ".body.data.issue.platform",
    "status": ".body.data.issue.status",
    "projectID": ".body.data.issue.project.id"
    }
    }
    }
    ]

3.向下滚动到高级设置,输入以下详细信息: 1.签名头名称: sentry-hooks-signature; 2.签名算法: 从下拉选项中选择 sha256; 3.点击页面底部的保存

我们省略了 webhook 配置中安全对象的 "secret "字段,因为secret值是由 Sentry 在创建 webhook 时生成的。 因此,在遵循此示例时,请先在 Port 中创建 webhook 配置。 使用响应中的 webhook URL 并在 Sentry 中创建 webhook。 从 Sentry 获取secret后,您可以返回 Port 并使用secret更新webhook configuration

Create a webhook in Sentry

  1. 使用贵组织的凭据登录 Sentry;
  2. 单击页面左侧边栏的齿轮图标(设置);
  3. 选择 开发设置
  4. 在页面上角,点击创建新集成
  5. Sentry 提供两种类型的集成: 内部集成和公共集成。在本指南中,请选择内部集成,然后点击下一步按钮;
  6. 输入以下详细信息:
    1. Name - 被用于一个有意义的名称,如 Port Webhook;
    2. Webhook URL- 输入创建 Webhook 配置后收到的url` 键的值;
    3. Overview - 输入 webhook 的描述;
    4. 权限"- 授予 webhook 在问题和事件类别的读取权限; 5.Webhooks` - 在该部分下,启用问题复选框,允许 Sentry 向 Port 报告问题事件; 7.单击页面底部的保存更改
网络钩子已创建,您可以引用 Sentry 生成的secret值,并用它更新 Port 网络钩子配置中的 security 对象

Relate comments to Issues

下面的示例除了上一个示例中的 "sentryIssue "蓝图外,还添加了一个 "sentryComment "蓝图。 此外,它还添加了一个 "sentryIssue "关系。 webhook 将创建或更新这两个现有实体之间的关系,使您可以映射评论是针对哪个问题提出的:

Sentry comments blueprint (including the sentryIssue relation)
{
"identifier": "sentryComment",
"description": "This blueprint represents a Sentry comment in our software catalog",
"title": "Sentry Comment",
"icon": "Sentry",
"schema": {
"properties": {
"action": {
"type": "string",
"title": "action",
"enum": ["created", "updated", "deleted"]
},
"comment": {
"type": "string",
"title": "Comment"
},
"project": {
"type": "string",
"title": "Project Slug"
},
"issue_id": {
"type": "string",
"title": "Issue ID"
},
"timestamp": {
"type": "string",
"title": "Comment Timestamp"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {
"sentryIssue": {
"title": "Issue",
"target": "sentryIssue",
"required": false,
"many": false
}
}
}

创建以下 webhook 配置using Port UI :

Sentry comments webhook configuration
  1. 基本信息 选项卡 - 填写以下详细信息: 1.title: "条目注释映射器"; 2.标识符: sentry_comment_mapper; 3.Description : 将 Sentry 注释映射到 Port 的 webhook 配置; 4.图标 : Sentry
  2. 集成配置选项卡 - 填写以下 JQ 映射:
    [
    {
    "blueprint": "sentryComment",
    "entity": {
    "identifier": ".body.data.comment_id",
    "title": "Comment Event",
    "properties": {
    "action": ".body.action",
    "comment": ".body.data.comment",
    "project": ".body.data.project_slug",
    "issue_id": ".body.data.issue_id",
    "timestamp": ".body.data.timestamp"
    },
    "relations": {
    "sentryIssue": ".body.data.issue_id | tostring"
    }
    }
    }
    ]

3.向下滚动到高级设置,输入以下详细信息: 1.签名头名称: sentry-hooks-signature; 2.签名算法: 从下拉选项中选择 sha256; 3.点击页面底部的保存

要查看 Sentry webhooks 中的不同有效载荷和事件、click here

完成!Sentry 中的任何问题和评论都将触发 webhook 事件。 Port 将根据映射解析事件,并相应地更新目录实体。

Let's Test It

本节包括创建问题或评论时 Sentry 发送的 webhook 事件示例。 此外,本节还包括根据上一节提供的 webhook 配置从事件中创建的实体。

Payload

下面是创建 Sentry 问题或评论时发送到 webhook URL 的有效载荷结构示例:

Sentry issue webhook event payload
{
"action": "created",
"installation": {
"uuid": "54a3e698-f389-4d86-b9f8-50093a228449"
},
"data": {
"issue": {
"id": "4253613038",
"shareId": "None",
"shortId": "PYTHON-B",
"title": "NameError: name 'total' is not defined",
"culprit": "__main__ in <module>",
"permalink": "None",
"logger": "None",
"level": "error",
"status": "unresolved",
"statusDetails": {},
"substatus": "new",
"isPublic": false,
"platform": "python",
"project": {
"id": "4504989602480128",
"name": "python",
"slug": "python",
"platform": "python"
},
"type": "error",
"metadata": {
"value": "name 'total' is not defined",
"type": "NameError",
"filename": "sentry.py",
"function": "<module>",
"display_title_with_tree_label": false
},
"numComments": 0,
"assignedTo": "None",
"isBookmarked": false,
"isSubscribed": false,
"subscriptionDetails": "None",
"hasSeen": false,
"annotations": [],
"issueType": "error",
"issueCategory": "error",
"isUnhandled": true,
"count": "1",
"userCount": 0,
"firstSeen": "2023-06-15T17:10:09.914274Z",
"lastSeen": "2023-06-15T17:10:09.914274Z"
}
},
"actor": {
"type": "application",
"id": "sentry",
"name": "Sentry"
}
}
Sentry comment webhook event payload
{
"action": "created",
"installation": {
"uuid": "d5a2de51-0138-496a-8e79-c17747c3a40d"
},
"data": {
"comment_id": "1729635072",
"issue_id": "4253613038",
"project_slug": "python",
"timestamp": "2023-06-15T17:15:53.383120Z",
"comment": "Hello admin please take a look at this"
},
"actor": {
"type": "user",
"id": 2683666,
"name": "[email protected]"
}
}

Mapping Result

结合示例有效载荷和 webhook 配置可生成以下 Port sentryIssue 实体:

{
"identifier": "4253613038",
"title": "NameError: name 'total' is not defined",
"blueprint": "sentryIssue",
"properties": {
"action": "created",
"level": "error",
"platform": "python",
"status": "unresolved",
"projectID": "4504989602480128"
},
"relations": {}
}

此外,还将生成以下 Port sentryComment 实体:

{
"identifier": "1729635072",
"title": "Comment Event",
"blueprint": "sentryComment",
"properties": {
"action": "created",
"comment": "Hello admin please take a look at this",
"project": "python",
"issue_id": "4253613038",
"timestamp": "2023-06-15T17:15:53.383120Z"
},
"relations": {
"sentryIssue": "4253613038"
}
}