ACC basic metering: data collection and last-used timestamp processing<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } .kb-wrapper{font-family:'Lato',sans-serif;font-size:12pt;line-height:1.7;color:#000;max-width:100%} .kb-wrapper p{margin:0 0 12px 0} .kb-wrapper ul{margin:0 0 12px 0;padding-left:24px} .kb-wrapper li{margin-bottom:8px} .kb-wrapper h2{font-size:14pt;font-weight:900;border-bottom:2px solid #e8fce4;padding-bottom:4px;margin:28px 0 10px 0} .kb-wrapper h3{font-size:12pt;font-weight:900;border-bottom:2px solid #e8fce4;padding-bottom:4px;margin:20px 0 8px 0} .kb-wrapper .note{border-left:4px solid #52B8FF;background:#e6f4ff;padding:10px 14px;margin:14px 0} .kb-wrapper .warning{border-left:4px solid #e6a817;background:#fff4e0;padding:10px 14px;margin:14px 0} .kb-wrapper code{background:#e6f0f5;color:#032D42;border:1px solid #b8cfd8;padding:1px 4px;border-radius:3px;font-family:monospace;font-size:11pt} .kb-wrapper pre{background:#e6f0f5;color:#032D42;border:1px solid #b8cfd8;padding:12px 16px;overflow-x:auto;font-family:monospace;font-size:11pt;line-height:1.5;margin:10px 0 16px 0;border-radius:3px} .kb-wrapper ol.steps{list-style:none;padding:0;counter-reset:step-counter} .kb-wrapper ol.steps>li{counter-increment:step-counter;display:flex;align-items:flex-start;margin-bottom:16px;list-style:none} .kb-wrapper ol.steps>li::before{content:counter(step-counter);flex-shrink:0;width:28px;height:28px;border-radius:50%;background:#032D42;color:#63DF4E;font-weight:900;font-size:11pt;text-align:center;line-height:28px;display:block;margin-right:16px} .kb-wrapper ol.steps>li>div{flex:1} .kb-wrapper ol.sub-steps{list-style:lower-alpha;padding-left:24px;margin:10px 0 4px 0} .kb-wrapper table{width:100%;border-collapse:collapse;margin:14px 0;font-size:12pt} .kb-wrapper th{background:#032D42;color:#fff;padding:9px 12px;text-align:left;font-weight:700} .kb-wrapper td{padding:8px 12px;border-bottom:1px solid #ddd;vertical-align:top} .kb-wrapper tr:nth-child(even) td{background:#e8fce4} .kb-wrapper p.disclaimer{font-size:10pt;font-style:italic} Summary This article describes how the Agent Client Collector (ACC) Basic Metering feature collects a last-used timestamp for each installed software entry on managed endpoints, and how that data flows to the ServiceNow instance to populate the Last Used field on software installation records. Basic metering runs as part of the installed_software_with_sam_metering check on the ACC agent. For each installed software entry, it records a last_used value indicating when that software was last run on the endpoint. Basic metering collects a single timestamp per software entry — it does not collect session duration or process-level usage data, which are captured by Advanced Metering in the same check module. The check module produces two types of output: installed_software_with_sam_metering | +-- Basic Metering → last_used on each installed_software entry | → cmdb_sam_sw_install.last_used | → samp_sw_usage.last_used_time (SAM reclamation) | +-- Advanced Metering → sam_advanced array (process-level usage data) → sn_acc_vis_content_sam_software_usage_staging Data collection by operating system Basic metering behavior differs by operating system. The following sections describe the data source and collection method for each platform. Windows On Windows, basic metering reads the Windows UserAssist registry using osqueryi — a one-off query tool, not the osqueryd daemon. UserAssist tracks per-user application run history maintained by the Windows shell. At check execution time, the agent runs the following queries: UserAssist table — primary metering source select p.path, p.last_execution_time, p.count, u.username from users u CROSS JOIN userassist p on p.sid=u.uuid where p.last_execution_time != "0" Returns the executable path, last run time (Unix epoch seconds), run count, and user name for each application. Boot startup programs select name from registry where key like 'HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run' System uptime — used to calculate boot time: select total_seconds from uptime Boot time = Time.now.to_i - total_seconds Active Directory (AD) domain — queried once per check run and set on each software entry that has a UserAssist match. The agent queries via PowerShell first, with Windows Management Instrumentation (WMI) as a fallback: Primary: (Get-CimInstance -ClassName Win32_ComputerSystem).DomainFallback: wmic computersystem get domain /format:list Software name matching The agent fetches the entire UserAssist table into memory once, then matches each installed software name against it using up to four search patterns: PatternExample for "Microsoft Excel 16.0"Lowercased name — words up to first numeric tokenmicrosoft excelLowercased name without spacesmicrosoftexcelMicrosoft-specific — product name with prefix "Microsoft" removedexcelCustom override from SoftwareNameMapping.jsonVaries per entry The UserAssist entry with the highest last_execution_time among all matching paths is used. How last_used is set Software in the boot startup list: last_used is set to the boot time (Unix epoch)All other software: last_used is set to last_execution_time from the best UserAssist match (Unix epoch string) Software names beginning with Hotfix and names containing a pipe character (|) are excluded from metering. The agent also sets the following additional fields on matched software entries: path, username, ad_domain, count. The ad_domain value is used on the instance to look up the reporting user in the User [sys_user] table. When present, the lookup searches for both DOMAIN\username and username@DOMAIN formats against the field configured in the sn_acc_vis_content.column_name_for_user_mapping system property. When absent, the lookup falls back to a plain user name match. On environments where user records carry domain-qualified names, a missing ad_domain value causes the user lookup to fail, which silently prevents a software usage record from being written. macOS On macOS, basic metering queries the Spotlight metadata database using the mdls command — a metadata lookup service built into macOS. The agent runs the following command once for each installed application that has a valid path value: mdls "<software_path>" -name kMDItemLastUsedDate -name kMDItemFSOwnerUserID The following Spotlight attributes are extracted: Spotlight attributeValueUsed forkMDItemLastUsedDateYYYY-MM-DD HH:MM:SS +0000last_used timestampkMDItemFSOwnerUserIDNumeric user IDUser name lookup The kMDItemLastUsedDate value is converted to a Unix epoch seconds string: # input: "2022-03-15 13:04:46 +0000" # output: Unix epoch seconds as string, e.g. "1647349486" year, month, day = last_used[0..3], last_used[5..6], last_used[8..9] hours, minutes, seconds = last_used[11..12], last_used[14..15], last_used[17..18] unixTime = Time.new(year, month, day, hours, minutes, seconds).to_i.to_s The numeric user ID from kMDItemFSOwnerUserID is mapped to a user name using a lookup table built from the osquery query select username, uid from users. Important: The mdls command runs only for applications that have a path value. Application paths are populated during the software inventory phase of the check using system_profiler SPApplicationsDataType -json. Applications without a path receive no last_used value. Linux Basic metering is not implemented for Linux. The Linux agent collects only the software name, vendor, and version via rpm -q -a, with dpkg as a fallback. No last_used timestamp is collected on Linux endpoints. How last-used data is processed on the instance The last_used value collected by the agent travels two separate paths on the instance. Writing to software installation records When the agent check result reaches the instance, the last_used value for each software entry is converted to a GlideDateTime object before the record is written to the Software Installation [cmdb_sam_sw_install] table. The conversion accepts only two timestamp formats: Input formatExampleResult10-digit Unix epoch1647349486Converted to GlideDateTime8-digit date string (yyyyMMdd)20220315Converted to GlideDateTimeAny other format—Dropped; last_used field is not written Both Windows and macOS basic metering produce 10-digit Unix epoch values, which match the first accepted format. If the last_used field on a software installation record is blank after a successful check run, verify that the last_used value in the agent payload is exactly 10 digits. Writing to software usage records for SAM reclamation A second processing path handles Software Asset Management (SAM) reclamation data. For each software entry in the check result that has both a name and a last_used value, the instance attempts to write a record to the Software Usage [samp_sw_usage] table. These records drive SAM Professional license reclamation rules of type last_used_date. The following conditions must all be met for a usage record to be written: The SAM Professional plugin (com.snc.samp) is active on the instance.The system property sn_acc_vis_content.persist_sam_usage_metrics is set to true (default value).A matching software installation record exists in the Software Installation [cmdb_sam_sw_install] table for the configuration item (CI).A reclamation rule of type last_used_date is configured in the Reclamation Rules [samp_m2m_rule_product] table for the matched software product — or the property sn_acc_vis_content.disable_sam_reclamation_rules_for_licensable_softwares is set to true.The matched software has a normalized product with a publisher defined in the Software Discovery Model [cmdb_sam_sw_discovery_model] table.The user name reported by the agent matches a record in the User [sys_user] table. If any condition is not met, the record for that software is skipped without generating an error. The absence of records in samp_sw_usage is the primary indicator that one or more conditions were not met. Relevant system properties PropertyDefaultDescriptionsn_acc_vis_content.persist_sam_usage_metricstrueControls whether last-used data is written to the Software Usage [samp_sw_usage] table.sn_acc_vis_content.disable_sam_reclamation_rules_for_licensable_softwaresfalseWhen set to true, writes usage data for all licensable software regardless of whether a reclamation rule exists for that product.sn_acc_vis_content.column_name_for_user_mapping(empty)The User [sys_user] table field used to match the reporting user by domain-qualified name. Supports DOMAIN\username and username@DOMAIN formats. When empty, the lookup uses user_name only, without the AD domain. Set this property when user records on your instance carry domain-qualified names. Troubleshooting Windows: no last_used value on any software Verify that osqueryi is available and returning results on the endpoint. Confirm that UserAssist data is present by running the following query directly on the endpoint: osqueryi "select * from userassist limit 5" If no rows are returned, UserAssist tracking may be turned off or the endpoint may not have recent application run activity. Windows: some software has last_used, others do not Name-to-path matching failed for the affected software entries. Review SoftwareNameMapping.json for custom override entries for the affected software. Check the agent debug logs for the message "No matching entry found in userassist table" to confirm which entries are not matching. macOS: no last_used value on any software Verify that the affected software entries have a path value populated. The mdls command runs only for applications with a valid path from system_profiler. Software without a path receives no last_used value. Linux: no last_used value This is by design. Basic metering is not implemented for Linux endpoints. samp_sw_usage table is not receiving records Work through the following in order: Verify that the SAM Professional plugin (com.snc.samp) is active. Verify that the system property sn_acc_vis_content.persist_sam_usage_metrics is set to true. Verify that a reclamation rule of type last_used_date exists in the Reclamation Rules [samp_m2m_rule_product] table for the affected software product. Verify that the user name reported by the agent matches a record in the User [sys_user] table. Related links Using push-based Discovery and SAM together SAM Basic Metering Setup with ACC ACC advanced metering: SAM software total usage data collection and configuration