实时跟踪、可视化和告警资产

编辑

实时跟踪、可视化和告警资产

编辑

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

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

您将学习如何:

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

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

construction zones

先决条件

编辑

第一部分:摄入波特兰公共交通数据

编辑

要开始可视化和告警波特兰公共交通车辆的乐趣,您必须首先将 自定义 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. 转到发现
  2. 将数据视图设置为TriMet Positions
  3. 打开时间过滤器,并将时间范围设置为过去 15 分钟。
  4. 展开一个文档并探索您将在本教程后面用到的一些字段:trimet.bearingtrimet.inCongestiontrimet.locationtrimet.vehicleID
discover

第二部分:构建操作地图

编辑

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

步骤 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

第三部分:设置地理围栏警报

编辑

让我们使 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

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