А твой Exchange в полном порядке? Как бесплатно мониторить здоровье сервера

в 16:14, , рубрики: exchange, Grafana, influxdb, monitoring, open source, Настройка Linux, почтовый сервер, системное администрирование

Всем привет. Меня зовут Игорь - я занимаюсь администрированием офисной инфраструктуры, руковожу отделом мониторинга и технической поддержки пользователей в компании NUT.Tech.

Уже более 10-ти лет я так или иначе сталкиваюсь с различными задачами, связанными с администрированием Microsoft Exchange Server. В основном – ничего сложного, обычные прикладные задачи вроде создания в системе новых почтовых ящиков и решения различных проблем с доставкой почтовых сообщений. Но так или иначе у меня накопилась некоторая экспертиза в этом вопросе.

Основная идея этой статьи – рассказать о решении, которое позволяет быстро и без затрат реализовать мониторинг Exchange сервера, используя популярные open source решения.

Знание этих несложных инструментов и умение применять их на практике позволят вам детализировать мониторинг Exchange практически до любого уровня, а также откроют возможности для осуществления мониторинга большого числа других сервисов и компонентов вашей инфраструктуры.

Microsoft Exchange можно условно назвать "коробочным решением" в том плане, что, несмотря на некоторую сложность в его внедрении (требуется инфраструктура ADDS, опыт работы с продуктами MS, покупка лицензий и.т.д.), после установки и настройки, он просто работает и ничего особенного с ним не происходит. Сообщения принимаются и отправляются, Outlook стабильно подключается к серверу, а веб-интерфейс OWA (Outlook Web Access) радует пользователей.

На мой субъективный взгляд такая вот "коробочная" особенность Exchange позволяет рядовому офисному администратору, который оказался ответственным за Exchange, особо не задумываться о том, а насколько же в действительности хорошо или плохо функционирует корпоративный почтовый сервер. Скорее всего такой админ не совершает проактивных действий по предотвращению возможных инцидентов с почтой, а о многих неполадках узнает от пользователей или, еще хуже, от своего руководства. Согласитесь, неприятно оказаться в ситуации, когда звонит начальник и сообщает, что он уже несколько часов назад отправил одно очень важное письмо, а партнеры его до сих пор не получили. И уже после проведения диагностики оказывается, что сервер перестал отправлять внешние сообщения, т.к. ваш IP адрес оказался в черном списке, при этом внутренняя почта продолжает работать и нет никаких признаков, что существует проблема.

Само собой, в крупных компаниях, где IT направление в целом находится на высоком уровне, скорее всего применяются коммерческие системы мониторинга, в которых есть готовые шаблоны по мониторингу Exchange и на которые можно полностью положиться, особо не вдаваясь в детали различных показателей работы сервиса и того, как они могут влиять на его состояние. С другой стороны, небольшие компании по примеру тех, в которых мне довелось работать, вряд ли готовы закладывать в свой бюджет расходы на энтерпрайз систему мониторинга. Администраторы в таких компаниях, как правило, загружены рутинной работой, и не горят желанием разбираться с метриками Exchange сервера, тем более что "Почту настраивал предыдущий админ, я тут работаю уже пару лет, и она еще ни разу не ломалась". Да, такой подход имеет место быть. И я не говорю, что он совсем неприменим. Даже наоборот, Exchange действительно довольно стабильная система и, на самом деле, можно несколько лет с ней ничего не делать, и она будет работать без каких-либо проблем.

Но статья же не об этом, правильно? Давайте перейдем ближе к делу.

Однажды, будучи таким вот офисным админом, я задумался о том, что, в действительности, я не располагаю какой-либо оперативной информацией о состоянии сервиса. Я имею в виду, что у меня под рукой совсем нет никаких показателей, на которые я бы мог посмотреть и понять работает ли почта. Да, конечно, я в любой момент могу зайти на сервер по RDP или подключиться удаленно через консоль или PowerShell, зайти на нем в пару мест и понять, что с сервером ничего плохого не происходит - почта приходит и уходит, клиенты подключаются, все хорошо. Но для совершения этих действий мне бы пришлось отвлечься от других задач, ненадолго, но выпасть из рабочего процесса, да и зачем мне лазить на сервер, когда ничего не случилось, и я уверен, что он в полном порядке.

