Afilters: Difference between revisions

From Svacer Wiki
(Описание advanced filters)
 
Line 113: Line 113:


= Описание языка предикатов =
= Описание языка предикатов =
Для написания предикатов используется язык  '''Expr'''. Детальное описание всех возможностей можно найти здесь: <nowiki>https://github.com/expr-lang/expr</nowiki>.
Для написания предикатов используется язык  '''Expr'''. Детальное описание всех возможностей можно найти здесь: https://github.com/expr-lang/expr  


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

Revision as of 12:36, 27 November 2025

Advanced filters

Поле "Расширенный фильтр" в пользовательских фильтрах предназначено для фильтрации маркеров (предупреждений) по сложным предикатам.

Предикат может использовать:

  • поля маркера, его трассы, разметки и комментариев
  • информацию из контекста (имя проекта, ветки, снимка и т.п.)
  • атрибуты снимка (включая пользовательские атрибуты, заданные при импорте)
  • статусы разметки
  • текст и атрибуты комментариев

Формат фильтра определяется следующим шаблоном:

filter(markers, <predicate expr> )

Выражение <predicate expr> определяет предикат. Объект markers содержит массив маркеров из контекста, функция filter фильтрует данный список по предикату. Таким образом, применение фильтра заключается в фильтрации списка маркеров по указанному предикату.

Список доступных полей

Поля маркера (предупреждения)

  • Comments - список комментариев маркера. Объект типа Comment (смотреть ниже)
  • Details - информация, специфичная для анализатора. Ближайший аналог - fingerprint в SARIF
  • File - имя файла
  • Function - имя функции, может быть managled для С++
  • ID - UUID маркера
  • Invariant - инвариант маркера. Используется для авто-переноса разметки между снимками
  • Lang - язык детектора
  • Line - номер строки в файле
  • LocID - порядковый номер маркера относительно изначального отчета анализатора
  • MTid - шаблон сообщения
  • Msg - текст сообщения
  • OrigFunc - 'человекочитаемое' имя функции. Может быть недоступно
  • Tags - список тэгов(меток) маркера
  • Tool - модуль анализатора, ответственного за данный детектор
  • Traces - список трасс маркера. Объект типа Trace (смотреть ниже)
  • WarnClass - название детектора/класса детекторов

Имена полей могут так же использоваться в формате, где первая буква в lower-case.

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

