По вашему запросу ничего не найдено :(
Убедитесь, что запрос написан правильно, или посмотрите другие
наши статьи:
Процесс анализа программного кода должен быть максимально автоматизирован. Когда вы создаете запрос на включение изменений, как минимум, вам нужно запустить модульные тесты и статический анализ программного кода в функциональной ветке. Средства автоматизации могут многое рассказать о качестве кода: метрики, покрытие кода модульными тестами, обнаружение дублированных строк и т.д.
Однако есть как минимум 50 вещей, которые нельзя проверить автоматически. Они нуждаются во внимательном взгляде опытного проверяющего (это дает нам хоть какую-то надежду на то, что роботы не заменят разработчиков в ближайшем будущем).
Требования
Программный код реализует все функциональные требования, которые необходимы заказчику?
Программный код удовлетворяет всем нефункциональным требованиям, таким как производительность и безопасность? Если нефункциональные требования не были упомянуты заказчиком, то этот вопрос необходимо уточнить у проектировщика или у самого заказчика.
Условия сопровождения
Помещены ли все интерфейсы, классы и т.д. на соответствующий прикладной уровень в соответствии с архитектурой
Onion/Clean
?
Не изобретаете ли вы колесо, когда пишете программный код? Можно ли его заменить чем-то, что уже существует и что предоставляет какая-либо сторонняя библиотека?
Есть ли уже реализованная логика или какие-то ее фрагменты в кодовой базе?
Правильно ли была выбрана область жизненного цикла для интерфейса и реализации в контейнере внедрения зависимостей?
Являются ли реализованные функции детерминированными (то есть всегда ли они выдают один и тот же результат для одних и тех же входных данных)?
Все ли зависимости явно внедряются через конструктор типов?
Есть ли сильная связанность между классами, которая может затруднить повторное использование кода?
Используются ли
объекты-значения
вместо элементарных типов данных для того, чтобы избежать проблемы одержимости элементарными типами?
Соответствуют ли реализованные компоненты, такие как функции, классы, интерфейсы и модули,
принципу единственной обязанностей
?
Расширяются ли существующие функциональные возможности при помощи декораторов, технологий аспектно-ориентированного программирования (принципа открытия-закрытия) или они модифицируются на месте?
Правильно ли реализованы механизмы синхронизации потоков при доступе к объектам-одиночкам в веб-приложениях?
Используются ли по возможности
неизменяемые типы данных
вместо изменяемых для того, чтобы избежать побочных эффектов?
Добавлена ли функция ведения журнала с верными
уровнями ведения протокола
в основные места кода, которые требуют отслеживания?
Производительность
Правильно ли были выбраны
структуры данных
? Например, используется ли структура Hashtable вместо массива, когда нужно часто искать значения, для того, чтобы избежать линейного поиска?
Распараллелены ли длительные операции между всеми доступными ядрами для того, чтобы использовать ресурсы компьютера максимально эффективного?
Выполняет ли программный код большое количестве
операций по выделению памяти
для объектов в куче, оказывая тем самым дополнительную нагрузку на программу сборки мусора?
Кэшируются
ли данные, которые были считаны из базы данных, локально или в удаленном кэше?
Сколько раз текущий код обращается к базе данных? Возможно стоит получить все данные за одно или несколько обращений?
Выполняет ли код все обращения к базе данных, ввод-вывод и другие блокирующие вызовы асинхронно?
Использует ли код
пул потоков
по максимуму вместо того, чтобы создавать новые потоки?
Правильно ли выбран баланс между
нормализацией
и
денормализацией
при создании дополнительных таблиц базы данных?
Правильно ли добавляются или исправляются индексы, если запрос на включение изменений содержит новые SQL-запросы?
Возникает ли
проблема с N+1 запросами
при извлечении данных из базы данных при помощи фреймворка ORM?
Установлен ли правильный уровень изоляции транзакций в хранимых процедурах?
Возвращают ли SQL-запросы избыточные данные из базы данных, которые не требуются для кода приложения? Используется ли что-то вроде
SELECT *
или что-то подобное?
Модульное и интеграционное тестирование
Полностью ли модульные тесты покрывают дополнительную логику?
При появлении исправлений в логике, появляются ли изменения в соответствующем модульном тесте?
Всегда ли все реализованные модульные или другие виды тестов ведут себя детерминировано? Например, приостанавливают ли они выполнение потока на какой-то определенный период времени перед утверждением (что по своей сути является ошибочным шаблоном)?
Все ли модульные тесты реализованы в соответствии с принципами
F.I.R.S.T.
?
Есть ли какие-либо признаки проблем в модульном тестировании, такие как проблемы с
логикой проверки условий
,
рулеткой с утверждениями
,
дублированием утверждений
и другие?
Добавлен ли интеграционный тест, как минимум, для happy-path-сценария (сценария счастливого пути) реализованной функции?
Все ли зависимости тестируемого объекта имитируются для того, чтобы модульный тест случайно не превратился в интеграционный и не выполнился быстрее положенного?
Изолированы ли модульные и интеграционные тесты друг от друга?
Конечные точки API
Выбираются ли HTTP-команды, такие как
GET, POST, PUT, DELETE
и другие, в соответствии с действием их конечной точки?
Отвечает ли каждая конечная точка API за выполнение лишь одной бизнес-операции? Или все же нескольких?
Возвращает ли конечная точка API правильный код состояния? Например, не возвращает ли она код 401 вместо 500 при несанкционированном запросе?
Сжимаются ли объемные ответы перед их отправкой вызывающей стороне?
Защищены ли конечные точки API политиками аутентификации и авторизации?
Позволяет ли API, который возвращает большой список объектов, фильтровать его и разбивать на страницы?
Является ли конечная точка API GET идемпотентной?
Используются ли имена существительные вместо глаголов в именах конечных точек API?
Критические изменения
Имеются ли в конечной точке API такие критические изменения, как переименование API, удаление или переименование его параметров?
Имеются ли критические изменения в полезных данных сообщения (в случае, если используется брокер сообщений), например, удаление или переименование его свойств?
Повлияют ли такие изменения в схеме базы данных, как удаление столбцов или таблиц, на другие службы системы?
Системная среда
Насколько загружен ЦП и сколько оперативной памяти потребляет код при выполнении запроса на включение изменений? Будет ли в средах, в которых будет развернут код (среда тестирования, среда приёмочного пользовательского тестирования, производственная среда), достаточно мощный процессор и достаточный объем оперативной памяти для эффективного выполнения кода?
Будет ли реализованная логика, алгоритмы, структуры данных и т.д. работать достаточно быстро на большом наборе данных, который может быть в производственной среде?
Документация
Была ли изменена документация для того, чтобы отразить новые изменения программного кода (документация API, документация по структуре, проектная документация)?
Создается ли тикет
технических недоработок
, если запрос на внесение изменений содержит неэффективный или «грязный» код, который сейчас невозможно перестроить из-за недостаточного количества времени?
Заключение
Количество пунктов, на которых проверяющий должен заострить свое внимание, зависит от конкретного проекта и даже от конкретного запроса на внесение изменений. Ваш с коллегами мозговой штурм (если вы примите во внимание вышеприведенные пункты) может значительно снизить риск того, что вы забудете о чем-то важно при анализе программного кода.
YAML (YAML – Ain’t Markup Language, что можно перевести как "YAML – это не язык разметки"") считается языком сериализации по типу XML и JSON. Он представляет собой расширенную версию JSON, которая используется, в основном, для файлов конфигурации. Вы можете сохранить YAML-файл с расширением .yaml или .yml. Это удобочитаемый файловый формат, состоящий из пар «ключ-значение» и делающий акцент на отступы и отбивку строк. YAML активно используется в файлах конфигурации многих хорошо известных инструментов/технологий, по типу docker-compose, Kubernetes, Ansible и т.д.
Ниже приведено сравнение YAML с XML и JSON.
Теперь давайте обсудим синтаксис, типы данных и особенности YAML-файлов.
Пары «ключ-значение»
Пара «ключ-значение» – это базовая составляющая YAML. Каждый элемент в YAML-документе является членом как минимум одного словаря. Ключами чаще всего являются строки, а значением могут быть данные любого типа: число, логическое значение, строка, пустое значение, массив и объект.
name: John
age: 25
city: LA
Числа
Числа – это одни из скаляров, которые могут использоваться в качестве значения YAML-файлов. Числа бывают десятичными, с плавающей запятой, экспоненциальными, восьмеричными и шестнадцатеричными. Если добавлять их без одинарных или двойных кавычек, то они обрабатываются как строки.
decimal : 10
float : 2.5
exponential : 5.0e+12
infinity : .inf
octal : 0o12
hexadecimal : 0xF
Примечание: Будьте осторожны при представлении некоторых стандартных типов чисел (время, восьмеричные и шестнадцатеричные коды и т.д.). Они могут быть некорректно интерпретированы. Вот несколько примеров.
time : 6:00
hexval: 0x12
octval: 0o25
В этом примере время преобразуется в минуты, поэтому 6:00 интерпретируется как 360. 0x12 обрабатывается как шестнадцатеричный код, поэтому оно переводится в десятеричное значение 18, а 0o25 интерпретируется в десятеричное значение 21. Так что если вы не собираетесь использовать их в таком виде, то добавляйте эти значения в кавычках.
Примечание: Начиная со спецификации YAML 1.2, 0o представляет восьмеричные значения. В более ранних версиях для этих целей использовался 0.
Логические значения
Логические значения похожи на другие языки программирования/представления с двумя состояниями: true или false. Логическими значениями в YAML-файлах считаются не только стандартные true/false, но также yes/no и on/off (исключение: если они добавлены в кавычках).
Примечание: Следите за тем, как вы используете значения yes/no и on/off. Если добавлять их не в одинарных кавычках, то они будут интерпретироваться как логические значения true/false.
Комментарии
Вы можете комментировать содержимое YAML-файла с помощью символа #. Пример ниже:
# This a comment on the first.
# And this a commented second line.
Строки
В YAML-файле вы можете прописывать строки без кавычек. Либо добавлять их в одинарные или двойные кавычки. Можно даже пользоваться всеми тремя способами.
Если в строке содержатся специальные символы, которые нужно экранировать с помощью , то добавлять такую строку нужно в двойных кавычках. Пример:
signature: "John Williams
Sales Executive
XYZ Company LA."
Но при использовании любого из специальных символов ниже:
:, {, }, [, ], ,, &, *, #, ?, |, -, , =, !, %, @, `
не нужно ничего экранировать. Воспользуйтесь одинарными кавычками – с ними строка будет интерпретироваться как нужно.
Одиночная строка
Если вы хотите разбить одну строку на несколько строчек, но синтаксический анализатор должен будет интерпретировать их как одиночную строку, то сделайте следующее:
message: >
this is a normal string
which spans more than multiple lines
but needs to be treated
as a single line.
Начните код с символа > , а затем впишите содержимое строки в виде блока с отступами. В конце проанализированного содержимого добавляется
. Если вам не нужен символ новой строки, то воспользуйтесь символом >-.
Многострочное значение
При добавлении строки, которая разделяется на несколько строк и анализируется так же, как написана, воспользуйтесь схемой ниже.
message: |
this is a multi-line string
which spans across multiple lines
and needs to be treated
as a multi-line string.
| добавляет в конце проанализированного содержимого символ перехода на новую строку. Если вы не хотите видеть в конце проанализированного содержимого символ
, то лучше воспользуйтесь |-.
Нулевые значения
Вы можете представить нулевое значение с помощью ~ или null. Такие значения добавляются без кавычек.
foo: ~
bar: null
Массивы
В YAML значения можно представить в форме массивов/списков. Пример массива данных:
teams:
- name: Australia
rank: 3
- name: New Zealand
rank: 4
- name: England
rank: 1
- name: India
rank: 2
В примере выше представлен массив объектов с названием и рангом команды. Обязательно проверьте, что отбивка строк и отступы заданы единообразно. В противном случае, файл будет некорректным.
Каждый элемент массива обозначается через дефис -. Все элементы должны находиться на одном уровне с одинаковыми отступами.
Если вместо объектов в массиве используются примитивные элементы, то их можно представить следующим образом:
teams: [ Australia, New Zealand, England, India ]
Объекты
Объекты в YAML представляются так:
student:
name: John
age: 22
city: NY
college: NYU
gpa: 3.5
Все атрибуты внутри объекта должны находиться на одном уровне и с одинаковым отступом. Именно это условие указывает на принадлежность к одному объекту и гарантирует корректность YAML-документа.
Заключение
В данной статье вы познакомились с базовыми концепциями при работе с YAML-файлами. Разобравшись в них, вы поймете, как правильно прописывать файлы для своих собственных инструментов и технологий.
Channel event logging (события на канале) – система, созданная для детального логирования телефонных событий. Система CEL позволяет пошагово отслеживать сложные сценарии вызовов, последовательно записывая их в таблицу данных. Сегодня расскажем о типах событий CEL и о содержимом таблицы ‘cel’
?
Как и обычно, подключаемся к базе данных asteriskcdrdb:
[root@asterisk]# mysql // подключаемся к MySQL
mysql> use asteriskcdrdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
Смотрим содержимое таблица cel, видим поля и типы данных:
mysql> show columns from cel;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| eventtype | varchar(30) | NO | | NULL | |
| eventtime | datetime | NO | | NULL | |
| cid_name | varchar(80) | NO | | NULL | |
| cid_num | varchar(80) | NO | | NULL | |
| cid_ani | varchar(80) | NO | | NULL | |
| cid_rdnis | varchar(80) | NO | | NULL | |
| cid_dnid | varchar(80) | NO | | NULL | |
| exten | varchar(80) | NO | | NULL | |
| context | varchar(80) | NO | MUL | NULL | |
| channame | varchar(80) | NO | | NULL | |
| appname | varchar(80) | NO | | NULL | |
| appdata | varchar(80) | NO | | NULL | |
| amaflags | int(11) | NO | | NULL | |
| accountcode | varchar(20) | NO | | NULL | |
| uniqueid | varchar(32) | NO | MUL | NULL | |
| linkedid | varchar(32) | NO | MUL | NULL | |
| peer | varchar(80) | NO | | NULL | |
| userdeftype | varchar(255) | NO | | NULL | |
| extra | varchar(512) | NO | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
20 rows in set (0.00 sec)
К описанию таблицы CEL мы вернемся чуть позже, а сейчас давайте разберем возможные события в рамках системы Channel Event Logging :
Событие
Описание
CHAN_START
Канал связи был создан
CHAN_END
Канал связи был разорван
LINKEDID_END
Канал связи с указанным ID был разорван
ANSWER
На созданном канале связи ответили на звонок. При звонке в город, данное событие генерируется когда удаленный (вызываемый абонент) поднимет трубку
HANGUP
Была повешена трубка. Как правило, это событие сразу же сопровождается событием CHAN_END. Разница в том, что HANGUP происходит когда трубка положена, а CHAN_END, когда Asterisk освободил все ресурсы, занимаемые этим каналом
APP_START
Определенное приложение было запущено для этого канала. Например, это может быть Dial, Busy или Congestion
APP_END
Указанное приложение в событие APP_START завершило свое выполнение
PARK_START
Была произведена «Парковка» вызова. Функция парковки, представляет собой определенный номер, в который помещается вызов, работу с которым, могут продолжить другие сотрудники.
PARK_END
Вызов был снят с «Парковки»
BRIDGE_START
Между двумя каналами образовалось соединение (мост). Данное событие сопровождает такие приложения, как Dial() или Queue()
BRIDGE_END
Мост между каналами был разрушен
BRIDGE_UPDATE
В соединении между каналами произошло обновление. Это события появляется тогда, например, если изменится имя или прочая канальная информация
BLINDTRANSFER
Был выполнен «слепой» (без предварительной консультации) трансфер
ATTENDEDTRANSFER
На канале был выполнен трансфер с предварительной консультацией
USER_DEFINED
Кастомное событие, которое определяется в приложении CELGenUserEvent()
В таблице выше мы перечислили основные события в рамках системы CEL. Теперь перейдем к описанию таблицы ‘cel’ в рамках базы asteriskcdrdb:
Столбец
Пример значения
Описание
eventtype
CHAN_START
Имя произошедшего события (все события описаны в таблице выше)
eventtime
2016-04-01 14:53:54
Время, в которое произошло указанное выше событие
cidname
Oleg Ivanov
Имя, передаваемое в рамках CallerID (CID), закрепленное за данным каналом
cidnum
84991111111
Номер, передаваемый в рамках CallerID (CID), закрепленный за данным каналом в рамках соответствующего события
cidani
84991111111
Automatic Number Identification (ANI), или другими словами – автоматическое определение номера на данном канале в рамках соответствующего события
cidrdnis
84991111234
Номер перенаправления на данном канале в рамках соответствующего события
ciddnid
84993456458
Набранный номер на канале в рамках соответствующего события
exten
7057
Добавочный номер, который был набран, в рамках плана нумерации
context
Local
Контекст для добавочного номера, который был набран
channame
SIP/0007B3060EB4-00000010
Имя установленного канала
appname
Dial
Название приложения, которое было выполнено
appdata
SIP/0007B3060EB4
Параметры, которые были переданы в приложении согласно плана нумерации
amaflags
DOCUMENTATION
Метка Automatic Message Accounting (AMA) – автоматический учет стоимости вызова.
accountcode
6473
Идентификатор аккаунта. Данное значение пустое по умолчанию, и определяется параметрами конкретного пользователя.
uniqueid
6547653456.18332
Уникальный идентификатор для канала
userfield
Chto ugodno
Пользовательское поле
linkedid
6547653456.18332
Данный идентификатор, позволяет связать воедино звонок по частям. Например, если одна часть звонка была входящей из города, следом был трансфер, потом еще один – у все этих вызовов будет разный uniqueid, но одинаковый linkedid
peer
SIP/0007B306054F-00000020
Название канала, к которому, который соединен (bridge) с каналом с идентификатором channame
Теперь, давайте рассмотрим как выглядит запись в таблице ‘cel’. Для этого выполним нижеследующий запрос к базе данных asteriskcdrdb:
mysql> SELECT * FROM `cel` WHERE `uniqueid` = '1459503113.15';
+------+------------+---------------------+-------------+-------------+-------------+-----------+----------+-------------+------------------+--------------------------------------------+------------+----------------------------------------------------------------------------------+----------+-------------+---------------+---------------+------+-------------+----------------------------------------------------------------------------+
| id | eventtype | eventtime | cid_name | cid_num | cid_ani | cid_rdnis | cid_dnid | exten | context | channame | appname | appdata | amaflags | accountcode | uniqueid | linkedid | peer | userdeftype | extra |
+------+------------+---------------------+-------------+-------------+-------------+-----------+----------+-------------+------------------+--------------------------------------------+------------+----------------------------------------------------------------------------------+----------+-------------+---------------+---------------+------+-------------+----------------------------------------------------------------------------+
| 2339 | CHAN_START | 2016-04-01 12:31:53 | | | | | | 89641111111 | from-internal | Local/89641111111@from-internal-00000004;2 | | | 3 | | 1459503113.15 | 1459503090.11 | | | |
| 2346 | APP_START | 2016-04-01 12:31:53 | 79252222222 | 79252222222 | 79252222222 | | | recordcheck | sub-record-check | Local/89641111111@from-internal-00000004;2 | MixMonitor | 2016/04/01/out-89641111111-79252222222-20160401-123153-1459503113.15.wav,ai(LOCA | 3 | | 1459503113.15 | 1459503090.11 | | | |
| 2347 | APP_END | 2016-04-01 12:31:53 | 79252222222 | 79252222222 | 79252222222 | | | recordcheck | sub-record-check | Local/89641111111@from-internal-00000004;2 | MixMonitor | 2016/04/01/out-89641111111-79252222222-20160401-123153-1459503113.15.wav,ai(LOCA | 3 | | 1459503113.15 | 1459503090.11 | | | |
| 2364 | HANGUP | 2016-04-01 12:32:10 | | 79252222222 | 79252222222 | | | h | from-internal | Local/89641111111@from-internal-00000004;2 | | | 3 | | 1459503113.15 | 1459503090.11 | | | {"dialstatus":"CANCEL","hangupcause":16,"hangupsource":"dialplan/builtin"} |
| 2365 | CHAN_END | 2016-04-01 12:32:10 | | 79252222222 | 79252222222 | | | h | from-internal | Local/89641111111@from-internal-00000004;2 | | | 3 | | 1459503113.15 | 1459503090.11 | | | |
+------+------------+---------------------+-------------+-------------+-------------+-----------+----------+-------------+------------------+--------------------------------------------+------------+----------------------------------------------------------------------------------+----------+-------------+---------------+---------------+------+-------------+----------------------------------------------------------------------------+
5 rows in set (0.00 sec)
В указанном выше запросе мы извлекли все содержимое таблицы ‘cel’, где поле uniqueid = 1459503113.15. Полученные данные можно обрабатывать и использовать для глубокой аналитики