您的软件开发生命周期数据模板
您的软件开发生命周期数据模板
- 建议收集的属性
- 需要跟踪的关键活动
- ServiceNow DevOps数据提取指南
软件开发生命周期属性
| 名称 | 说明 | ||
|---|---|---|---|
| 开发事项 DevelopmentItem | 表示单个工作单元的唯一标识符,例如在开发生命周期中持续流转的功能、缺陷或任务。 | ||
| 说明 Development Item作为主要案例标识,代表正在跟踪的一个独立工作单元。它将该工作项从最初构思和规划,到开发、测试和部署的所有活动关联起来。 在流程挖掘分析中,该属性是还原每个工作项端到端历程的基础。它支持可视化流程、计算总周期时间,以及识别单个功能或缺陷修复的流程变体。日志中的每个事件都必须关联一个Development Item,才能构建连贯的流程图。 为什么重要 这是连接所有相关开发活动的核心标识,可将其归入单个流程实例,从而分析每个工作项的完整生命周期。 获取位置 该标识通常是管理用户故事、缺陷或任务的表中的主键,例如ServiceNow中的“rm_story”“rm_bug”或“task”表。 示例 STRY0010015BUG0034092TASK0050118 | |||
| 开始时间 EventTime | 表示具体活动或事件发生时间的精确时间戳。 | ||
| 说明 此属性记录开发生命周期中每项活动的日期和时间,是按时间顺序排列事件及开展所有基于时间的分析的基础。 在流程挖掘中,开始时间用于计算活动之间的时长、识别等待时间并衡量流程整体周期时间。它也是性能分析仪表板的重要组成部分,例如SDLC端到端周期时间分析,并用于计算代码评审交付时间等关键绩效指标。 为什么重要 此时间戳对于正确排列事件以及计算周期时间、持续时间和等待时间等所有绩效指标至关重要。 获取位置 通常位于系统生成的时间戳字段中,例如审计轨迹或任务表中的“sys_updated_on”或“sys_created_on”。 示例 2023-10-26T10:00:00Z2023-10-27T14:35:10Z2023-11-01T09:15:00Z | |||
| 活动名称 ActivityName | 已发生的具体开发生命周期事件名称,例如“Development Started”或“Code Review Performed”。 | ||
| 说明 此属性记录软件开发生命周期中每个已完成里程碑或任务的名称。这些活动构成从创建到部署的流程步骤。 分析这些活动的顺序和频率是流程挖掘的核心功能。它支持构建流程图,帮助识别步骤之间的瓶颈,并突出不合规或低效的流程变体。活动集合包括设计、开发、测试和部署等关键阶段。 为什么重要 它定义流程图中的步骤,用于分析流程、识别瓶颈,以及发现偏离标准SDLC的情况。 获取位置 通常通过将状态变更、事件记录或审计轨迹条目映射到标准化活动名称列表来生成。例如,“state”字段变为“In Progress”时,可映射为“Development Started”。 示例 开发已开始代码已提交QA测试已完成已部署到生产环境 | |||
| 最后数据更新时间 LastDataUpdate | 表示事件日志数据最近一次从源系统刷新时间的时间戳。 | ||
| 说明 此属性记录数据集最近一次从ServiceNow DevOps提取或更新的时间。它适用于整个数据集,而非单个事件。 此时间戳对于了解分析结果的新鲜度至关重要。它能告知用户流程洞察的时效性,并帮助安排数据刷新。在仪表板中显示该信息,可为所有指标和可视化结果提供背景,确保决策基于及时数据。 为什么重要 为数据的时效性提供重要背景,确保用户了解流程分析结果的最新程度。 获取位置 此时间戳在数据提取过程中生成并添加,用于记录提取执行时间。 示例 2023-11-15T08:00:00Z | |||
| 源系统 SourceSystem | 标识数据提取自哪个系统,本例中为ServiceNow DevOps。 | ||
| 说明 此属性指定事件数据的来源系统。对于此流程,其值始终为“ServiceNow DevOps”。 虽然它看似是静态信息,但明确记录源系统对于数据治理至关重要,尤其是在数据可能来自多个系统的环境中,例如Jira或Azure DevOps。它有助于明确数据来源,并诊断数据质量或提取问题。 为什么重要 确保数据可追溯,对于维护数据完整性至关重要,尤其是在整合多个开发工具的数据时。 获取位置 这是一个静态值,应在数据提取和转换过程中添加。 示例 ServiceNow DevOps | |||
| Development Item周期时间 DevelopmentItemCycleTime | 从Development Item创建到最终关闭或部署所经过的总时间。 | ||
| 说明 此属性是一个计算指标,表示单个Development Item的端到端持续时间。计算方式是找出每个案例中第一项活动和最后一项活动的时间戳,并计算两者之差。 这是整个SDLC流程的核心关键绩效指标,直接支持“平均SDLC周期时间”KPI。它从高层衡量流程速度和效率。按时间以及优先级、团队等不同维度分析该指标,有助于跟踪流程改进措施的影响。 为什么重要 表示工作项的端到端总持续时间,是衡量整体流程效率和速度的关键指标。 获取位置 这不是源系统中的字段,而是流程挖掘工具按每个CaseId计算得出,计算方式为最大StartTime减去最小StartTime。 示例 15天4小时3天12小时32天8小时 | |||
| Development Item状态 DevelopmentItemState | 事件发生时Development Item的状态,例如“Open”“In Progress”或“Closed”。 | ||
| 说明 此属性反映Development Item在ServiceNow中的正式状态。活动是派生出的流程步骤,而状态代表系统工作流中的正式阶段。 状态通常是派生活动的来源,也可用于数据验证和创建更简洁的高层流程视图。例如,分析每种状态的停留时间,可以从不同于活动间耗时的角度识别瓶颈。它还适用于识别停滞或已解决的项目。 为什么重要 提供工作项的正式系统状态,通常是派生活动的来源,也可用于验证和开展高层状态分析。 获取位置 这是标准字段,通常位于ServiceNow任务相关表中,字段名为“state”或“stage”。 示例 待处理进行中准备测试已完成并关闭 | |||
| Development Item类型 DevelopmentItemType | 工作项的分类,例如“Feature”“Bug”“Technical Debt”或“Task”。 | ||
| 说明 此属性区分SDLC流程中流转的不同工作类型。例如,修复严重缺陷的流程可能不同于开发新功能的流程,且速度更快。 按工作项类型分析流程,可以更细致地了解绩效表现。它有助于回答以下问题:“缺陷的返工率是否高于新功能?”“技术债务减少的周期时间是否在可接受范围内?”这种细分比一刀切的流程视图提供更深入的洞察。 为什么重要 区分功能和缺陷等不同工作类型,因为它们可能具有不同的流程路径、优先级和预期持续时间。 获取位置 可以根据记录所在的源表(例如“rm_story”与“rm_bug”)确定,也可以根据通用任务表中的“type”字段确定。 示例 功能缺陷任务技术调研 | |||
| 优先级 DevelopmentItemPriority | 分配给Development Item的优先级,例如“High”“Medium”或“Low”。 | ||
| 说明 此属性根据业务紧迫性对开发项目进行分类。优先级有助于团队优先处理最关键的任务,也常用于管理SLA和利益相关方预期。 在流程挖掘中,优先级是比较分析的重要维度。通过按优先级筛选流程图,可以查看高优先级项目是否采用更快或不同的路径。它是“高优先级功能交付时间”仪表板和KPI的基础,可用于验证关键项目是否真正得到加速处理。 为什么重要 支持按不同优先级筛选和比较流程,帮助验证高优先级项目是否处理得更快、更高效。 获取位置 这是标准字段,通常位于ServiceNow任务相关表中,字段名为“priority”。 示例 1-严重2-高3-中等4-低 | |||
| 分配组 AssignmentGroup | 活动发生时负责Development Item的团队或小组。 | ||
| 说明 此属性标识负责工作项的团队,例如“前端开发人员”“后端服务”或“QA团队”。随着工作项推进,它通常会在不同分配组之间交接。 跟踪分配组对于了解跨职能协作和交接至关重要。它有助于识别工作从一个团队转移到另一个团队时产生的系统性延迟。此属性支持团队级绩效和工作负载分析,并帮助识别整体流程中的瓶颈团队。 为什么重要 跟踪负责工作的团队,支持分析团队绩效、工作负载平衡以及团队间交接效率。 获取位置 此信息存储在“assignment_group”字段中,该字段是ServiceNow任务相关表的标准字段。 示例 平台工程移动应用团队质量保证DevOps | |||
| 受影响的模块/组件 ModuleComponentAffected | Development Item涉及的具体软件模块、应用或组件。 | ||
| 说明 此属性根据开发工作影响的系统部分对其进行分类,可以是特定微服务、UI组件或后端应用。 按模块或组件细分流程,对于识别局部瓶颈至关重要。“组件专属瓶颈洞察”仪表板和“按组件统计的平均阶段时长”KPI依赖此属性,用于确定代码库中的某些部分是否持续对应更长的开发周期、更高的返工率或更频繁的部署失败。这有助于将改进工作集中在最需要的地方。 为什么重要 支持按应用或组件细分分析,帮助隔离系统特定部分的瓶颈或质量问题。 获取位置 通常是自定义字段,或指向配置管理数据库(CMDB)的引用,将工作项关联到“cmdb_ci”记录。请参阅ServiceNow DevOps文档。 示例 计费服务用户身份验证界面报表数据库API网关 | |||
| 指定的开发人员 AssignedDeveloper | 活动发生时,分配给Development Item的开发人员或用户姓名或ID。 | ||
| 说明 此属性标识负责执行特定任务或活动的人员。它是动态的,可能随着Development Item在不同阶段和团队之间流转而变化。 此属性对于分析资源分配、工作负载和交接至关重要。它直接支持“开发人员工作负载与交接”仪表板及“每位开发人员的活动量”KPI。通过跟踪该字段的变化,可以衡量交接时间,并识别开发人员之间或开发团队与QA团队之间的协作瓶颈。 为什么重要 这是开展资源分析的基础,包括工作负载分配、交接效率以及团队特有绩效模式的识别。 获取位置 此信息通常存储在ServiceNow任务相关表的“assigned_to”字段中。 示例 David MillerAnna WilliamsJames Brown | |||
| 是否返工 IsRework | 布尔标记。如果活动属于返工循环,例如测试后返回开发阶段,则值为true。 | ||
| 说明 这是一个派生属性,用于识别流程返回早期阶段后发生的活动。例如,同一项目在“QA Testing Completed”之后再次出现“Development Started”时,该活动会被标记为返工。 此标记对于量化和可视化返工至关重要。它直接支持“返工与拒绝流程分析”仪表板,并用于计算“测试后返工率”KPI。通过标记这些事件,分析人员可以轻松筛选并分析返工频率、原因及其对整体周期时间的影响。 为什么重要 此标记便于量化和分析返工,帮助衡量流程质量并识别重复工作的根本原因。 获取位置 流程挖掘工具会分析每个案例的活动顺序,检测流程中的回退,从而计算此属性。 示例 truefalse | |||
| Commit ID CommitId | 与开发工作关联的源代码提交的唯一标识。 | ||
| 说明 此属性将Development Item直接关联到Git等源代码仓库中的具体代码变更。它在“Code Committed”活动发生时记录。 在流程挖掘中,Commit ID通过连接流程数据和工程数据丰富分析。分析人员可以将问题部署追溯到确切的代码变更,或将代码复杂度指标与开发周期时间进行关联,从而开展更深入、更具技术性的根因分析。 为什么重要 将流程事件关联到具体代码变更,通过把流程指标与代码级细节结合起来,支持更深入的根因分析。 获取位置 由ServiceNow DevOps与Git或SVN等源代码管理系统的集成捕获。数据位于与Development Item关联的相关表中。 示例 a1b2c3d4e5f6f0e9d8c7b6a59a8b7c6d5e4f | |||
| 结束时间 EventEndTime | 表示活动完成时间的精确时间戳。对于瞬时事件,该时间与开始时间相同。 | ||
| 说明 此属性提供开发生命周期中每项活动完成时的日期和时间。对于“Code Review Performed”或“QA Testing”等具有可测量持续时间的活动,它尤其有用。 在流程挖掘中,同时记录开始时间和结束时间,可以精确计算活动处理时间,并将其与活动之间的等待时间区分开来。这有助于判断延迟是由任务耗时过长,还是资源等待时间过长造成的。对于“Build Triggered”等瞬时事件,结束时间可以与开始时间相同。 为什么重要 支持精确计算活动处理时间,帮助区分实际工作时间和等待时间。 获取位置 可能需要通过计算生成。它可以取下一项活动的开始时间,也可以取源系统中单独的“end date”字段(如果有)。 示例 2023-10-26T18:05:00Z2023-10-28T11:20:15Z2023-11-02T10:00:00Z | |||
| 计划发布版本 PlannedReleaseVersion | 计划交付Development Item的目标软件发布或版本。 | ||
| 说明 此属性将Development Item关联到特定计划发布,例如“Version 2.3”或“Q4 2023 Release”。它是项目管理和发布规划的重要组成部分。 在流程挖掘中,此属性是“发布计划执行情况监控”仪表板的基础。通过比较实际完成日期与计划发布日期,团队可以衡量计划执行情况,识别可能错过发布的项目,并分析发布延迟原因。它建立了底层开发流程与高层业务目标之间的直接联系。 为什么重要 将开发工作关联到具体发布,支持分析计划执行情况以及流程延迟对发布进度的影响。 获取位置 此信息通常存储在“release”或“planned_release”字段中,并经常引用ServiceNow中的发布管理表。请参阅ServiceNow DevOps文档。 示例 v3.4.12024年第一季度发布Phoenix项目正式上线 | |||
| 返工原因 ReworkReason | 对开发项目在测试后需要返工原因的分类或说明。 | ||
| 说明 当项目未通过QA或UAT时,此属性记录失败原因,可能是特定缺陷类别、需求理解偏差或环境问题。 此信息为“返工与拒绝流程分析”仪表板提供重要背景。分析人员不仅能了解发生了返工,还能明确返工原因,从而采取有针对性的改进措施,例如完善需求定义、加强单元测试或提高测试环境稳定性,以降低整体返工率。 为什么重要 提供返工原因的定性洞察,支持有针对性的流程改进,以提升质量并减少返工循环。 获取位置 测试失败时,可能记录在“close_notes”字段中,也可能记录在专用的“rework_reason”自定义字段中。请参阅ServiceNow DevOps文档。 示例 误解需求回归缺陷性能测试失败UI/UX问题 | |||
| 部署状态 DeploymentStatus | 表示部署活动的结果,通常为“Success”或“Failure”。 | ||
| 说明 此属性记录部署到特定环境的结果,是了解发布流程可靠性和稳定性的关键信息。 此属性是“部署成功与失败趋势”仪表板和“部署失败率”KPI的基础。通过分析部署失败的频率和趋势,组织可以识别测试、基础设施或发布协调中的潜在问题,并将改进工作集中于提升软件交付质量和可靠性。 为什么重要 直接衡量部署活动是否成功,对于计算部署失败率和分析发布稳定性至关重要。 获取位置 此状态通常记录在部署跟踪任务或与ServiceNow DevOps集成的CI/CD流水线执行记录中。 示例 成功失败完成但有警告 | |||
软件开发生命周期活动
| 活动 | 说明 | ||
|---|---|---|---|
| QA测试已完成 | 表示质量保证团队已成功完成开发事项的测试活动。通常当事项状态从测试阶段转为“Ready for UAT”或“Done”等状态时推断。 | ||
| 为什么重要 该里程碑标志着重要质量门完成,是进入用户验收测试或发布准备等后续阶段的前提。 获取位置 根据状态从测试状态(例如“In QA”)变更为测试后状态(例如“Ready for UAT”或“Resolved”)的时间戳推断。 采集 根据状态从“Testing”变更为后续状态的时间戳确定。 事件类型 inferred | |||
| UAT已批准 | 表示业务相关方在用户验收测试后正式批准开发事项。这是一个关键里程碑,通常根据状态从“In UAT”变更为“Ready for Release”或“Approved”等状态推断。 | ||
| 为什么重要 这是事项获准部署到生产环境前的最终业务审批,也是关键的质量和治理检查点。 获取位置 根据开发事项记录中表示UAT成功完成的状态转换推断,并记录在事项活动历史中。 采集 根据状态从“UAT”变更为已批准或可发布状态推断。 事件类型 inferred | |||
| 代码审查已完成 | 该活动表示同行代码审查已完成,通常与拉取请求或合并请求相关。该事件可通过DevOps集成明确捕获,也可根据相关记录的状态变更推断。 | ||
| 为什么重要 这是一个关键质量门。分析其持续时间,有助于发现审查流程中的瓶颈,而这正是SDLC延误的常见来源。 获取位置 可从ServiceNow Git集成中Pull Request记录的“Merged”或“Completed”事件获取,也可根据开发事项状态变更为“Code Review Complete”推断。 采集 与工作项关联的Pull Request合并时记录。 事件类型 explicit | |||
| 已部署到生产环境 | 该事件标志着成功完成生产环境部署。当CI/CD工具报告流水线成功完成时,ServiceNow DevOps会明确捕获此事件。 | ||
| 为什么重要 这是SDLC流程的主要成功终点,标志价值流完成,也是计算总周期时间的关键。 获取位置 从Pipeline Execution[sn_devops_pipeline_execution]记录或其关联的Stage Execution Run中的“completion_status”获取。结束时间的“Success”状态标志着该事件。 采集 生产部署流水线成功完成时记录。 事件类型 explicit | |||
| 开发事项已创建 | 该活动表示在ServiceNow中创建了新的开发事项,例如用户故事、缺陷或Epic。通常,当相关表中插入新记录时,系统会明确记录此事件,例如Story[rm_story]表。 | ||
| 为什么重要 这是SDLC流程的主要开始事件,可用于衡量端到端总周期时间并跟踪初始需求受理。 获取位置 在Story[rm_story]、Epic[rm_epic]或Defect[rm_defect]等开发相关表中创建记录后,记录于sys_audit或sys_history_line表。创建时间戳通常直接保存在记录中。 采集 从开发事项记录的创建时间戳中获取。 事件类型 explicit | |||
| 开发已开始 | 该活动表示开发人员开始主动编写代码或实施开发事项。通常根据事项状态变更为“In Progress”“Development”或“Coding”推断。 | ||
| 为什么重要 这是一个关键里程碑,标志着增值构建阶段开始,对于衡量开发人员交付周期和代码审查周期至关重要。 获取位置 根据开发事项记录(例如Story[rm_story])中“State”字段更新为“In Progress”或等效状态的时间戳推断。 采集 根据状态变更为“In Progress”或类似值的时间戳确定。 事件类型 inferred | |||
| 部署失败 | 表示将开发事项部署到生产环境的尝试未成功。当CI/CD流水线报告失败时,ServiceNow DevOps会明确捕获此事件。 | ||
| 为什么重要 这是一个关键失败终点。分析其频率和原因,对于提升发布稳定性、降低部署失败率至关重要。 获取位置 从Pipeline Execution[sn_devops_pipeline_execution]记录的“completion_status”获取。结束时间的“Failed”状态标志着该事件。 采集 生产部署流水线报告失败状态时记录。 事件类型 explicit | |||
| QA测试已开始 | 标志正式质量保证测试阶段开始。几乎总是根据开发事项状态变更为“In QA”“Testing”或“Ready for Test”等值推断。 | ||
| 为什么重要 该活动表示从开发团队向QA团队交接,可用于衡量测试阶段持续时间并识别测试能力瓶颈。 获取位置 根据开发事项记录(例如Story、Defect)中“State”字段更新为QA专属状态的时间戳推断。 采集 根据状态变更为“Testing”或等效状态的时间戳确定。 事件类型 inferred | |||
| UAT已开始 | 表示用户验收测试开始,业务相关方将在此阶段验证功能。通常通过状态变更为“UAT”“In UAT”或“User Acceptance Testing”推断。 | ||
| 为什么重要 该阶段对于确保开发功能满足业务需求至关重要。分析其持续时间,有助于发现用户参与度不足或需求不匹配等问题。 获取位置 根据开发事项记录中的状态转换推断,前提是客户的状态模型包含独立的UAT状态。 采集 根据状态变更为“UAT”推断。 事件类型 inferred | |||
| 代码已提交 | 表示开发人员将代码提交到与开发事项关联的版本控制系统代码库。ServiceNow DevOps会从Git或GitHub等集成SCM工具中明确捕获这些事件。 | ||
| 为什么重要 跟踪提交记录可细致了解开发进度和活动频率,并帮助您将具体代码变更与上级开发事项关联起来。 获取位置 作为明确事件记录在ServiceNow DevOps的Commits[sn_devops_commit]表中,该表由集成源代码管理系统发送的webhook填充。 采集 收到SCM工具发送的提交webhook时记录。 事件类型 explicit | |||
| 已准备发布 | 该活动表示开发事项已通过所有质量门,并已纳入特定发布版本。通常可根据事项与Release记录建立关联,或状态变更为“Ready for Deployment”推断。 | ||
| 为什么重要 该步骤表示事项在技术和功能上均已完成。处于此状态的时间,可能代表计划部署窗口前的排队时间。 获取位置 根据“State”字段变更为“Ready for Release”,或跟踪开发事项记录中“Release”字段被填充或更新的时间确定。 采集 根据状态变更或与Release记录建立关联推断。 事件类型 inferred | |||
| 已开始部署到生产环境 | 该活动标志着向生产环境部署的流水线启动。当CI/CD流水线的生产阶段开始执行时,ServiceNow DevOps会明确记录此事件。 | ||
| 为什么重要 这标志着生命周期最后且通常最关键的阶段开始。跟踪该阶段有助于分析部署持续时间并发现自动化机会。 获取位置 在Stage Execution Run[sn_devops_stage_execution]表中明确记录,并筛选与生产环境相关的阶段。 采集 从Pipeline Execution中生产部署阶段的开始时间获取。 事件类型 explicit | |||
| 已识别返工 | 表示测试期间发现问题,需要将事项退回开发阶段。通常通过观察流程反向移动来推断,例如状态从“In QA”变回“In Progress”。 | ||
| 为什么重要 跟踪返工对于了解质量问题和流程低效至关重要。该活动频率较高,通常说明开发过程或需求清晰度存在问题。 获取位置 通过分析sys_audit或sys_history_line表中的“State”字段历史记录推断。状态从后续阶段(例如“Testing”)变更为前序阶段(例如“In Progress”),即表示发生返工。 采集 根据反向状态转换推断,例如“Testing”→“In Progress”。 事件类型 inferred | |||
| 开发事项已取消 | 表示开发事项在完成前终止。这是一种替代性结束状态,通常根据事项状态设置为“Cancelled”或“Closed Incomplete”推断。 | ||
| 为什么重要 跟踪取消情况有助于识别无效投入,了解范围变更或优先级调整的原因,并更完整地呈现所有可能的流程结果。 获取位置 根据开发事项记录中“State”字段更新为“Cancelled”等终止性未完成状态的时间戳推断。 采集 根据状态变更为“Cancelled”或等效终止状态推断。 事件类型 inferred | |||
| 构建已触发 | 该事件表示CI/CD流水线构建开始,通常由代码提交触发。ServiceNow DevOps会将其记录为流水线执行,并关联回发起该执行的开发事项。 | ||
| 为什么重要 该活动连接开发与自动化测试或部署。分析提交到构建开始之间的时间,有助于发现CI/CD流程中的延误。 获取位置 当集成CI/CD工具(例如Jenkins、Azure DevOps)启动构建时,系统会在Pipeline Execution[sn_devops_pipeline_execution]表中明确记录。 采集 从Pipeline Execution表中记录的开始时间获取。 事件类型 explicit | |||
| 设计已开始 | 表示正在为开发事项创建技术设计或解决方案架构的阶段。通常根据开发事项记录中的状态或状态字段变更推断,例如变更为“Design”或“Solutioning”。 | ||
| 为什么重要 分析设计阶段的持续时间,有助于在开发工作开始前发现需求转化和解决方案规划中的瓶颈。 获取位置 根据开发事项记录(例如Story[rm_story])中的状态转换推断。请查找“State”字段或自定义“Stage”字段是否变更为与设计相关的值。 采集 根据状态变更为“Design”或类似状态推断。 事件类型 inferred | |||
提取指南
步骤
- 了解状态模型:在创建报告之前,记录开发项目状态字段中的具体值(例如Story
[rm_story]或Defect[rm_defect]表中的状态值),并明确这些值对应的活动。例如,状态值“In Progress”可能对应“开发已开始”活动。 - 进入报告创建页面:登录ServiceNow实例。在筛选导航器中,进入
Reports > View / Run,然后点击Create a report按钮。 - 创建状态变更报告:创建第一份报告,用于捕获由状态驱动的活动。配置如下:
- 报告名称:
ProcessMind - State Change Events - 来源类型:
Table - 表:
Audit [sys_audit] - 类型:
List - 配置列:添加
Document key、Created on、Table name、Field name、Old value和New value。 - 筛选:将
Table name设置为开发项目表之一(例如Story),将Field name设置为状态字段(例如State)。在Created on字段上添加所需时间段的日期筛选。
- 报告名称:
- 创建项目创建报告:为初始创建事件创建新报告。
- 报告名称:
ProcessMind - Item Creation Events - 来源类型:
Table - 表:
Story [rm_story](或您的主要开发项目表) - 类型:
List - 配置列:添加所需属性对应的列,例如
数字、Created on、Assigned to、Priority、State等。 - 筛选:在
Created on字段上应用日期筛选。
- 报告名称:
- 创建代码提交报告:为与提交相关的明确DevOps事件创建报告。
- 报告名称:
ProcessMind - Commit Events - 来源类型:
Table - 表:
Commit [sn_devops_commit] - 类型:
List - 配置列:添加
Work item、Commit time、Author等列。 - 筛选:在
Commit time字段上应用日期筛选。
- 报告名称:
- 创建构建和部署报告:按照上一步的流程,为
Build [sn_devops_build]和Deployment [sn_devops_deployment]表重复创建报告。这些表包含Build Triggered、Deployment to Production Started、Deployed to Production和Deployment Failed活动的记录。 - 导出所有报告:分别运行创建的报告。对于每份报告,点击上下文菜单图标(三个点或向下箭头),选择
Export > CSV或Export > Excel,并保存所有文件。 - 合并并转换数据:在电子表格程序中打开导出文件,或使用数据准备工具。将所有文件中的数据手动合并到一个工作表中。创建所需的事件日志列(
DevelopmentItem、ActivityName、EventTime等),并将源列中的数据映射到这些列。例如,将审计报告中的Document key和Story报告中的数字映射到DevelopmentItem列。 - 映射活动名称:通过转换源数据创建
ActivityName列。对于状态变更报告,使用已记录的状态模型,将New value条目映射到活动名称(例如,将状态Testing映射为QA Testing Started)。对于其他报告,为每行分配固定的活动名称(例如,提交导出文件中的所有行均设为Code Committed)。 - 完成并保存:为所有行添加包含固定值的
SourceSystem和LastDataUpdate列。确保所有时间戳格式一致。将最终合并文件保存为单个CSV文件,即可上传到ProcessMind。
配置
- 必需表:提取所需的主要表包括用于推断事件的
Audit [sys_audit]、具体开发项表(例如Story [rm_story]、Defect [rm_defect]),以及ServiceNow DevOps核心表:Commit [sn_devops_commit]、Build [sn_devops_build]和Deployment [sn_devops_deployment]。 - 关键筛选条件:最重要的筛选条件是日期范围,应在所有报告中统一应用于
Created on、Commit time或开始时间等时间戳字段。对于sys_audit报告,必须按Table name(例如rm_story)和Field name(例如state)筛选,仅保留相关状态变更数据。 - 日期范围建议:建议提取3至6个月的数据,以确保数据集具有代表性,同时避免性能问题。对于规模较大的系统,可考虑按月分批提取。
- 状态模型定义:您必须清楚了解组织的工作项状态模型,才能将
sys_audit表中捕获的状态值正确映射为相应业务活动,例如'QA Testing Started'或'UAT Approved'。 - 前提条件:执行提取的用户需要拥有
report_user角色或创建、运行报告所需的同等权限,还需要具备上述DevOps和应用开发表的读取权限。必须安装ServiceNow DevOps插件,并将其与SCM和CI/CD工具完成有效集成。
a 示例查询 sql
/*
This extraction method uses the ServiceNow report builder UI. The following sections describe the configuration for each report that must be created and exported.
The exported data must then be manually combined and transformed into a single event log file.
*/
---
-- REPORT 1: Item Creation Events
---
Report_Name: ProcessMind - Item Creation Events
Source_Table: rm_story
Report_Type: List
Columns:
- Number (maps to DevelopmentItem)
- sys_created_on (maps to EventTime)
- 'Development Item Created' (create a formula or static column for ActivityName)
- Assigned to (maps to AssignedDeveloper)
- Priority (maps to DevelopmentItemPriority)
- State (maps to DevelopmentItemState)
- cmdb_ci (maps to ModuleComponentAffected)
- Type (maps to DevelopmentItemType)
- Assignment group (maps to AssignmentGroup)
Filters:
- sys_created_on ON Last 6 months
---
-- REPORT 2: Inferred State Change Events
---
Report_Name: ProcessMind - State Change Events
Source_Table: sys_audit
Report_Type: List
Columns:
- documentkey (maps to DevelopmentItem)
- sys_created_on (maps to EventTime)
- newvalue (maps to ActivityName, requires translation)
- user (maps to AssignedDeveloper)
ActivityName_Mapping_Logic (Example):
- WHEN newvalue IS '[Your Design State]' THEN 'Design Started'
- WHEN newvalue IS '[Your In Progress State]' THEN 'Development Started'
- WHEN newvalue IS '[Your QA State]' THEN 'QA Testing Started'
- WHEN oldvalue IS '[Your QA State]' AND newvalue IS '[Your In Progress State]' THEN 'Rework Identified'
- WHEN oldvalue IS '[Your QA State]' AND newvalue IS '[Your UAT State]' THEN 'QA Testing Completed'
- WHEN newvalue IS '[Your UAT State]' THEN 'UAT Started'
- WHEN newvalue IS '[Your UAT Approved State]' THEN 'UAT Approved'
- WHEN newvalue IS '[Your Release Ready State]' THEN 'Prepared For Release'
- WHEN newvalue IS '[Your Cancelled State]' THEN 'Development Item Cancelled'
Filters:
- tablename = 'rm_story'
- fieldname = 'state'
- sys_created_on ON Last 6 months
---
-- REPORT 3: Code Commit Events
---
Report_Name: ProcessMind - Commit Events
Source_Table: sn_devops_commit
Report_Type: List
Columns:
- work_item.number (maps to DevelopmentItem)
- commit_time (maps to EventTime)
- 'Code Committed' (create a formula or static column for ActivityName)
- author.name (maps to AssignedDeveloper)
Filters:
- commit_time ON Last 6 months
---
-- REPORT 4: Build Events
---
Report_Name: ProcessMind - Build Events
Source_Table: sn_devops_build
Report_Type: List
Columns:
- work_item.number (maps to DevelopmentItem)
- start_time (maps to EventTime)
- 'Build Triggered' (create a formula or static column for ActivityName)
Filters:
- start_time ON Last 6 months
---
-- REPORT 5: Deployment Events
---
Report_Name: ProcessMind - Deployment Events
Source_Table: sn_devops_deployment
Report_Type: List
Columns:
- work_item.number (maps to DevelopmentItem)
- start_time (maps to EventTime for 'Started' activities)
- end_time (maps to EventTime for 'Completed' or 'Failed' activities)
- state (maps to ActivityName, requires translation)
ActivityName_Mapping_Logic:
- WHEN state IS 'in_progress' THEN 'Deployment to Production Started'
- WHEN state IS 'successful' THEN 'Deployed to Production'
- WHEN state IS 'failed' THEN 'Deployment Failed'
Filters:
- start_time ON Last 6 months
- [Filter for production deployments based on your environment configuration]
---
-- Additional events like 'Code Review Performed' may require a separate report
-- on a table like `sn_devops_pull_request` if available and configured.
--- 步骤
- 前提条件:确保您可以访问ServiceNow实例,并获得具有读取权限的专用服务账户,
itil和sn_devops.viewer角色可作为起点。该用户需要访问rm_story、sys_audit以及sn_devops_*架构中的表。 - 安装ServiceNow ODBC Driver:从ServiceNow支持门户下载适用于您操作系统的ServiceNow ODBC Driver,并按照提供的说明完成安装。
- 配置DSN:在运行查询的计算机上设置新的系统DSN(Data Source Name)。在ODBC数据源管理器中添加ServiceNow驱动,并配置实例URL,例如
yourinstance.service-now.com、用户名和密码。 - 使用SQL客户端连接:使用DBeaver、Microsoft SQL Server Management Studio(通过链接服务器)等SQL客户端工具,或使用带ODBC库的Python等脚本语言,通过已配置的DSN连接ServiceNow。
- 确定状态模型:运行查询前,必须确定组织在开发项目表,例如
rm_story和rm_defect中使用的state字段确切值。提供的查询使用“In Progress”或“In QA”等常见示例,您需要将其替换为实际值。 - 自定义SQL查询:将提供的SQL查询复制到客户端中。修改查询顶部的占位配置,包括提取开始日期,以及对应开发生命周期活动的具体状态值。
- 执行查询:通过ODBC连接对ServiceNow数据库运行完整SQL查询。具体耗时取决于日期范围和数据量,可能需要较长时间。
- 检查数据:查询完成后,简要检查返回的数据集。确认包含多种活动,并确保
DevelopmentItem、ActivityName和EventTime等关键列已按预期填充。 - 导出为CSV:将完整结果集导出为CSV文件。确保文件采用UTF-8编码,列标题与ProcessMind要求的属性名称一致,例如
DevelopmentItem、ActivityName和EventTime。 - 准备上传:确保最终CSV文件末尾没有空行,并且
EventTime和LastDataUpdate的日期格式一致且受ProcessMind支持,例如YYYY-MM-DD HH:MM:SS。
配置
- 前提条件:需要访问已启用DevOps模块的ServiceNow实例,并使用对所需表具有读取权限的专用用户账户。客户端计算机必须安装并配置ServiceNow ODBC Driver。
- ODBC Driver配置:连接需要实例URL、用户名,以及密码或OAuth令牌。运行复杂查询前,务必测试DSN连接。
- 日期范围筛选:提供的查询包含占位条件
s.sys_created_on >= '2023-01-01',用于限制提取数据量。强烈建议提取明确时间段的数据,例如最近6至12个月,以确保查询耗时可控。 - 状态模型自定义:推断事件的准确性完全取决于状态模型。您必须将占位状态值,例如
[Your 'In Progress' State Value]和[Your 'In QA' State Value],替换为ServiceNow配置中使用的确切值。状态值区分大小写。 - 工作项目表:查询针对Story表(
rm_story)编写。如果组织还使用Defect(rm_defect)、Enhancement(rm_enhancement)或其他任务类型,必须在初始DevItems公用表表达式(CTE)中使用UNION ALL添加这些表。 - 性能:直接查询生产环境中的ServiceNow实例可能影响性能。建议在业务低峰期执行大型提取。对于超大数据集,可基于
sys_updated_on字段采用增量提取策略。
a 示例查询 sql
WITH DevItems AS (
-- This CTE selects the base set of development items to analyze.
-- Add other tables like rm_defect or rm_enhancement here using UNION ALL if needed.
SELECT
s.sys_id,
s.number,
s.sys_created_on,
s.sys_updated_on,
s.assigned_to,
s.priority,
s.state,
s.cmdb_ci, -- Module/Component Affected
s.sys_class_name, -- Development Item Type
s.assignment_group,
DATEDIFF(second, s.sys_created_on, s.closed_at) AS cycle_time_seconds
FROM rm_story s
WHERE s.sys_created_on >= '2023-01-01' -- *** Placeholder: Set your desired start date ***
),
StateChanges AS (
-- This CTE unnests the audit trail for state changes, which are used for inferred activities.
SELECT
a.documentkey AS item_sys_id,
a.sys_created_on AS change_time,
a.oldvalue,
a.newvalue,
-- *** Placeholder: Define the numeric order of your states to detect rework. Adjust values and names. ***
CASE a.oldvalue
WHEN '1' THEN 1 -- Open
WHEN '[Your 'Design' State Value]' THEN 2
WHEN '[Your 'In Progress' State Value]' THEN 3
WHEN '[Your 'In QA' State Value]' THEN 4
WHEN '[Your 'In UAT' State Value]' THEN 5
ELSE 0
END AS old_state_order,
CASE a.newvalue
WHEN '1' THEN 1 -- Open
WHEN '[Your 'Design' State Value]' THEN 2
WHEN '[Your 'In Progress' State Value]' THEN 3
WHEN '[Your 'In QA' State Value]' THEN 4
WHEN '[Your 'In UAT' State Value]' THEN 5
ELSE 0
END AS new_state_order
FROM sys_audit a
WHERE a.tablename = 'rm_story' AND a.fieldname = 'state'
)
-- 1. Development Item Created
SELECT
i.number AS DevelopmentItem,
'Development Item Created' AS ActivityName,
i.sys_created_on AS EventTime,
'ServiceNow DevOps' AS SourceSystem,
GETDATE() AS LastDataUpdate,
us.name AS AssignedDeveloper,
i.priority AS DevelopmentItemPriority,
i.state AS DevelopmentItemState,
ci.name AS ModuleComponentAffected,
i.sys_class_name AS DevelopmentItemType,
grp.name AS AssignmentGroup,
i.cycle_time_seconds AS DevelopmentItemCycleTime,
CAST(0 AS BIT) AS IsRework
FROM DevItems i
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id
LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id
LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
UNION ALL
-- 2. Design Started
SELECT i.number, 'Design Started', sc.change_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, sc.newvalue, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM StateChanges sc JOIN DevItems i ON sc.item_sys_id = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE sc.newvalue = '[Your ''Design'' State Value]' -- *** Placeholder: Adjust state value ***
UNION ALL
-- 3. Development Started
SELECT i.number, 'Development Started', sc.change_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, sc.newvalue, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM StateChanges sc JOIN DevItems i ON sc.item_sys_id = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE sc.newvalue = '[Your ''In Progress'' State Value]' AND sc.old_state_order < 3 -- *** Placeholder: Adjust state value and order ***
UNION ALL
-- 4. Code Committed
SELECT i.number, 'Code Committed', c.committed_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, i.state, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM sn_devops_commit c JOIN DevItems i ON c.work_item = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
UNION ALL
-- 5. Build Triggered
SELECT i.number, 'Build Triggered', b.start_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, i.state, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM sn_devops_build b JOIN sn_devops_commit_build cb ON b.sys_id = cb.build JOIN sn_devops_commit c ON cb.commit = c.sys_id JOIN DevItems i ON c.work_item = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
UNION ALL
-- 6. Code Review Performed
SELECT i.number, 'Code Review Performed', pr.closed_at, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, i.state, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM sn_devops_pull_request pr JOIN DevItems i ON pr.work_item = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE pr.state = 'merged' -- Or 'closed', depending on process
UNION ALL
-- 7. QA Testing Started
SELECT i.number, 'QA Testing Started', sc.change_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, sc.newvalue, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM StateChanges sc JOIN DevItems i ON sc.item_sys_id = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE sc.newvalue = '[Your ''In QA'' State Value]' -- *** Placeholder: Adjust state value ***
UNION ALL
-- 8. Rework Identified
SELECT i.number, 'Rework Identified', sc.change_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, sc.newvalue, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(1 AS BIT)
FROM StateChanges sc JOIN DevItems i ON sc.item_sys_id = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE sc.new_state_order < sc.old_state_order AND sc.new_state_order > 1 -- Moved to an earlier state
UNION ALL
-- 9. QA Testing Completed
SELECT i.number, 'QA Testing Completed', sc.change_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, sc.newvalue, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM StateChanges sc JOIN DevItems i ON sc.item_sys_id = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE sc.oldvalue = '[Your ''In QA'' State Value]' AND sc.new_state_order > sc.old_state_order -- *** Placeholder: Adjust state value ***
UNION ALL
-- 10. UAT Started
SELECT i.number, 'UAT Started', sc.change_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, sc.newvalue, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM StateChanges sc JOIN DevItems i ON sc.item_sys_id = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE sc.newvalue = '[Your ''In UAT'' State Value]' -- *** Placeholder: Adjust state value ***
UNION ALL
-- 11. UAT Approved
SELECT i.number, 'UAT Approved', sc.change_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, sc.newvalue, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM StateChanges sc JOIN DevItems i ON sc.item_sys_id = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE sc.oldvalue = '[Your ''In UAT'' State Value]' AND sc.new_state_order > sc.old_state_order -- *** Placeholder: Adjust state value ***
UNION ALL
-- 12. Prepared For Release
SELECT i.number, 'Prepared For Release', sc.change_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, sc.newvalue, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM StateChanges sc JOIN DevItems i ON sc.item_sys_id = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE sc.newvalue = '[Your ''Ready for Release'' State Value]' -- *** Placeholder: Adjust state value ***
UNION ALL
-- 13. Deployment to Production Started
SELECT i.number, 'Deployment to Production Started', se.start_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, i.state, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM sn_devops_step_execution se JOIN sn_devops_artifact_build sab ON se.deployable = sab.sys_id JOIN sn_devops_commit_build cb ON sab.build = cb.build JOIN sn_devops_commit c ON cb.commit = c.sys_id JOIN DevItems i ON c.work_item = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE se.stage_name = 'Production' -- *** Placeholder: Adjust stage name ***
UNION ALL
-- 14. Deployed to Production
SELECT i.number, 'Deployed to Production', se.end_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, i.state, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM sn_devops_step_execution se JOIN sn_devops_artifact_build sab ON se.deployable = sab.sys_id JOIN sn_devops_commit_build cb ON sab.build = cb.build JOIN sn_devops_commit c ON cb.commit = c.sys_id JOIN DevItems i ON c.work_item = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE se.stage_name = 'Production' AND se.result = 'SUCCESS' -- *** Placeholder: Adjust stage name and result value ***
UNION ALL
-- 15. Deployment Failed
SELECT i.number, 'Deployment Failed', se.end_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, i.state, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM sn_devops_step_execution se JOIN sn_devops_artifact_build sab ON se.deployable = sab.sys_id JOIN sn_devops_commit_build cb ON sab.build = cb.build JOIN sn_devops_commit c ON cb.commit = c.sys_id JOIN DevItems i ON c.work_item = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE se.stage_name = 'Production' AND se.result = 'FAILURE' -- *** Placeholder: Adjust stage name and result value ***
UNION ALL
-- 16. Development Item Cancelled
SELECT i.number, 'Development Item Cancelled', sc.change_time, 'ServiceNow DevOps', GETDATE(), us.name, i.priority, sc.newvalue, ci.name, i.sys_class_name, grp.name, i.cycle_time_seconds, CAST(0 AS BIT)
FROM StateChanges sc JOIN DevItems i ON sc.item_sys_id = i.sys_id
LEFT JOIN sys_user us ON i.assigned_to = us.sys_id LEFT JOIN cmdb_ci ci ON i.cmdb_ci = ci.sys_id LEFT JOIN sys_user_group grp ON i.assignment_group = grp.sys_id
WHERE sc.newvalue = '[Your ''Cancelled'' State Value]'; -- *** Placeholder: Adjust state value *** 立即优化您的软件开发生命周期,别再延误
精准定位低效环节,将SDLC周期时间缩短30%或更多。
无需信用卡,立即开始优化