实时跟踪、可视化资产并发出警报

编辑

实时跟踪、可视化资产并发出警报编辑

您是否对资产跟踪感兴趣?好消息!使用 地图 可以轻松地可视化和分析移动数据。您可以跟踪物联网设备的位置,并监控运输途中的包裹或车辆。

在本教程中,您将查看来自俄勒冈州波特兰市的实时城市交通数据。您将观察城市的公共汽车、电车和火车,使用数据可视化拥堵情况,并在车辆进入施工区域时通知调度团队。

您将学习

  • 使用 Elastic Agent 将 TriMet REST API 摄取到 Elasticsearch 中。
  • 创建包含可视化资产轨迹和最后已知位置图层的的地图。
  • 使用符号和颜色来设置数据值的样式,并显示资产的航向。
  • 设置跟踪围栏警报以监控移动车辆。
  • 在地图上显示这些警报。

完成本教程后,您将获得如下所示的地图

construction zones

先决条件编辑

第 1 部分:摄取波特兰公共交通数据编辑

要体验可视化波特兰公共交通工具并对其发出警报的乐趣,您必须首先将 自定义 API 集成添加到 Elastic Agent 策略中,以便将 TriMet 波特兰数据获取到 Elasticsearch 中。

步骤 1:设置 Elasticsearch 索引编辑

  1. 在 Kibana 中,打开主菜单,然后单击 开发工具
  2. 控制台 中,创建 tri_met_tracks 索引生命周期策略。此策略会将事件在热数据阶段保留 7 天。然后,数据将移至温数据阶段。在温数据阶段保留 365 天后,数据将被删除。

    ILM 策略定义
    PUT _ilm/policy/tri_met_tracks
    {
     "policy": {
       "phases": {
         "hot": {
           "min_age": "0ms",
           "actions": {
             "rollover": {
               "max_primary_shard_size": "50gb",
               "max_age": "7d"
             },
             "set_priority": {
               "priority": 100
             }
           }
         },
         "warm": {
           "min_age": "0d",
           "actions": {
             "set_priority": {
               "priority": 50
             }
           }
         },
         "delete": {
           "min_age": "365d",
           "actions": {
             "delete": {
               "delete_searchable_snapshot": true
             }
           }
         }
       }
     }
    }
  3. 控制台 中,添加 tri_met_tracks_for_elastic_agent 摄取管道。

    摄取策略定义
    PUT _ingest/pipeline/tri_met_tracks_for_elastic_agent
    {
     "processors": [
       {
         "set": {
           "field": "trimet.inCongestion",
           "value": "false",
           "if": "ctx?.trimet?.inCongestion == null"
         }
       },
       {
         "convert": {
           "field": "trimet.bearing",
           "type": "float"
         }
       },
       {
         "convert": {
           "field": "trimet.inCongestion",
           "type": "boolean"
         }
       },
       {
         "script": {
           "source": """
             double lat=Math.round(ctx['trimet']['latitude']*1e6)/1e6;
             double lon=Math.round(ctx['trimet']['longitude']*1e6)/1e6;
             ctx['trimet']['location'] = lat + "," + lon
             """,
           "description": "Generate the geometry rounding to six decimals"
         }
       },
       {
         "script": {
           "source": """ctx['_id'] = ctx['trimet']['vehicleID'] + "_" + ctx['trimet']['time']""",
           "description": "Generate documentID"
         }
       },
       {
         "remove": {
           "field": [
             "message",
             "input",
             "agent",
             "ecs",
             "host",
             "event",
             "trimet.longitude",
             "trimet.latitude"
           ]
         }
       }
     ]
    }
  4. 控制台 中,创建组件和索引模板,该模板配置为使用数据流以及之前的 ILM 策略和摄取管道

    索引组件模板
    PUT _component_template/logs-httpjson.trimet@package
    {
     "template": {
       "settings": {
         "index": {
           "lifecycle": {
             "name": "tri_met_tracks"
           },
           "codec": "best_compression",
           "default_pipeline": "tri_met_tracks_for_elastic_agent"
         }
       },
       "mappings": {
         "_routing": {
           "required": false
         },
         "numeric_detection": false,
         "dynamic_date_formats": [
           "strict_date_optional_time",
           "yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"
         ],
         "dynamic": true,
         "_source": {
           "excludes": [],
           "includes": [],
           "enabled": true
         },
         "dynamic_templates": [],
         "date_detection": true,
         "properties": {
           "input": {
             "properties": {
               "type": {
                 "ignore_above": 1024,
                 "type": "keyword"
               }
             }
           },
           "@timestamp": {
             "ignore_malformed": false,
             "type": "date"
           },
           "ecs": {
             "properties": {
               "version": {
                 "ignore_above": 1024,
                 "type": "keyword"
               }
             }
           },
           "data_stream": {
             "properties": {
               "namespace": {
                 "type": "constant_keyword"
               },
               "type": {
                 "type": "constant_keyword"
               },
               "dataset": {
                 "type": "constant_keyword"
               }
             }
           },
           "event": {
             "properties": {
               "created": {
                 "type": "date"
               },
               "module": {
                 "type": "constant_keyword",
                 "value": "httpjson"
               },
               "dataset": {
                 "type": "constant_keyword",
                 "value": "httpjson.trimet"
               }
             }
           },
           "message": {
             "type": "match_only_text"
           },
           "tags": {
             "ignore_above": 1024,
             "type": "keyword"
           },
           "trimet": {
             "type": "object",
             "properties": {
               "expires": {
                 "type": "date"
               },
               "signMessage": {
                 "type": "text"
               },
               "serviceDate": {
                 "type": "date"
               },
               "loadPercentage": {
                 "type": "float"
               },
               "nextStopSeq": {
                 "type": "integer"
               },
               "source": {
                 "type": "keyword"
               },
               "type": {
                 "type": "keyword"
               },
               "blockID": {
                 "type": "integer"
               },
               "signMessageLong": {
                 "type": "text"
               },
               "lastLocID": {
                 "type": "keyword"
               },
               "nextLocID": {
                 "type": "keyword"
               },
               "locationInScheduleDay": {
                 "type": "integer"
               },
               "newTrip": {
                 "type": "boolean"
               },
               "direction": {
                 "type": "integer"
               },
               "inCongestion": {
                 "type": "boolean"
               },
               "routeNumber": {
                 "type": "integer"
               },
               "bearing": {
                 "type": "integer"
               },
               "garage": {
                 "type": "keyword"
               },
               "tripID": {
                 "type": "keyword"
               },
               "delay": {
                 "type": "integer"
               },
               "extraBlockID": {
                 "type": "keyword"
               },
               "messageCode": {
                 "type": "integer"
               },
               "lastStopSeq": {
                 "type": "integer"
               },
               "location": {
                 "type": "geo_point"
               },
               "time": {
                 "index": true,
                 "ignore_malformed": false,
                 "store": false,
                 "type": "date",
                 "doc_values": true
               },
               "vehicleID": {
                 "type": "keyword"
               },
               "offRoute": {
                 "type": "boolean"
               }
             }
           }
         }
       }
     }
    }
    索引模板
    PUT _index_template/logs-httpjson.trimet
    {
     "index_patterns": [
       "logs-httpjson.trimet-*"
     ],
     "composed_of": [
       "logs-httpjson.trimet@package",
       ".fleet_globals-1",
       ".fleet_agent_id_verification-1"
     ],
     "priority": 200,
     "data_stream": {
       "hidden": false,
       "allow_custom_routing": false
     }
    }