Спустя некоторое время, разрешив свой внутренний конфликт и немного поразмыслив, я решил, что для дальнейшего душевного спокойствия мне хотелось бы иметь дашборд (сводную информацию) с какими-то основными метриками, которые бы помещались на одном экране и на которые я мог бы периодически поглядывать и визуально оценивать текущее здоровье сервиса.

Так как до этого момента мне не приходилось иметь дело с системами мониторинга, я не особо понимал, как можно осуществить задуманное и с чего вообще начать. Немного пообщавшись со своими более опытными коллегами в НАТ.Тех и изучив доступную в интернете информацию, я довольно быстро нашел несколько популярных open source продуктов, которые в дальнейшем и помогли мне реализовать задачу мониторинга MS Exchange Server.

Для всех этих продуктов в интернете существует большое количество документации, всевозможных мануалов и инструкций, так что для тех, кто уже знаком с ними я ничего нового не расскажу, но постараюсь рассказать про некоторые интересные моменты, с которыми я столкнулся в процессе настройки. Также, я надеюсь, что эта статья будет полезна тем, кто, как и я, никогда на разворачивал системы мониторинга для Exchange.

Итак, примерно разобравшись с тем, как должна выглядеть архитектура моего сервиса, я пришел к следующей схеме по её реализации.

А твой Exchange в полном порядке? Как бесплатно мониторить здоровье сервера - 1
  1. Telegraf. Агент для сбора и передачи метрик с сервера Exchange. https://www.influxdata.com/time-series-platform/telegraf/

  2. InfluxDB. База данных для хранения данных в виде временных рядов. (Time series database) https://www.influxdata.com/

  3. Grafana. Веб-платформа для аналитики и интерактивной визуализации данных из различных источников. https://grafana.com/

Для простоты, все компоненты, кроме агента Telegraf, я установлю на одной виртуальной машине с OS CentOS 7. Агент необходимо установить на сервер Exchange.

Начнем с установки базы данных InfluxDB.

На странице https://portal.influxdata.com/downloads/ выберите из списка вашу OS и воспользуйтесь автоматически сгенерированной командой для загрузки и установки пакета.

В моем случае для загрузки пакета я использовал утилиту CURL, так как wget по умолчанию не установлен в CentOS 7.

curl -O https://dl.influxdata.com/influxdb/releases/influxdb2-2.0.7.x86_64.rpm

yum localinstall influxdb2-2.0.7.x86_64.rpm

Запустим службу InfluxDB и добавим её в автозапуск

systemctl start influxdb

systemctl enable influxdb

В рамках тестовой среды отключим firewall. Если планируете вводить сервис в эксплуатацию, не отключайте firewall, а произведите его настройку.

systemctl stop firewalld

Для проверки доступности сервиса со стороны Exchange можно выполнить следующую команду в PowerShell.

curl -Uri IP_адрес_сервера_INFLUXDB:8086/ping -UseBasicParsing

Должно произойти соединение с сервером, и команда вернет ответ

StatusCode: 204

Сервис доступен.

Важный момент - в конце 2020 года вышла новая версия influxdb версии 2.0. В этой версии очень сильно изменилась идеология продукта. Приведенные ниже примеры подойдут только для influxdb версии 2.x. В версии 1.x алгоритм настройки будет сильно отличаться.

Для дальнейшей настройки воспользуемся веб-интерфейсом, который предоставляет платформа InfluxDB.

Веб-интерфейс доступен по адресу http://IP_адрес_сервера_INFLUXDB:8086/

Придумываем имя пользователя, пароль, название организации и название корзины (условной базы данных, в которую будут записываться наши метрики).

На следующем шаге выбираем вариант настройки "Advanced" - это позволит нам сразу настроить подключение для будущего агента Telegraf.

Для осуществления операций по чтению и записи данных в корзину нам потребуется токен нашей учетной записи.

В веб интерфейсе в левом меню идем в раздел DATA-Tokens, щелкаем по имени вашего пользователя. Откроется окошко с параметрами токена, скопируйте его в блокнот - он нам понадобится на следующем этапе.

Для того, чтобы можно было использовать InfluxQL, более простой язык запросов к базе данных, вместо более сложного FLUX, который появился в версии 2, потребуется сделать дополнительные настройки.

Вот здесь есть более подробное описание, как это делается.

