@@ -42,7 +42,9 @@ export interface AgentLocalMetadata extends AgentMetadata {
4242 } ;
4343 } ;
4444 host : {
45+ hostname : string ;
4546 id : string ;
47+ name : string ;
4648 } ;
4749 os : {
4850 name : string ;
@@ -78,17 +80,20 @@ export const updateEndpointOSTelemetry = (
7880 os : AgentLocalMetadata [ 'os' ] ,
7981 osTracker : OSTracker
8082) : OSTracker => {
81- const updatedOSTracker = cloneDeep ( osTracker ) ;
82- const { version : osVersion , platform : osPlatform , full : osFullName } = os ;
83- if ( osFullName && osVersion ) {
84- if ( updatedOSTracker [ osFullName ] ) updatedOSTracker [ osFullName ] . count += 1 ;
85- else {
86- updatedOSTracker [ osFullName ] = {
87- full_name : osFullName ,
88- platform : osPlatform ,
89- version : osVersion ,
90- count : 1 ,
91- } ;
83+ let updatedOSTracker = osTracker ;
84+ if ( os && typeof os === 'object' ) {
85+ updatedOSTracker = cloneDeep ( osTracker ) ;
86+ const { version : osVersion , platform : osPlatform , full : osFullName } = os ;
87+ if ( osFullName && osVersion ) {
88+ if ( updatedOSTracker [ osFullName ] ) updatedOSTracker [ osFullName ] . count += 1 ;
89+ else {
90+ updatedOSTracker [ osFullName ] = {
91+ full_name : osFullName ,
92+ platform : osPlatform ,
93+ version : osVersion ,
94+ count : 1 ,
95+ } ;
96+ }
9297 }
9398 }
9499
@@ -211,46 +216,53 @@ export const getEndpointTelemetryFromFleet = async (
211216 if ( ! endpointAgents || endpointAgentsCount < 1 ) return endpointTelemetry ;
212217
213218 // Use unique hosts to prevent any potential duplicates
214- const uniqueHostIds : Set < string > = new Set ( ) ;
219+ const uniqueHosts : Set < string > = new Set ( ) ;
215220 let osTracker : OSTracker = { } ;
216221 let dailyActiveCount = 0 ;
217222 let policyTracker : PoliciesTelemetry = { malware : { active : 0 , inactive : 0 , failure : 0 } } ;
218223
219224 for ( let i = 0 ; i < endpointAgentsCount ; i += 1 ) {
220- const { attributes : metadataAttributes } = endpointAgents [ i ] ;
221- const { last_checkin : lastCheckin , local_metadata : localMetadata } = metadataAttributes ;
222- const { host, os, elastic } = localMetadata as AgentLocalMetadata ; // AgentMetadata is just an empty blob, casting for our use case
223-
224- if ( ! uniqueHostIds . has ( host . id ) ) {
225- uniqueHostIds . add ( host . id ) ;
226- const agentId = elastic ?. agent ?. id ;
227- osTracker = updateEndpointOSTelemetry ( os , osTracker ) ;
228-
229- if ( agentId ) {
230- let agentEvents ;
231- try {
232- const response = await getLatestFleetEndpointEvent ( soClient , agentId ) ;
233- agentEvents = response . saved_objects ;
234- } catch ( error ) {
235- // If the request fails we do not obtain `active within last 24 hours for this agent` or policy specifics
236- }
237-
238- // AgentEvents will have a max length of 1
239- if ( agentEvents && agentEvents . length > 0 ) {
240- const latestEndpointEvent = agentEvents [ 0 ] ;
241- dailyActiveCount = updateEndpointDailyActiveCount (
242- latestEndpointEvent ,
243- lastCheckin ,
244- dailyActiveCount
225+ try {
226+ const { attributes : metadataAttributes } = endpointAgents [ i ] ;
227+ const { last_checkin : lastCheckin , local_metadata : localMetadata } = metadataAttributes ;
228+ const { host, os, elastic } = localMetadata as AgentLocalMetadata ;
229+
230+ // Although not perfect, the goal is to dedupe hosts to get the most recent data for a host
231+ // An agent re-installed on the same host will have the same id and hostname
232+ // A cloned VM will have the same id, but "may" have the same hostname, but it's really up to the user.
233+ const compoundUniqueId = `${ host ?. id } -${ host ?. hostname } ` ;
234+ if ( ! uniqueHosts . has ( compoundUniqueId ) ) {
235+ uniqueHosts . add ( compoundUniqueId ) ;
236+ const agentId = elastic ?. agent ?. id ;
237+ osTracker = updateEndpointOSTelemetry ( os , osTracker ) ;
238+
239+ if ( agentId ) {
240+ const { saved_objects : agentEvents } = await getLatestFleetEndpointEvent (
241+ soClient ,
242+ agentId
245243 ) ;
246- policyTracker = updateEndpointPolicyTelemetry ( latestEndpointEvent , policyTracker ) ;
244+
245+ // AgentEvents will have a max length of 1
246+ if ( agentEvents && agentEvents . length > 0 ) {
247+ const latestEndpointEvent = agentEvents [ 0 ] ;
248+ dailyActiveCount = updateEndpointDailyActiveCount (
249+ latestEndpointEvent ,
250+ lastCheckin ,
251+ dailyActiveCount
252+ ) ;
253+ policyTracker = updateEndpointPolicyTelemetry ( latestEndpointEvent , policyTracker ) ;
254+ }
247255 }
248256 }
257+ } catch ( error ) {
258+ // All errors thrown in the loop would be handled here
259+ // Not logging any errors to avoid leaking any potential PII
260+ // Depending on when the error is thrown in the loop some specifics may be missing, but it allows the loop to continue
249261 }
250262 }
251263
252264 // All unique hosts with an endpoint installed, thus all unique endpoint installs
253- endpointTelemetry . total_installed = uniqueHostIds . size ;
265+ endpointTelemetry . total_installed = uniqueHosts . size ;
254266 // Set the daily active count for the endpoints
255267 endpointTelemetry . active_within_last_24_hours = dailyActiveCount ;
256268 // Get the objects to populate our OS Telemetry
0 commit comments