步骤 2:配置 Elastic Agent编辑

如果您已有代理策略,请从 查看策略 操作弹出窗口中获取其标识符

agent policy id
policy id

控制台 执行以下请求,以安装新的自定义 API 集成。为 policy_idtri_met_app_id 放入相应的值。

创建新的自定义 API 集成
POST kbn:/api/fleet/package_policies
{
 "policy_id": "<policy_id>", 
 "package": {
   "name": "httpjson",
   "version": "1.18.0"
 },
 "name": "httpjson-trimet",
 "description": "TriMet data upload",
 "namespace": "default",
 "inputs": {
   "generic-httpjson": {
     "enabled": true,
     "streams": {
       "httpjson.generic": {
         "enabled": true,
         "vars": {
           "data_stream.dataset": "httpjson.trimet",
           "request_url": "https://developer.trimet.org/ws/v2/vehicles?appID=<tri_met_app_id>", 
           "request_interval": "1m", 
           "request_method": "GET",
           "response_split": "target: body.resultSet.vehicle",
           "request_redirect_headers_ban_list": [],
           "oauth_scopes": [],
           "processors": "- decode_json_fields:\n    fields: [\"message\"]\n    target: \"trimet\"\n",
           "tags": [
             "trimet"
             ]
         }
       }
     }
   }
 }
}

代理策略标识符

TriMet 应用程序标识符

每分钟检索一次车辆位置