Сначала необходимо получить ID корзины, для которой мы настраиваем доступ по логину и паролю. В веб интерфейсе в левом меню идем в раздел DATA-Buckets. В списке найдите корзину, которую вы создали и скопируйте её ID, который отображается рядом с именем.

Следующие команды выполняем в консоли вашего сервера.

Создаем пользователя, чтобы была возможность подключиться к InfluxDB, используя логин и пароль, вместо токена

influx v1 auth create 
 --username grafanauser 
 --password grafanauser 
 --org НАЗВАНИЕ_ОРГАНИЗАЦИИ_В_INFLUXDB 
 --read-bucket ID_ВАШЕЙ_КОРЗИНЫ 
 -t ТОКЕН_ВАШЕГО_ПОЛЬЗОВАТЕЛЯ

Создаем привязку корзины к базе данных

influx v1 dbrp create 
   --db test 
   --rp test-rp 
   --bucket-id ID_ВАШЕЙ_КОРЗИНЫ 
   --default 
   --org НАЗВАНИЕ_ОРГАНИЗАЦИИ_В_INFLUXDB 
   -t ТОКЕН_ВАШЕГО_ПОЛЬЗОВАТЕЛЯ

Ну вот и все, теперь у нас есть первый компонент нашего сервиса мониторинга.

Переходим к установке агента Telegraf

Дальнейшие действия необходимо производить на сервере Exchange.

Скачиваем дистрибутив для Windows тут.

На сайте выберете платформу Windows и увидите сгенерированные команды для загрузки и установки файлов.

Этими командами можно воспользоваться в PowerShell.

wget https://dl.influxdata.com/telegraf/releases/telegraf-1.19.1_windows_amd64.zip -UseBasicParsing -OutFile telegraf-1.19.1_windows_amd64.zip

Файл загрузится не в ту директорию, где выполняется команда, а в вашу домашнюю директорию. Распаковать скаченный архив можно тут же при помощи команды.

Expand-Archive ~telegraf-1.19.1_windows_amd64.zip -DestinationPath 'C:ProgramFilesInfluxDatatelegraf'

В директории окажется два файла:

telgraf.exe - собственно сам исполняемый файл;

telegraf.conf - конфигурационный файл с настройками подключения к хранилищу данных и описанием метрик, которые будет собирать наш агент.

В этом файле практически все строки закомментированы и содержат описания возможных параметров конфигурации.  Они приведены для примера настройки различных сценариев использования агента Telegraf. Чтобы не запутаться в конфигурации, давайте самостоятельно создадим этот файл с чистого листа и добавим только те параметры, которые нам будут нужны.

Для начала сделайте копию исходного файла и переименуйте его в telegraf.bak

Откройте оригинальный файл, выделите в нем весь текст и удалите его, чтобы он остался совершенно пустым.

Отлично.

Первым делом нам нужно создать секцию [agent]. В этой секции задаются глобальные параметры работы агента. Скопируйте основные параметры.

Для нас пока важен только параметр interval, который задает интервал (частоту) сбора метрик. Установите его в 5 секунд, чтобы в процессе настройки мы могли быстрее видеть новые значения метрик. В дальнейшем вы можете подобрать эти параметры под ваши требования.

[[agent]]
  interval = "5s"
  round_interval = true
  metric_batch_size = 1000
  metric_buffer_limit = 10000
  collection_jitter = "0s"
  flush_jitter = "0s"
  precision = ""

Далее нам нужно создать секцию [Output], которая описывает параметры для отправки полученных агентом метрик в базу данных.

В нашем случае секция будет называться [[outputs.influxdb_v2]]

Конфигурирование этой секции очень простое, а, если быть точным, все параметры автоматически генерируются на стороне InfluxDB в соответствии с настройками вашей инсталляции и нам остается только скопировать эти готовые параметры.

Для этого открываем веб интерфейс InfluxDB, идем в раздел Data -> Telegraf и нажимаем на кнопку "InfluxDB output plugin"

Откроется окошко с нужными нам параметрами, далее скопируем эту секцию в наш конфигурационный файл.

Проверьте все параметры и убедитесь, что они соответствуют настройкам вашей инсталляции.

Также в параметр Token скопируйте ранее сохраненный токен пользователя, созданный в InfluxDB, заполните поля «organization» и «bucket» в соответствии с вашими параметрами.

