File: //usr/share/filebeat/module/zoom/webhook/ingest/phone.yml
description: Pipeline for parsing Zoom phone webhooks
processors:
- append:
field: event.type
value: info
- append:
field: event.type
value: creation
if: "['phone.caller_ringing', 'phone.callee_ringing'].contains(ctx?.event?.action)"
- append:
field: event.type
value: start
if: "['phone.callee_answered', 'phone.caller_connected'].contains(ctx?.event?.action)"
- append:
field: event.type
value: end
if: "['phone.callee_missed', 'phone.callee_ended', 'phone.caller_ended'].contains(ctx?.event?.action)"
- rename:
field: zoom.object
target_field: zoom.phone
ignore_missing: true
- uri_parts:
field: zoom.phone.download_url
ignore_failure: true
if: ctx?.zoom?.phone?.download_url != null
- rename:
field: zoom.phone.download_url
target_field: url.full
ignore_missing: true
- date:
field: zoom.phone.ringing_start_time
target_field: '@timestamp'
formats:
- ISO_INSTANT
if: "['phone.callee_ringing', 'phone.caller_ringing', 'phone.caller_ended'].contains(ctx?.event?.action)"
ignore_failure: true
- date:
field: zoom.phone.connected_start_time
target_field: '@timestamp'
formats:
- ISO_INSTANT
if: ctx?.event?.action == 'phone.caller_connected'
ignore_failure: true
- date:
field: zoom.phone.answer_start_time
target_field: '@timestamp'
formats:
- ISO_INSTANT
if: "ctx?.zoom?.phone.answer_start_time != null && ctx?.event?.action == 'phone.callee_answered'"
ignore_failure: true
- date:
field: zoom.phone.call_end_time
target_field: '@timestamp'
formats:
- ISO_INSTANT
if: "['phone.callee_missed', 'phone.callee_ended', 'phone.caller_ended', 'phone.callee_rejected'].contains(ctx?.event?.action)"
ignore_failure: true
- date:
field: zoom.phone.date_time
target_field: '@timestamp'
formats:
- ISO_INSTANT
if: ctx?.event?.action == 'phone.voicemail_received'
ignore_failure: true
# Calculates duration when duration is unknown but start and end time is known (with ringing_start_time)
- script:
lang: painless
if: "ctx?.zoom?.phone?.ringing_start_time != null && ctx?.zoom?.phone?.answer_start_time == null && ctx?.zoom?.phone?.call_end_time != null && ctx?.zoom?.duration == null"
source: >-
ctx.event.start = ctx.zoom.phone.ringing_start_time;
ctx.event.end = ctx.zoom.phone.call_end_time;
ZonedDateTime start = ZonedDateTime.parse(ctx.event.start);
ZonedDateTime end = ZonedDateTime.parse(ctx.event.end);
ctx.event.duration = ChronoUnit.NANOS.between(start, end);
# Calculates duration when duration is unknown but start and end time is known (with answer_start_time)
- script:
lang: painless
if: "ctx?.zoom?.phone?.ringing_start_time == null && ctx?.zoom?.phone?.answer_start_time != null && ctx?.zoom?.phone?.call_end_time != null && ctx?.zoom?.duration == null"
source: >-
ctx.event.start = ctx.zoom.phone.answer_start_time;
ctx.event.end = ctx.zoom.phone.call_end_time;
ZonedDateTime start = ZonedDateTime.parse(ctx.event.start);
ZonedDateTime end = ZonedDateTime.parse(ctx.event.end);
ctx.event.duration = ChronoUnit.NANOS.between(start, end);
# Duration is in minutes, so multiply by seconds and then multiply again to convert seconds to nano
- script:
lang: painless
if: ctx?.zoom?.duration != null
source: >-
ctx.event.duration = Integer.parseInt(ctx.zoom.duration) * 60L * 1000000000L;
# Moving all voicemail related fields to their proper nested fields
# that already exists for all other phone webhooks
- rename:
field: zoom.phone.callee_user_id
target_field: zoom.phone.callee.user_id
ignore_missing: true
- rename:
field: zoom.phone.callee_extension_type
target_field: zoom.phone.callee.extension_type
ignore_missing: true
- rename:
field: zoom.phone.callee_id
target_field: zoom.phone.callee.id
ignore_missing: true
- rename:
field: zoom.phone.callee_name
target_field: zoom.phone.callee.name
ignore_missing: true
- rename:
field: zoom.phone.callee_number
target_field: zoom.phone.callee.phone_number
ignore_missing: true
- rename:
field: zoom.phone.callee_number_type
target_field: zoom.phone.callee.number_type
ignore_missing: true
- rename:
field: zoom.phone.callee_user_id
target_field: zoom.phone.callee.user_id
ignore_missing: true
- rename:
field: zoom.phone.callee_extension_type
target_field: zoom.phone.callee.extension_type
ignore_missing: true
- rename:
field: zoom.phone.caller_id
target_field: zoom.phone.caller.id
ignore_missing: true
- rename:
field: zoom.phone.caller_name
target_field: zoom.phone.caller.name
ignore_missing: true
- rename:
field: zoom.phone.caller_number
target_field: zoom.phone.caller.phone_number
ignore_missing: true
- rename:
field: zoom.phone.caller_number_type
target_field: zoom.phone.caller.number_type
ignore_missing: true
- append:
field: related.user
value: "{{zoom.phone.callee.user_id}}"
allow_duplicates: false
if: ctx?.zoom?.phone?.callee?.user_id != null
- append:
field: related.user
value: "{{zoom.phone.callee_user_id}}"
allow_duplicates: false
if: ctx?.zoom?.phone?.callee_user_id != null
- append:
field: related.user
value: "{{zoom.phone.caller.user_id}}"
allow_duplicates: false
if: ctx?.zoom?.phone?.caller?.user_id != null
- remove:
field: zoom.phone.date_time
ignore_missing: true
if: ctx?.event?.action == 'phone.voicemail_received'
- set:
field: source.user.id
value: '{{zoom.phone.caller.user_id}}'
ignore_empty_value: true
- set:
field: destination.user.id
value: '{{zoom.phone.callee.user_id}}'
ignore_empty_value: true
on_failure:
- set:
field: error.message
value: '{{ _ingest.on_failure_message }}'