此请求将配置集成,使其每分钟向 TriMet REST API 发出请求,将 API 响应拆分为每个车辆一条消息,并将其放入 httpjson.trimet 数据流中,并将车辆的数据编码到 trimet 字段中。其余的数据管理将由第一步中定义的摄取策略处理。

步骤 3:为 tri_met_tracks Elasticsearch 索引创建数据视图编辑

控制台 中执行此请求,以创建一个名为 TriMet Positions 的新 Kibana 数据视图

POST kbn:/api/data_views/data_view
{
 "data_view": {
    "title": "logs-httpjson.trimet-*",
    "name": "TriMet Positions",
    "timeFieldName": "trimet.time"
 }
}

Kibana 显示数据视图中的字段。

data view

您可能希望调整此数据视图,以根据您的个人偏好调整字段名称和数字或日期格式。地图应用程序会在工具提示和其他 UI 元素中遵循这些设置。有关更多详细信息,请查看 格式化数据字段

步骤 4:探索波特兰 TriMet 数据编辑

  1. 打开主菜单,然后单击 Discover
  2. 将数据视图设置为 TriMet Positions
  3. 打开 时间过滤器,并将时间范围设置为过去 15 分钟。
  4. 展开文档并探索您将在本教程后面部分中使用的一些字段:trimet.bearingtrimet.inCongestiontrimet.locationtrimet.vehicleID
discover

第 2 部分:构建运营地图编辑

通过查看单个事件很难概览波特兰的车辆。让我们创建一个地图来显示每辆车的路线和当前位置,以及它们的航向。

步骤 1:创建地图编辑

创建地图并将默认图层的主题设置为深色模式。

  1. 打开主菜单,然后单击 地图
  2. 单击 创建地图
  3. 图层 列表中,单击 道路地图,然后单击 编辑图层设置
  4. 打开 切片服务 下拉列表,然后选择 道路地图 - 深色
  5. 单击 保留更改

步骤 2. 添加轨迹图层编辑

添加一个图层以显示过去 15 分钟的车辆路线。

  1. 单击 添加图层
  2. 单击 轨迹
  3. 选择 TriMet Positions 数据视图。
  4. 定义轨迹

    1. 实体 设置为 trimet.vehicleID
    2. 排序 设置为 trimet.time
  5. 单击 添加并继续
  6. 在图层设置中

    1. 名称 设置为 轨迹
    2. 不透明度 设置为 80%。
  7. 滚动到 图层样式,并将 边框颜色 设置为粉色。
  8. 单击 保留更改
  9. 图层 列表中,单击 轨迹,然后单击 适应数据

此时,您将看到一个地图,其中包含表示 TriMet 车辆在城市中移动路线的线条。

tracks layer

步骤 3. 指示车辆轨迹的方向编辑

添加一个图层,该图层使用数据中的属性来设置车辆的样式和方向。您将看到车辆的行驶方向和交通状况。

  1. 单击 添加图层,然后选择 每个实体的热门结果
  2. 选择 TriMet Positions 数据视图。
  3. 要显示每辆车的最新位置

    1. 实体 设置为 trimet.vehicleID
    2. 每个实体的文档数 设置为 1。
    3. 排序字段 设置为 trimet.time
    4. 排序顺序 设置为 降序
  4. 单击 添加并继续
  5. 将名称更改为 最新位置
  6. 滚动到 图层样式

    1. 符号类型 设置为 图标
    2. 图标 设置为 箭头
    3. 设置 填充颜色

      1. 选择 按值 样式,并将字段设置为 trimet.inCongestion
      2. 使用 自定义调色板
      3. 其他 颜色设置为深灰色。
      4. false 添加一个绿色类,表示车辆未处于交通拥堵状态。
      5. true 添加一个红色类,表示车辆处于交通拥堵状态。
    4. 边框宽度 设置为 0。
    5. 更改 符号方向 以使用 按值trimet.bearing 字段。

      top hits layer style
  7. 单击 保留更改
  8. 打开 时间过滤器,并将 刷新间隔 设置为 10 秒,然后单击 开始

您的地图应每 10 秒自动刷新一次,以显示最新的车辆位置和轨迹。

tracks and top hits

第 3 部分:设置地理围栏警报编辑

让我们使 TriMet 波特兰数据可操作,并在车辆进入施工区域时发出警报。

步骤 1. 添加施工区域编辑