[[outputs.influxdb_v2]]
  ## The URLs of the InfluxDB cluster nodes.
  ##
  ## Multiple URLs can be specified for a single cluster, only ONE of the
  ## urls will be written to each interval.
  ## urls exp: http://127.0.0.1:9999

  urls = ["http://IP_адрес_сервера_INFLUXDB:8086"]

  ## Token for authentication.
  token = "$INFLUX_TOKEN"

  ## Organization is the name of the organization you wish to write to; must exist.
  organization = "test"

  ## Destination bucket to write into.
  bucket = "test"
  timeout = "5s"

И последняя секция, которая нам понадобится на данном этапе, это секция Inputs, в которой перечисляются метрики, значения которых будут отправляться в базу данных.

Для примера давайте сконфигурируем метрику загрузки процессора.

Метрики, относящиеся к Exchange, добавим позже, когда все компоненты сервиса будут установлены.

[[inputs.win_perf_counters]]
  [[inputs.win_perf_counters.object]]

    # Processor usage, alternative to native, reports on a per core.
    ObjectName = "Processor"

    Instances = ["*"]
    Counters = ["% Idle Time", "% Interrupt Time", "% Privileged Time", "% User Time", "% Processor Time"]
    Measurement = "win_cpu"

Давайте запустим Telegraf в тестовом режиме и проверим, что в нашем конфиге нет никаких ошибок. В таком режиме Telegraf не отправляет метрики в базу данных, а выводит их в консоль.

В командной строке перейдите в директорию, в которую вы распаковали файлы Telegraf.

cd "C:Program FilesInfluxDatatelegraftelegraf-1.19.1"

и выполните команду:

.telegraf.exe -config telegraf.conf -test

Команда запустит Telegraf с нашим конфигом и выведет несколько значений по текущей загрузке каждого ядра процессора.

Для моего 4-х ядерного процессора я получил 8 строчек со значениями для каждого логического ядра.

Если на вашей системе вы получаете метрики загрузки процессора и при запуске нет никаких ошибок, то можете запустит Telegraf уже в полноценном режиме, чтобы он отправлял метрики в наше хранилище данных с помощью команды.

telegraf -config telegraf.conf

Для дальнейшей полноценной эксплуатации вы можете установить Telegraf в качестве службы.

telegraf.exe --service install

Установка последнего и самого интересного компонента - Grafana

Идем на страничку https://grafana.com/grafana/download

Находим нужные команды для нашей ОС. В моем случае для CentOS для загрузки и установки пакета я использую команды:

curl -O https://dl.grafana.com/oss/release/grafana-8.0.5-1.x86_64.rpm

yum install grafana-8.0.5-1.x86_64.rpm

Как обычно добавим сервис в автозапуск и запустим

systemctl start grafana-server

systemctl enable grafana-server

Веб-интерфейс доступен по адресу http://IP_адрес_сервера_INFLUXDB:3000/

Пароль по умолчанию admin:admin

Первое, что необходимо сделать, это подключить нашу базу данных в качестве источника данных.

В левом меню идем в раздел Configuration (шестеренка) -> Data Sources, нажимаем кнопку «Add Data source».

В списке находим и выбираем InfluxDB, откроется окно с настройками подключения.

Проверяем, что в поле «Query Language» установлен InfluxQL. Это позволит нам использовать визуальный конструктор запросов к хранилищу данных.

Заполняем следующие поля:

Раздел HTTP

URL: http://IP_адрес_сервера_INFLUXDB:8086

Раздел InfluxDB Details

Database: test (название нашей корзины в InfluxDB)

User: grafanauser

Password: grafanauser

HTTP Method: GET

Все. Нажимаем кнопку «Save and test».

Должно произойти тестовое подключение к хранилищу данных и отобразится зеленая галочка с надписью "Data source is working"

А твой Exchange в полном порядке? Как бесплатно мониторить здоровье сервера - 2

Теперь создадим новый дашборд и выведем на него наши тестовые метрики по загрузке процессора.

Слева в меню идем в раздел "Create" иконка +, выбираем Dashboard, на дашборде в новой панели выбираем "Add an empty panel".

Откроются настройки новой панели. Проверьте, что в качестве источника данных у вас установлен InfluxDB (так как он пока единственный источник).

