1077 lines
36 KiB
Bash
1077 lines
36 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
###
|
|
# JItsi Log Observer - command line interface
|
|
#
|
|
# Bash script for Jitsi Meet components (Videobridge, Jicofo, etc.) logs parsing
|
|
# Command line interface (jilo-cli)
|
|
###
|
|
|
|
VERSION="0.1.1"
|
|
RELEASE_DATE="2024-06-18"
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" #"
|
|
|
|
### Configuration file (overrides default configs)
|
|
CONFIG_FILE="$SCRIPT_DIR/jilo.conf"
|
|
|
|
### Default configuration
|
|
|
|
# Default database type (sqlite, mysql|mariadb)
|
|
DEFAULT_DB_TYPE="sqlite"
|
|
# Default SQLite database file
|
|
DEFAULT_DB="$SCRIPT_DIR/jilo.db"
|
|
# Default MySQL/MariaDB configuration
|
|
DEFAULT_MYSQL_HOST="localhost"
|
|
DEFAULT_MYSQL_USER="jilo"
|
|
DEFAULT_MYSQL_PASS="jilopass"
|
|
DEFAULT_MYSQL_DB="jilo_db"
|
|
|
|
DEFAULT_NORMAL_TEXT="\033[0m"
|
|
DEFAULT_IMPORTANT_TEXT="\033[1m"
|
|
|
|
# Load configurations from the config file if it exists
|
|
if [[ -f "$CONFIG_FILE" ]]; then
|
|
source "$CONFIG_FILE"
|
|
fi
|
|
|
|
# use default values if not overriden by config file
|
|
DB=${DB:-$DEFAULT_DB}
|
|
DB_TYPE=${DB_TYPE:-$DEFAULT_DB_TYPE}
|
|
MYSQL_HOST=${MYSQL_HOST:-$DEFAULT_MYSQL_HOST}
|
|
MYSQL_USER=${MYSQL_USER:-$DEFAULT_MYSQL_USER}
|
|
MYSQL_PASS=${MYSQL_PASS:-$DEFAULT_MYSQL_PASS}
|
|
MYSQL_DB=${MYSQL_DB:-$DEFAULT_MYSQL_DB}
|
|
|
|
NORMAL_TEXT=${NORMAL_TEXT:-$DEFAULT_NORMAL_TEXT}
|
|
IMPORTANT_TEXT=${IMPORTANT_TEXT:-$DEFAULT_IMPORTANT_TEXT}
|
|
|
|
### DB queries
|
|
|
|
## conference related
|
|
|
|
db_conferences_all_formatted_template="
|
|
SELECT DISTINCT
|
|
c.jitsi_component,
|
|
(SELECT ce.time
|
|
FROM conference_events ce
|
|
WHERE
|
|
ce.conference_id = c.conference_id
|
|
AND
|
|
ce.conference_event = 'conference expired')
|
|
AS start,
|
|
(SELECT ce.time
|
|
FROM conference_events ce
|
|
WHERE
|
|
ce.conference_id = c.conference_id
|
|
AND
|
|
ce.conference_event = 'conference created')
|
|
AS end,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
(SELECT COUNT(pe.participant_id) AS participants
|
|
FROM participant_events pe
|
|
WHERE
|
|
pe.event_type = 'participant joining'
|
|
AND
|
|
pe.event_param = c.conference_id),
|
|
name_counts.name_count,
|
|
c.conference_host
|
|
FROM
|
|
conferences c
|
|
JOIN (
|
|
SELECT
|
|
conference_name,
|
|
COUNT(*) AS name_count
|
|
FROM
|
|
conferences
|
|
GROUP BY
|
|
conference_name
|
|
) AS name_counts ON c.conference_name = name_counts.conference_name
|
|
JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
WHERE (ce.time >= '%s 00:00:00' AND ce.time <= '%s 23:59:59')
|
|
ORDER BY
|
|
c.id;"
|
|
|
|
db_conference_by_id_template="
|
|
SELECT
|
|
pe.time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
pe.loglevel,
|
|
pe.event_type,
|
|
p.endpoint_id AS participant_id,
|
|
pe.event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
LEFT JOIN
|
|
participants p ON c.conference_id = p.conference_id
|
|
LEFT JOIN
|
|
participant_events pe ON p.endpoint_id = pe.participant_id
|
|
WHERE
|
|
c.conference_id = '%s'
|
|
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
|
|
|
UNION
|
|
|
|
SELECT
|
|
ce.time AS event_time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
ce.loglevel,
|
|
ce.conference_event AS event_type,
|
|
NULL AS participant_id,
|
|
ce.conference_param AS event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
WHERE
|
|
c.conference_id = '%s'
|
|
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|
|
|
ORDER BY
|
|
pe.time;"
|
|
|
|
db_conference_by_name_template="
|
|
SELECT
|
|
pe.time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
pe.loglevel,
|
|
pe.event_type,
|
|
p.endpoint_id AS participant_id,
|
|
pe.event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
LEFT JOIN
|
|
participants p ON c.conference_id = p.conference_id
|
|
LEFT JOIN
|
|
participant_events pe ON p.endpoint_id = pe.participant_id
|
|
WHERE
|
|
c.conference_name = '%s'
|
|
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
|
|
|
UNION
|
|
|
|
SELECT
|
|
ce.time AS event_time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
ce.loglevel,
|
|
ce.conference_event AS event_type,
|
|
NULL AS participant_id,
|
|
ce.conference_param AS event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
WHERE
|
|
c.conference_name = '%s'
|
|
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|
|
|
ORDER BY
|
|
pe.time;"
|
|
|
|
## participant related
|
|
|
|
db_participants_all_template="
|
|
SELECT DISTINCT
|
|
p.jitsi_component, p.endpoint_id, p.conference_id
|
|
FROM
|
|
participants p
|
|
JOIN
|
|
participant_events pe ON p.endpoint_id = pe.participant_id
|
|
WHERE
|
|
pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59'
|
|
ORDER BY p.id;"
|
|
|
|
db_conference_by_participant_id_template="
|
|
SELECT
|
|
pe.time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
pe.loglevel,
|
|
pe.event_type,
|
|
p.endpoint_id AS participant_id,
|
|
pe.event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
LEFT JOIN
|
|
participants p ON c.conference_id = p.conference_id
|
|
LEFT JOIN
|
|
participant_events pe ON p.endpoint_id = pe.participant_id
|
|
WHERE
|
|
p.endpoint_id = '%s'
|
|
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
|
|
|
UNION
|
|
|
|
SELECT
|
|
ce.time AS event_time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
ce.loglevel,
|
|
ce.conference_event AS event_type,
|
|
NULL AS participant_id,
|
|
ce.conference_param AS event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
WHERE
|
|
participant_id = '%s'
|
|
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|
|
|
ORDER BY
|
|
pe.time;"
|
|
|
|
db_participant_by_conference_id_template="
|
|
SELECT
|
|
pe.time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
pe.loglevel,
|
|
pe.event_type,
|
|
p.endpoint_id AS participant_id,
|
|
pe.event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
LEFT JOIN
|
|
participants p ON c.conference_id = p.conference_id
|
|
LEFT JOIN
|
|
participant_events pe ON p.endpoint_id = pe.participant_id
|
|
WHERE
|
|
c.conference_id = '%s'
|
|
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
|
|
|
UNION
|
|
|
|
SELECT
|
|
ce.time AS event_time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
ce.loglevel,
|
|
ce.conference_event AS event_type,
|
|
NULL AS participant_id,
|
|
ce.conference_param AS event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
WHERE
|
|
ce.conference_id = '%s'
|
|
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|
|
|
ORDER BY
|
|
pe.time;"
|
|
|
|
db_participant_by_conference_name_template="
|
|
SELECT
|
|
pe.time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
pe.loglevel,
|
|
pe.event_type,
|
|
p.endpoint_id AS participant_id,
|
|
pe.event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
LEFT JOIN
|
|
participants p ON c.conference_id = p.conference_id
|
|
LEFT JOIN
|
|
participant_events pe ON p.endpoint_id = pe.participant_id
|
|
WHERE
|
|
c.conference_name LIKE '%%%s%%'
|
|
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
|
|
|
UNION
|
|
|
|
SELECT
|
|
ce.time AS event_time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
ce.loglevel,
|
|
ce.conference_event AS event_type,
|
|
NULL AS participant_id,
|
|
ce.conference_param AS event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
WHERE c.conference_name LIKE '%%%s%%'
|
|
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|
|
|
ORDER BY
|
|
pe.time;"
|
|
|
|
db_participant_by_stats_id_template="
|
|
SELECT
|
|
pe.time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
pe.loglevel,
|
|
pe.event_type,
|
|
p.endpoint_id AS participant_id,
|
|
pe.event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
LEFT JOIN
|
|
participants p ON c.conference_id = p.conference_id
|
|
LEFT JOIN
|
|
participant_events pe ON p.endpoint_id = pe.participant_id
|
|
WHERE
|
|
pe.event_type = 'stats_id' AND pe.event_param LIKE '%%%s%%'
|
|
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
|
|
|
UNION
|
|
|
|
SELECT
|
|
ce.time AS event_time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
ce.loglevel,
|
|
ce.conference_event AS event_type,
|
|
NULL AS participant_id,
|
|
ce.conference_param AS event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
WHERE
|
|
event_type = 'stats_id' AND event_param LIKE '%%%s%%'
|
|
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|
|
|
ORDER BY
|
|
pe.time;"
|
|
|
|
db_participant_by_ip_template="
|
|
SELECT
|
|
pe.time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
pe.loglevel,
|
|
pe.event_type,
|
|
p.endpoint_id AS participant_id,
|
|
pe.event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
LEFT JOIN
|
|
participants p ON c.conference_id = p.conference_id
|
|
LEFT JOIN
|
|
participant_events pe ON p.endpoint_id = pe.participant_id
|
|
WHERE
|
|
pe.event_type = 'pair selected' AND pe.event_param = '%s'
|
|
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
|
|
|
UNION
|
|
|
|
SELECT
|
|
ce.time AS event_time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
ce.loglevel,
|
|
ce.conference_event AS event_type,
|
|
NULL AS participant_id,
|
|
ce.conference_param AS event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
WHERE
|
|
event_type = 'pair selected' AND event_param = '%s'
|
|
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|
|
|
ORDER BY
|
|
pe.time;"
|
|
|
|
## jitsi component related
|
|
|
|
# we use "jitsi_component = %s" (without quotes)
|
|
# to re-use the query for all components ("jitsi_component = jitsi_component")
|
|
# for specific component the single quotes are added upon loading the template
|
|
db_jitsi_components_template="
|
|
SELECT jitsi_component, loglevel, time, component_id, event_type, event_param
|
|
FROM
|
|
jitsi_components
|
|
WHERE
|
|
jitsi_component = %s
|
|
AND
|
|
(time >= '%s 00:00:00' AND time <= '%s 23:59:59')
|
|
ORDER BY
|
|
time;"
|
|
|
|
## time period related
|
|
|
|
db_events_by_period_template="
|
|
SELECT
|
|
pe.time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
pe.loglevel,
|
|
pe.event_type,
|
|
p.endpoint_id AS participant_id,
|
|
pe.event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
LEFT JOIN
|
|
participants p ON c.conference_id = p.conference_id
|
|
LEFT JOIN
|
|
participant_events pe ON p.endpoint_id = pe.participant_id
|
|
WHERE
|
|
pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59'
|
|
|
|
UNION
|
|
|
|
SELECT
|
|
ce.time AS event_time,
|
|
c.conference_id,
|
|
c.conference_name,
|
|
c.conference_host,
|
|
ce.loglevel,
|
|
ce.conference_event AS event_type,
|
|
NULL AS participant_id,
|
|
ce.conference_param AS event_param
|
|
FROM
|
|
conferences c
|
|
LEFT JOIN
|
|
conference_events ce ON c.conference_id = ce.conference_id
|
|
WHERE
|
|
event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59'
|
|
|
|
ORDER BY
|
|
pe.time;"
|
|
|
|
|
|
help="Usage:
|
|
$0 [OPTION]
|
|
Options:
|
|
--conference|-c [conference ID or name] - show specific conference(s), all of empty
|
|
--participant|-p [participant endpoint ID, conference ID, conference name, participant IP, or participant stats ID] - show specific participant(s), all if empty
|
|
--jitsi-component|-j [jvb|jicofo] - show service level events
|
|
--time|-t - show stats for a time interval; can be use separately ot together with -c, -p, or -j
|
|
--verbose|-v - show more details, when available
|
|
--silent|-s - show less details, more suitable for scripting
|
|
--help|-h - show this help message
|
|
--version|-V - show version"
|
|
|
|
version="JILO Jitsi Logs Observer command line client
|
|
jilo-cli_${VERSION}_${RELEASE_DATE}
|
|
version $VERSION
|
|
released on $RELEASE_DATE"
|
|
|
|
time_formats="Expected formats:
|
|
- exact times
|
|
YYYY-MM-DD, YYYY-MM, YYYY
|
|
- exact periods
|
|
YYYY-MM-DD:YYYY-MM-DD, YYYY-MM:YYYY-MM, YYYY:YYYY
|
|
- from begining to given time
|
|
:YYYY-MM-DD, :YYYY-MM, :YYYY
|
|
- from given time until end
|
|
YYYY-MM-DD:, YYYY-MM:, YYYY:"
|
|
|
|
|
|
###
|
|
|
|
# First we check for requirements
|
|
check_requirements() {
|
|
# required programs, anything non-bash - edit as needed
|
|
# deb packages - sqlite3, util-linux (column)
|
|
local required_programs=("sqlite3" "column")
|
|
local requirements_missing=''
|
|
for program in "${required_programs[@]}"; do
|
|
if ! command -v "$program" &> /dev/null; then
|
|
requirements_missing+="$program, "
|
|
fi
|
|
done
|
|
if [[ "$requirements_missing" != '' ]]; then
|
|
requirements_missing=${requirements_missing::-2}
|
|
echo "Error: $requirements_missing - not found. Please install to proceed."
|
|
exit 1
|
|
fi
|
|
}
|
|
check_requirements
|
|
|
|
###
|
|
|
|
# DB functions for Sqlite3 and for MySQL/MariaDB
|
|
|
|
# execute a query and return the result
|
|
db_query() {
|
|
local query=$1
|
|
if [[ "$DB_TYPE" == "sqlite" ]]; then
|
|
sqlite3 "$DB" "$query"
|
|
elif [[ "$DB_TYPE" == "mysql" || "$DB_TYPE" == "mariadb" ]]; then
|
|
mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p "$MYSQL_PASS" -D "$MYSQL_DB" -se "$query"
|
|
else
|
|
echo "Error: unknown database type $DB_TYPE."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
### input parameters parsing
|
|
|
|
# time parameters
|
|
parse_time_range() {
|
|
local time_range="$1"
|
|
|
|
## exact times
|
|
# exact date given (YYYY-MM-DD)
|
|
if [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]; then
|
|
from_time="${BASH_REMATCH[0]}"
|
|
until_time="${BASH_REMATCH[0]}"
|
|
# exact month given (YYYY-MM)
|
|
elif [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2})$ ]]; then
|
|
from_time="${BASH_REMATCH[0]}-01"
|
|
until_time="${BASH_REMATCH[0]}-31"
|
|
# exact year given (YYYY)
|
|
elif [[ "$time_range" =~ ^([0-9]{4})$ ]]; then
|
|
from_time="${BASH_REMATCH[0]}-01-01"
|
|
until_time="${BASH_REMATCH[0]}-12-31"
|
|
|
|
## exact periods
|
|
# from date to date
|
|
elif [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2}):([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]; then
|
|
from_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}"
|
|
until_time="${BASH_REMATCH[4]}-${BASH_REMATCH[5]}-${BASH_REMATCH[6]}"
|
|
# from month to month
|
|
elif [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2}):([0-9]{4})-([0-9]{2})$ ]]; then
|
|
from_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-01"
|
|
until_time="${BASH_REMATCH[3]}-${BASH_REMATCH[4]}-31"
|
|
# from year to year
|
|
elif [[ "$time_range" =~ ^([0-9]{4}):([0-9]{4})$ ]]; then
|
|
from_time="${BASH_REMATCH[1]}-01-01"
|
|
until_time="${BASH_REMATCH[2]}-12-31"
|
|
|
|
## only end time given
|
|
# from begining until date (:YYYY-MM-DD)
|
|
elif [[ "$time_range" =~ ^:([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]; then
|
|
from_time="0000-01-01"
|
|
until_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}"
|
|
# from begining until month (:YYYY-MM)
|
|
elif [[ "$time_range" =~ ^:([0-9]{4})-([0-9]{2})$ ]]; then
|
|
from_time="0000-01-01"
|
|
until_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-31"
|
|
# from begining until year (:YYYY)
|
|
elif [[ "$time_range" =~ ^:([0-9]{4})$ ]]; then
|
|
from_time="0000-01-01"
|
|
until_time="${BASH_REMATCH[0]}-12-31"
|
|
|
|
## only start time given
|
|
# from date until end (YYYY-MM-DD:)
|
|
elif [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2}):$ ]]; then
|
|
from_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}"
|
|
until_time="9999-12-31"
|
|
# from month until end (YYYY-MM:)
|
|
elif [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2}):$ ]]; then
|
|
from_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-01"
|
|
until_time="9999-12-31"
|
|
# from year until end (YYYY:)
|
|
elif [[ "$time_range" =~ ^([0-9]{4}):$ ]]; then
|
|
from_time="${BASH_REMATCH[1]}-01-01"
|
|
until_time="9999-12-31"
|
|
|
|
else
|
|
echo -e "Invalid time range. $time_formats" >&2
|
|
exit 1
|
|
fi
|
|
|
|
time_range_specified=true
|
|
}
|
|
|
|
# we have two timestamps in format YYYY-MM-DD HH:MM:SS.sss
|
|
# calculate and return the durtion in format HH:MM:SS
|
|
calculate_duration() {
|
|
start=$(date -d "$1" +"%s")
|
|
end=$(date -d "$2" +"%s")
|
|
duration_seconds=$((end - start))
|
|
hours=$((duration_seconds / 3600))
|
|
duration_seconds_remain=$((duration_seconds % 3600))
|
|
minutes=$((duration_seconds_remain / 60))
|
|
seconds=$((duration_seconds_remain % 60))
|
|
|
|
# add leading zeroes
|
|
duration=$(printf "%02d:%02d:%02d" $hours $minutes $seconds)
|
|
}
|
|
|
|
|
|
### commandline options
|
|
|
|
conference_arg=""
|
|
conference_option=false
|
|
participant_arg=""
|
|
participant_option=false
|
|
component_arg=""
|
|
component_option=false
|
|
from_time="0000-00-00"
|
|
until_time="9999-12-31"
|
|
time_option=false
|
|
time_range_specified=false
|
|
|
|
# display help if no arguments
|
|
if [[ $# -eq 0 ]]; then
|
|
echo -e "$help"
|
|
exit 0
|
|
fi
|
|
|
|
# then check all the options
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-c | --conference )
|
|
conference_option=true
|
|
if [[ -n "$2" && "$2" != -* ]]; then
|
|
conference_arg="$2"
|
|
shift 2
|
|
else
|
|
shift
|
|
fi
|
|
;;
|
|
-p | --participant)
|
|
participant_option=true
|
|
if [[ -n "$2" && "$2" != -* ]]; then
|
|
participant_arg="$2"
|
|
shift 2
|
|
else
|
|
shift
|
|
fi
|
|
;;
|
|
-j | --jitsi-component)
|
|
component_option=true
|
|
if [[ -n "$2" && "$2" != -* ]]; then
|
|
component_arg="$2"
|
|
shift 2
|
|
else
|
|
shift
|
|
fi
|
|
;;
|
|
-t | --time)
|
|
time_option=true
|
|
if [[ -n "$2" && "$2" != -* ]]; then
|
|
parse_time_range "$2"
|
|
shift 2
|
|
else
|
|
echo "Option -t needs a time range argument. $time_formats" >&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
-v | --verbose)
|
|
verbose=true
|
|
shift
|
|
;;
|
|
-s | --silent)
|
|
silent=true
|
|
shift
|
|
;;
|
|
-h | --help)
|
|
echo -e "$help"
|
|
exit 0
|
|
;;
|
|
-V | --version)
|
|
echo -e "$version"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Invalid option: $1" >&2
|
|
echo -e "$help"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ "$conference_option" == true ]]; then
|
|
|
|
# the argument to "--conference" can be either ID or name
|
|
if [[ -n "$conference_arg" ]]; then
|
|
|
|
# check for conferences match within a time period (or all if not period given)
|
|
db_conferences_id=$(printf "$db_conference_by_id_template" "$conference_arg" "$from_time" "$until_time" "$conference_arg" "$from_time" "$until_time")
|
|
mapfile -t conferences_id < <(db_query "$db_conferences_id")
|
|
db_conferences_name=$(printf "$db_conference_by_name_template" "$conference_arg" "$from_time" "$until_time" "$conference_arg" "$from_time" "$until_time")
|
|
mapfile -t conferences_name < <(db_query "$db_conferences_name")
|
|
|
|
# we check if the argument to "--conference" is a conference ID
|
|
# conference ID is unique, so we show that conference
|
|
if [[ "${#conferences_id[@]}" -gt 0 ]]; then
|
|
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
header="\nConferences with ID matching \"$IMPORTANT_TEXT$conference_arg$NORMAL_TEXT\""
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
header+=" for the time period \"$from_time - $until_time\""
|
|
fi
|
|
header+="\n"
|
|
echo -e "$header"
|
|
output="time\tconference ID\tconference name\tconference host\tloglevel\tparticipant ID\tevent\tparameter\n"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${conferences_id[@]}"; do
|
|
IFS='|' read -r time conference_id conference_name conference_host loglevel event_type participant_id event_param <<< "$row"
|
|
output+="$time\t$IMPORTANT_TEXT$conference_id$NORMAL_TEXT\t$conference_name\t$conference_host\t$loglevel\t$participant_id\t$event_type\t$event_param\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
|
|
# then we check if the argument to "--conference" is a conference name
|
|
# if so, we show all matching conferences (conference names are not unique)
|
|
elif [[ "${#conferences_name[@]}" -gt 0 ]]; then
|
|
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
header="\nConferences with names matching \"$IMPORTANT_TEXT$conference_arg$NORMAL_TEXT\""
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
header+=" for the time period \"$from_time - $until_time\""
|
|
fi
|
|
header+="\n"
|
|
echo -e "$header"
|
|
output="time\tconf ID\tconf name\tconf host\tloglevel\tparticipant ID\tevent\tparameter\n"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${conferences_name[@]}"; do
|
|
IFS='|' read -r time conference_id conference_name conference_host loglevel event_type participant_id event_param <<< "$row"
|
|
output+="$time\t$conference_id\t$IMPORTANT_TEXT$conference_name$NORMAL_TEXT\t$conference_host\t$loglevel\t$participant_id\t$event_type\t$event_param\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
|
|
# nothing found for neither conference ID or name
|
|
else
|
|
if [[ "$silent" != true ]]; then
|
|
echo "No match found for \"$conference_arg\""
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
echo "and time period $from_time - $until_time"
|
|
fi
|
|
fi
|
|
fi
|
|
exit 0
|
|
else
|
|
# if no argument is given, we show all the conferences
|
|
db_conferences_all=$(printf "$db_conferences_all_formatted_template" "$from_time" "$until_time")
|
|
mapfile -t conference_array < <(db_query "$db_conferences_all")
|
|
|
|
# we only format the outrput if there are conferences to show
|
|
if [[ "${#conference_array[@]}" -gt 0 ]]; then
|
|
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
header="\nAll conferences"
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
header+=" for the time period \"$IMPORTANT_TEXT$from_time - $until_time$NORMAL_TEXT\""
|
|
fi
|
|
header+="\n"
|
|
echo -e "$header"
|
|
output="component\tduration\tconference ID\tconference name\tparticipants\tname count\tconference host\n"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${conference_array[@]}"; do
|
|
IFS='|' read -r jitsi_component end start conference_id conference_name participants name_count conference_host <<< "$row"
|
|
calculate_duration "$start" "$end"
|
|
output+="$jitsi_component\t$duration\t$conference_id\t$conference_name\t$participants\t$name_count\t$conference_host\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
else
|
|
if [[ "$silent" != true ]]; then
|
|
echo -n "No conferences found"
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
echo -n " for the time period \"$from_time - $until_time\""
|
|
fi
|
|
echo "."
|
|
fi
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
elif [[ "$participant_option" == true ]]; then
|
|
|
|
# the argument to "--participant" can be endpointID, conferenceID, conference name, startsID, IP address
|
|
# check for participants match within a time period (or all if period not given)
|
|
# we check for all ot them and show the matches
|
|
## FIXME - we don't catch the case with no results found at all, no message is displayed if no results ## FIXME
|
|
if [[ -n "$participant_arg" ]]; then
|
|
|
|
db_participants_endpoint=$(printf "$db_conference_by_participant_id_template" "$participant_arg" "$from_time" "$until_time" "$participant_arg" "$from_time" "$until_time")
|
|
mapfile -t participants_endpoint < <(db_query "$db_participants_endpoint")
|
|
|
|
db_participants_conference=$(printf "$db_participant_by_conference_id_template" "$participant_arg" "$from_time" "$until_time" "$participant_arg" "$from_time" "$until_time")
|
|
mapfile -t participants_conference < <(db_query "$db_participants_conference")
|
|
|
|
db_participants_conference_name=$(printf "$db_participant_by_conference_name_template" "$participant_arg" "$from_time" "$until_time" "$participant_arg" "$from_time" "$until_time")
|
|
mapfile -t participants_conference_name < <(db_query "$db_participants_conference_name")
|
|
|
|
db_participants_statsid=$(printf "$db_participant_by_stats_id_template" "$participant_arg" "$from_time" "$until_time" "$participant_arg" "$from_time" "$until_time")
|
|
mapfile -t participants_statsid < <(db_query "$db_participants_statsid")
|
|
|
|
db_participants_ip=$(printf "$db_participant_by_ip_template" "$participant_arg" "$from_time" "$until_time" "$participant_arg" "$from_time" "$until_time")
|
|
mapfile -t participants_ip < <(db_query "$db_participants_ip")
|
|
|
|
# match for participant endpoint_id
|
|
if [[ "${#participants_endpoint[@]}" -gt 0 ]]; then
|
|
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
header="\nParticipants with ID matching \"$IMPORTANT_TEXT$participant_arg$NORMAL_TEXT\""
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
header+=" for the time period \"$from_time - $until_time\""
|
|
fi
|
|
header+="\n"
|
|
echo -e "$header"
|
|
output="time\tconference ID\tconference name\tconference host\tloglevel\tparticipant ID\tevent\tparameter\n"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${participants_endpoint[@]}"; do
|
|
IFS='|' read -r time conference_id conference_name conference_host loglevel event_type participant_id event_param <<< "$row"
|
|
output+="$time\t$conference_id\t$conference_name\t$conference_host\t$loglevel\t$IMPORTANT_TEXT$participant_id$NORMAL_TEXT\t$event_type\t$event_param\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
fi
|
|
|
|
# match for conference_id the participant was in
|
|
if [[ "${#participants_conference[@]}" -gt 0 ]]; then
|
|
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
header="\nParticipants in conferences with ID matching \"$IMPORTANT_TEXT$participant_arg$NORMAL_TEXT\""
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
header+=" for the time period \"$from_time - $until_time\""
|
|
fi
|
|
header+="\n"
|
|
echo -e "$header"
|
|
output+="time\tconference ID\tconference name\tconference host\tloglevel\tparticipant ID\tevent\tparameter\n"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${participants_conference[@]}"; do
|
|
IFS='|' read -r time conference_id conference_name conference_host loglevel event_type participant_id event_param <<< "$row"
|
|
output+="$time\t$IMPORTANT_TEXT$conference_id$NORMAL_TEXT\t$conference_name\t$conference_host\t$loglevel\t$participant_id\t$event_type\t$event_param\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
fi
|
|
|
|
# match for conference_name the participant was in
|
|
if [[ "${#participants_conference_name[@]}" -gt 0 ]]; then
|
|
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
header="\nParticipants in conferences with name that include the string \"$IMPORTANT_TEXT$participant_arg$NORMAL_TEXT\""
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
header+=" for the time period \"$from_time - $until_time\""
|
|
fi
|
|
header+="\n"
|
|
echo -e "$header"
|
|
output+="time\tconference ID\tconference name\tconference host\tloglevel\tparticipant ID\tevent\tparameter\n"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${participants_conference_name[@]}"; do
|
|
IFS='|' read -r time conference_id conference_name conference_host loglevel event_type participant_id event_param <<< "$row"
|
|
output+="$time\t$conference_id\t$IMPORTANT_TEXT$conference_name$NORMAL_TEXT\t$conference_host\t$loglevel\t$participant_id\t$event_type\t$event_param\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
fi
|
|
|
|
# match for participant stats_id
|
|
if [[ "${#participants_statsid[@]}" -gt 0 ]]; then
|
|
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
header="\nParticipants with stats ID that include the string \"$IMPORTANT_TEXT$participant_arg$NORMAL_TEXT\""
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
header+=" for the time period \"$from_time - $until_time\""
|
|
fi
|
|
header+="\n"
|
|
echo -e "$header"
|
|
output+="time\tconference ID\tconference name\tconference host\tloglevel\tparticipant ID\tevent\tparameter\n"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${participants_statsid[@]}"; do
|
|
IFS='|' read -r time conference_id conference_name conference_host loglevel event_type participant_id event_param <<< "$row"
|
|
output+="$time\t$conference_id\t$conference_name\t$conference_host\t$loglevel\t$participant_id\t$event_type\t$IMPORTANT_TEXT$event_param$NORMAL_TEXT\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
fi
|
|
|
|
# match for participant IP
|
|
if [[ "${#participants_ip[@]}" -gt 0 ]]; then
|
|
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
header="\nParticipants with IP address matching \"$IMPORTANT_TEXT$participant_arg$NORMAL_TEXT\""
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
header+=" for the time period \"$from_time - $until_time\""
|
|
fi
|
|
header+="\n"
|
|
echo -e "$header"
|
|
output+="time\tconference ID\tconference name\tconference host\tloglevel\tparticipant ID\tevent\tparameter\n"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${participants_ip[@]}"; do
|
|
IFS='|' read -r time conference_id conference_name conference_host loglevel event_type participant_id event_param <<< "$row"
|
|
output+="$time\t$conference_id\t$conference_name\t$conference_host\t$loglevel\t$participant_id\t$event_type\t$IMPORTANT_TEXT$event_param$NORMAL_TEXT\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
fi
|
|
|
|
exit 0
|
|
else
|
|
|
|
# if no argument is given, we show all the participants
|
|
db_participants_all=$(printf "$db_participants_all_template" "$from_time" "$until_time")
|
|
mapfile -t participant_array < <(db_query "$db_participants_all")
|
|
|
|
# we only format the outrput if there are conferences to show
|
|
if [[ "${#participant_array[@]}" -gt 0 ]]; then
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
header="\nAll participants"
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
header+=" for the time period \"$IMPORTANT_TEXT$from_time - $until_time$NORMAL_TEXT\""
|
|
fi
|
|
header+="\n"
|
|
echo -e "$header"
|
|
output+="component\tparticipant ID\tconference ID\n"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${participant_array[@]}"; do
|
|
IFS='|' read -r jitsi_component endpoint_id conference_id <<< "$row"
|
|
output+="$jitsi_component\t$endpoint_id\t$conference_id\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
else
|
|
if [[ "$silent" != true ]]; then
|
|
echo -n "No participants found"
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
echo -n " for the time period \"$from_time - $until_time\""
|
|
fi
|
|
echo "."
|
|
fi
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
elif [[ "$component_option" == true ]]; then
|
|
|
|
# argument for "--jitsi-component | -j" can be "jvb", "jicofo"
|
|
if [[ -n "$component_arg" ]]; then
|
|
case "$component_arg" in
|
|
jvb)
|
|
jitsi_component="'JVB'"
|
|
;;
|
|
jicofo)
|
|
jitsi_component="'JICOFO'"
|
|
;;
|
|
*)
|
|
# we have a component events search, but an unknown component string
|
|
# exiting with error, it's not a recognized option argument
|
|
echo "Invalid option: $component_arg" >&2
|
|
echo -e "$help"
|
|
exit 1
|
|
;;
|
|
esac
|
|
header="\nJitsi components events for \"$IMPORTANT_TEXT$jitsi_component$NORMAL_TEXT\""
|
|
|
|
else
|
|
jitsi_component="jitsi_component"
|
|
header="\nJitsi components events for \"$IMPORTANT_TEXT all components$NORMAL_TEXT\""
|
|
fi
|
|
|
|
db_jitsi_components=$(printf "$db_jitsi_components_template" "$jitsi_component" "$from_time" "$until_time")
|
|
mapfile -t jitsi_components < <(db_query "$db_jitsi_components")
|
|
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
header+=" for the time period \"$from_time - $until_time\""
|
|
fi
|
|
header+="\n"
|
|
echo -e "$header"
|
|
output+="jitsi_component\tloglevel\ttime\tcomponent ID\tevent\tparameter\n"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${jitsi_components[@]}"; do
|
|
IFS='|' read -r jitsi_component loglevel time component_id event_type event_param <<< "$row"
|
|
output+="$jitsi_component\t$loglevel\t$time\t$component_id\t$event_type\t$event_param\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
|
|
elif [[ "$time_option" == true ]]; then
|
|
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
db_events_time=$(printf "$db_events_by_period_template" "$from_time" "$until_time" "$from_time" "$until_time")
|
|
mapfile -t events_array < <(db_query "$db_events_time")
|
|
|
|
if [[ "${#events_array[@]}" -gt 0 ]]; then
|
|
output=""
|
|
# prepare the header
|
|
if [[ "$silent" != true ]]; then
|
|
header="\nEvents in the period \"$IMPORTANT_TEXT$from_time - $until_time$NORMAL_TEXT\"\n"
|
|
output="time\tconference ID\tconference name\tconference host\tloglevel\tparticipant ID\tevent\tparameter\n"
|
|
echo -e "$header"
|
|
fi
|
|
# prepare the formatted rows
|
|
for row in "${events_array[@]}"; do
|
|
IFS='|' read -r time conference_id conference_name conference_host loglevel event_type participant_id event_param <<< "$row"
|
|
output+="$IMPORTANT_TEXT$time$NORMAL_TEXT\t$conference_id\t$conference_name\t$conference_host\t$loglevel\t$event_type\t$participant_id\t$event_param\n"
|
|
done
|
|
# output
|
|
echo -e "$output" | column -t -s $'\t'
|
|
else
|
|
if [[ "$silent" != true ]]; then
|
|
echo -n "No events found"
|
|
if [[ "$time_range_specified" == true ]]; then
|
|
echo -n " for the time period \"$from_time - $until_time\""
|
|
fi
|
|
echo "."
|
|
fi
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
fi
|