severity(item) string - серьезность детектора (чекера). 
Пример: filter(markers, severity(#) == "Critical")

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

Данные о разметке

Поддерживаются следующие функции для получения информации о разметки:

  • status(item) string - статус разметки текущего маркера. Пример: filter(markers, status(#) == "Confirmed")
  • action(item) string - статус поля action текущего маркера. Пример: filter(markers, action(#) == "Ignore")
  • mseverity(item) string - статус поля severity текущего маркера (не путать с severity детектора). Пример: filter(markers, mseverity(#) == "Critical")
  • triaged(item) bool - возвращает true, если маркер имеет не дефолтную разметку. Пример: filter(markers, triaged(#))
  • get_triaged_by(item) UserInfo - возвращает структуру, с информацией о пользователе, кто произвел разметку

Поля структуры UserInfo:

  • login: string - логин юзера
  • create_ts: Time (UTC) - время разметки в UTC формате (RFC3339)

Комментарии

Объекты типа Comment содержатся в поле Comments маркера. Объект имеет следующие поля:

  • ID - UUID комментария
  • Text - текст комментария
  • CreatedBy - имя пользователя, кто создал комментарий
  • CreateTs - время создания комментария (объект типа time.Time)
  • UpdateTs - время обновления комментария (объект типа time.Time), может быть пустым
  • UpdatedBy - имя пользователя, кто обновил комментарий

Трассы

Маркер может содержать трассу маркера в поле Traces. Трасса описывается следующими структурами:

type Trace struct {
	Role      string
	Locations []TraceEntry
}
type TraceEntry struct {
	File     string	
	Line     uint32
	Col  	 uint32	
	Info 	 string
}

Доступ к полям объекта Trace может выполняться используя правила языка go-expr, описанные ниже.

Имена полей могут использоваться в виде как описано выше, либо в формате lower-case: role, locations, file, line, col, info

Пример:

filter(markers, any(.Comments, .Text == "Test")  &&
		any(.Traces, any(.Locations, .Info == "Boolean expression has constant value"))
)

Поля снимка

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

struct {
	ID               string                
	Name             string                
	SerialID         uint32                
	BuildObject      string                
	ResultsObject    string                
	ImportTime       time.Time             
	CreatedBy        string                
	CreatedByID      string                
	Details          map[string]any
	CreateTime       time.Time             
	SourcesAvailable bool                  
}

Имена полей могут использоваться в виде, где первая буква в lower case.

Объекты в поле Details можно просмотреть нажав на View JSON кнопку в WebUI в поле Snapshot Information.

Пример:

filter(markers, 
   snapshot.buildObject == "5b634b75422bd554a8569cc10bfadc3aea77b73e" &&
   .warnClass matches "DEREF"
)

Описание языка предикатов

Для написания предикатов используется язык Expr. Детальное описание всех возможностей можно найти здесь: https://github.com/expr-lang/expr

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

Литералы

Comment /* */ or //
Boolean true, false
Integer 42, 0x2A, 0o52, 0b101010
Float 0.5, .5
String "foo", 'bar'
Array [1, 2, 3]
Map {a: 1, b: 2, c: 3}
Nil nil

Строки

Строки могут быть в одинарных и двойных кавычках. Для эскейпа использовать обратный слэш.

Пример однострочного текста:

    "Hello\nWorld"

Пример многострочного текста:

    `Hello
    World`

В многострочном тексте escape-последовательности не поддерживаются.

Операторы

Arithmetic: +, -, *, /, % (modulus), ^ or ** (exponent)
Comparison: ==, !=, <, >, <=, >=
Logical: not or !, and or &&, or or ||
Conditional: ?: (ternary), ?? (nil coalescing), if {} else {} (multiline)
Membership:  [], ., ?., in
String:  + (concatenation), contains, startsWith, endsWith
Regex:  matches
Range ..
Slice [:]
Pipe |

Операторы доступа к полю объекта

Пользователь может использовать оператор точка . и оператор []:

    user.Name
    user["Name"]

Оператор in

Оператор in для проверки наличия объекта в массиве или мэпе:

    "John" in ["John", "Jane"]
    "name" in {"name": "John", "age": 30}

Optional chaining

Оператор ?. может использоваться для доступа к полю структуры или элементу отображения (map) без необходимости проверки, является ли структура или отображение равными nil. Если структура или отображение имеют значение nil, результатом выражения будет nil.

Пример вида:

    author.User?.Name

значит тоже самое, что:

    author.User != nil ? author.User.Name : nil

Nil coalescing

Оператор ?? может использоваться для возврата левого операнда, если он не равен nil, в противном случае возвращается правый операнд.

Пример вида:

    author.User?.Name ?? "Anonymous"

значит тоже самое, что:

    author.User != nil ? author.User.Name : "Anonymous"

Оператор конвейера

Оператор конвейера | может использоваться для передачи результата выражения левого операнда в качестве первого аргумента выражения правого операнда.

Пример вида:

    user.Name | lower() | split(" ")

значит тоже самое, что:

    split(lower(user.Name), " ")

Предикаты

Предикат — это выражение. Предикаты можно использовать в функциях, таких как filter, all, any, one, none и других.

filter(0..9, {# % 2 == 0})
filter(tweets, {len(.Content) > 240})

Скобки можно опускать { }:

    filter(tweets, len(.Content) > 240)

Операции над строками

trim(str[, chars])
trimPrefix(str, prefix)
trimSuffix(str, suffix)
upper(str)
lower(str)
indexOf(str, substring)
lastIndexOf(str, substring)
hasPrefix(str, prefix)
hasSuffix(str, suffix)

Так же есть оператор matches для поиска регулярного выражения в строке:

    str matches "regular expression"

Для сопоставления целой строки с регулярным выражением следует использовать вариант:

    str matches "^regex$"

Функции времени

Поддерживаются Go типы для времени и интервалов (time.Time, time.Duration) time package.

Можно использовать операции сложения и вычитания над объектами с типом time.Time.

createdAt - now()
createdAt + duration("1h")
createdAt > now() - duration("1h")
date("2023-08-14")
date("15:04:05")
date("2023-08-14T00:00:00Z")
date("2023-08-14 00:00:00", "2006-01-02 15:04:05", "Europe/Zurich")

Функции над массивами

- all(array, predicate) - все объекты должны удовлетворять предикату
- any(array, predicate) - должен быть по крайней мере один объект, который удовлетворяет предикату
- one(array, predicate) - должен быть только один объект, который удовлетворяет предикату
- none(array, predicate) - ни один объект не должен удовлетворять предикату
- find(array, predicate) - возвращает первый объект, который удовлетворяет предикату
- findLast(array, predicate) - возвращает последний объект, который удовлетворяет предикату
- count(array[, predicate]) - возвращает число объектов, удовлетворяющих предикату
- first(array) - первый объект из массива
- last(array) - последний объект из массива

Примеры:

    all(tweets, {.Size < 280})
    any(tweets, {.Size > 280})
    none(tweets, {.Size > 280})
    find([1, 2, 3, 4], # > 2) == 3
    findLast([1, 2, 3, 4], # > 2) == 4
    count(users, .Age > 18)
    first([1, 2, 3]) == 1
    last([1, 2, 3]) == 3