Далее в визуальном конструкторе запроса выбираем параметры как на скриншоте:

А твой Exchange в полном порядке? Как бесплатно мониторить здоровье сервера - 3

Если все настройки выполнены верно, вы увидите график загрузки процессора.

В правой части есть различные параметры отрисовки данных на графике, можете их настроить по своему вкусу.

Когда завершите все настройки, сверху нажмите кнопку Save, чтобы сохранить ваш дашборд, на котором располагается пока что только одна панель с метриками.

Все компоненты сервиса установлены и настроены. Последнее, что остается сделать, это добавить в конфигурацию агента Telegraf описание интересующих нас метрик Exchange и вывести их в отдельные графики на нашем дашборде в Grafana.

Расскажу, как это сделать.

Добавляем метрики Exchange в конфигурацию Telegraf.

Наверное, все знают, что в Windows есть оснастка Performance Monitor. Если кто-то из вас ни разу не пользовался этой штукой, в интернете полно информации.

Так вот, при установке Exchange Server в систему автоматически добавляется большое количество разнообразных метрик, которые как раз можно просматривать в Performance Monitor.

А в нашем агенте Telegraf очень удачно есть специальный модуль [[inputs.win_perf_counters]] , который позволяет читать любые метрики из Performance Monitor и отправлять в нашу базу данных ровно точно также как и ранее настроенные показатели загрузки процессора.

Давайте добавим в конфигурацию дополнительные секции для сбора интересующих нас метрик.

Я расскажу из чего состоит конфигурация на примере одной метрики. Все остальные метрики вы сможете добавить сами по этому шаблону.

Также в конце я приложу файл конфигурации со всеми метриками, которые я использовал в своей работе.

Вот так выглядит конфигурация секции [[inputs.win_perf_counters]]

[[inputs.win_perf_counters]]
  [[inputs.win_perf_counters.object]]

    ObjectName = "MSExchangeImap4"
    
    Counters = [
      "Current Connections",
      "Request rate",
    ]

    Measurement = "ex01__MSExchangeImap4"

    Instances = ["*"]

    IncludeTotal=true

Для нас тут важно поле ObjectName. Оно задает имя интересующего нас объекта для получения метрик. Каждый такой объект содержит свой набор различных метрик.

В поле counters перечислены метрики, которые существуют в данном объекте и значения которых мы будем отправлять в базу данных.

Поле Measurement определяет название таблицы, в которую на стороне базы данных записываются значения метрик, перечисленных в поле counters. Тут мы можем придумать своё название, чтобы нам легче было ориентироваться при добавлении метрик на наш дашборд.

Некоторые из счетчиков подразделяются на экземпляры (Instances), например, в счетчике загрузки процессора будет 8 экземпляров.

Если нам не нужен какой-то конкретный экземпляр счетчика, и мы хотим получить значения всех существующих экземпляров, то в поле Instances указывается *.

Для некоторых счетчиков экземпляры не предусмотрены (например, для оперативной памяти), в этом случае обязательно указывать "Instances = ["------"]", иначе Telegraf сообщит об ошибке в конфигурации и не будет работать.

Также можно указать параметр IncludeTotal=true, который позволяет получить отдельной метрикой общее значение для всех экземпляров счетчика, чтобы не считать их "вручную".

Список всех доступных объектов можно посмотреть в оснастке Performance Monitor.

А твой Exchange в полном порядке? Как бесплатно мониторить здоровье сервера - 4

Также их можно вывести с помощью команды Powershell.

Get-Counter -List * | ft CounterSetName

Отфильтровать вывод можно так:

Get-Counter -List * | Where {$_.countersetname -like "*processor*"} | ft CounterSetName

Список доступных счетчиков в объекте можно вывести командой:

(Get-Counter -ListSet MSExchangeImap4).Paths

К сожалению, вывод команды будет зависеть от языка системы, так в русском интерфейсе эти команды будут выводить название счетчиков на русском языке.

И ожидаемо - русские названия объектов не поддерживаются в конфигурации Telegraf.

Самое простое решение - это отобразить все необходимые счетчики в Performance Monitor, затем нажать кнопку "копировать свойства" в буфер обмена, открыть чистый блокнот и вставить туда содержимое буфера обмена.