添加施工区域图层,您将在图上绘制该图层。施工区域将用作地理围栏边界或阈值,作为触发警报的依据。

  1. 单击 添加图层
  2. 点击 创建索引
  3. 索引名称 设置为 trimet_construction_zones
  4. 点击 创建索引
  5. 在地图上绘制 2 或 3 个施工区域

    1. 在地图左侧的工具栏中,选择边框图标 边框图标
    2. 要绘制施工区域,请在地图上单击一个起点并拖动。
    3. 单击端点以完成。
  6. 完成绘制施工区域后,单击图例中图层名称下的 退出
  7. 图层设置 中,将 名称 设置为 施工区域
  8. 滚动到 图层样式,并将 填充颜色 设置为黄色。
  9. 单击 保留更改
  10. 保存 地图。

    1. 为地图添加标题。
    2. 添加到仪表板 下,选择
    3. 点击 保存并添加到库

该地图现在表示实时公共交通流量的操作视图。您将看到车辆的行驶方向,以及它们是否靠近或已进入施工区域。

您的地图现在已完成,恭喜!

construction zones

步骤 2. 配置警报编辑

通过定义规则和连接器来创建新警报。规则包括将触发警报的条件,连接器定义警报触发后执行的操作。在这种情况下,每个警报都会将一个新文档插入到 Elasticsearch 索引中。

在本例中,您将规则设置为每分钟检查一次。但是,在生产环境中运行时,可能需要将此值调整为更高的检查间隔,以避免性能问题。有关更多信息,请参阅警报生产注意事项

  1. 在 Kibana 控制台 中创建一个新的索引和数据视图

    为警报创建一个索引和数据视图
    # Create the alerts index
    PUT trimet_alerts
    {
     "settings": {
       "number_of_replicas": 1,
       "number_of_shards": 1
     },
     "mappings": {
       "properties": {
         "vehicleId": {"type": "keyword"},
         "documentId": {"type": "text"},
         "vehicleTime": {"type": "date"},
         "detectionTime": {"type": "date"},
         "location": {"type": "geo_point"},
         "boundaryId": {"type": "keyword"},
         "message": {"type": "text"}
       }
     }
    }
    
    
    # Create the alerts index data view
    POST kbn:/api/data_views/data_view
    {
     "data_view": {
        "title": "trimet_alerts",
        "name": "TriMet Alerts",
        "timeFieldName": "detectionTime"
     }
    }
  2. 打开 堆栈管理,然后单击 规则
  3. 点击 创建规则
  4. 将规则命名为 TriMet 警报
  5. 选择 跟踪包含 规则类型。
  6. 实体 块中

    1. 选择 TriMet 位置 数据视图
    2. 选择 trimet.time 作为 时间字段
    3. 选择 trimet.location 作为 位置字段
    4. 选择 trimet.vehicleID 作为 实体字段
  7. 边界 块中

    1. 选择 trimet_construction_zones 数据视图
    2. 选择 coordinates 作为 位置字段
    3. 显示名称过滤器 留空
  8. 选择每分钟检查一次规则
  9. 检查间隔 设置为 1 分钟
  10. 通知 仅在状态更改时

    rule configuration
  11. 操作 下,选择 索引 连接器类型。
  12. 添加一个名为 TriMet 警报 的新连接器

    1. 选择 trimet_alerts 索引
    2. 使用 detectionTime 字段为每个文档定义时间字段
  13. 操作频率 保留为默认选项:状态更改时
  14. 运行时间 选择器保留为默认选项:满足跟踪包含条件时
  15. 使用以下模板创建新的索引文档

    {
     "vehicleId": "{{context.entityId}}",
     "vehicleTime": "{{context.entityDateTime}}",
     "documentId": "{{context.entityDocumentId}}",
     "detectionTime": "{{context.detectionDateTime}}",
     "location": "{{context.entityLocation}}",
     "boundaryId": "{{context.containingBoundaryId}}"
    }
    alert connector
  16. 点击 保存

TriMet 警报连接器 已添加到 连接器 页面。有关常见连接器的更多信息,请参阅Slack电子邮件连接器。

步骤 3. 实时查看警报编辑

配置并运行警报后,几分钟后,您的 trimet_alerts 索引应该开始获取数据。您可以轻松地将此数据添加到操作地图中

  • 打开您的操作地图
  • 点击 添加图层
  • 点击 文档
  • 选择 TriMet 警报 数据视图
  • 符号类型 更改为 图标 并选择 公交车 图标
  • 将颜色更改为粉红色
  • 使用 vehicleId 字段启用 标签 选项
  • vehicleIdboundaryIddetectionTimevehicleTime 字段添加到工具提示配置中,以便在地图上查看警报详细信息。

    vehicle alerts

恭喜!您已完成本教程,并获得了跟踪资产的方法。您现在可以使用自己的数据尝试复制相同的分析。