А твой Exchange в полном порядке? Как бесплатно мониторить здоровье сервера - 5

Это текстовое описание текущего отображения счетчиков, в котором среди кучи параметров будет параметр PATH, значение VALUE которого содержит название объекта и счетчика на английском языке, который как раз подойдет для использования в конфигурации Telegraf.

<PARAM NAME="Counter00001.Path" VALUE="Memory% Committed Bytes In Use"/>

Ну вот и все, теперь вы сами сможете добавлять интересующие вас метрики Exchange, и не только его, на дашборд системы мониторинга.

Ну а мне остается только перечислить те метрики, которые я использовал в своей работе.

Общие параметры производительности сервера. Наиболее показательные

Processor% Processor Time
LogicalDisk(D:)% Disk Time

Подключение клиентов Outlook. Очень полезная метрика. Наглядно отображает, сколько сейчас подключено клиентов. На дашборде можно сразу заметить аномалии, если происходит массовое отключение клиентов от сервера.

MSExchange RpcClientAccessUser Count
MSExchange RpcClientAccessConnection Count

# Подключение клиентов по протоколу IMAP.

MSExchangeImap4Current Connections
MSExchangeImap4Request rate

# Подключение клиентов по протоколу Activeync

MSExchange ActiveSyncRequests/sec
MSExchange ActiveSyncCurrent Requests
MSExchange ActiveSyncSync Commands/sec

# Подключение клиентов через службу Outlook Anywhere, а также через веб-интерфейс 

W3SVC_W3WPRequests / Sec

Состояние репликации базы данных почтовых ящиков. Актуально для инсталляций, которые используют DAG (database availability group).

MSExchange Replication(_total)/CopyQueueLength
MSExchange Replication(_total)/ReplayQueueLength

Ну и как обещал, прикладываю свою конфигурацию секции Inputs, содержащую все вышеперечисленные метрики.

Конфигурация секции Inputs
[[inputs.win_perf_counters]]
  [[inputs.win_perf_counters.object]]
    ObjectName = "Processor"
    Instances = ["*"]
    Counters = [
      "% Processor Time",
    ]
    Measurement = "ex_win_cpu"
    IncludeTotal=true

[[inputs.win_perf_counters]]
  [[inputs.win_perf_counters.object]]
    ObjectName = "MSExchange RpcClientAccess"
    Counters = [
      "User Count",
      "Connection Count",
    ]
    Measurement = "ex__RpcClientAccess"
    Instances = ["------"]

[[inputs.win_perf_counters]]
  [[inputs.win_perf_counters.object]]
    ObjectName = "MSExchangeImap4"
    Counters = [
      "Current Connections",
      "Request rate",
    ]
    Measurement = "ex__MSExchangeImap4"
    Instances = ["*"]
    IncludeTotal=true
	
[[inputs.win_perf_counters]]
  [[inputs.win_perf_counters.object]]
    ObjectName = "MSExchange ActiveSync"
    Counters = [
      "Requests/sec",
      "Current Requests",
    ]
    Measurement = "ex__MSExchangeActiveSync"
    Instances = ["*"]
    IncludeTotal=true
	
[[inputs.win_perf_counters]]
  [[inputs.win_perf_counters.object]]
    ObjectName = "W3SVC_W3WP"
    Counters = [
      "Requests / Sec",
    ]
    Measurement = "ex__W3SVC_W3WP"
    Instances = ["*"]
    IncludeTotal=true

[[inputs.win_perf_counters]]
  [[inputs.win_perf_counters.object]]
    ObjectName = "MSExchange Replication(_total)"
    Counters = [
      "CopyQueueLength",
      "ReplayQueueLength",
    ]
    Measurement = "ex_DB_Replication"
    Instances = ["------"]

[[inputs.win_perf_counters]]
  [[inputs.win_perf_counters.object]]
    ObjectName = "LogicalDisk(D:)"
    Counters = [
      "% Disk Time",
    ]
    Measurement = "ex__LogicalDisk(D:)"
    Instances = ["------"]

А вот пример того, как может выглядеть дашборд, когда вы добавите на него интересующие вас метрики сервера Exchange.

А твой Exchange в полном порядке? Как бесплатно мониторить здоровье сервера - 6

Спасибо всем, кто дочитал статью до конца.

Автор: Игорь

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js