Системный журнал EVPC#
Настройка системного журнала#
Настройки отправляемых сообщений указываются в файле /conf/logback.xml. Отправляемые сообщения имеют формат JSON или XML согласно шаблону, описываемому в файле logback.xml.
Для логирования информации о работе EVPC необходимо в файле logback.xml заполнить блок:
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="file"/>
</root>
В нем необходимо указать наименования appenders, в которых описан вывод логов в конкретные места. В данном примере описан вывод логов EVPC в консоль управления EVPC и в файл.
Для логирования сообщений необходимо:
Настроить шаг обработки сообщения
logв параметреprocessorsконфигурационного файла epf.conf.Заполнить файл logback.xml необходимыми настройками логирования и поместить его в директорию conf перед запуском установки EVPC. Примеры заполненных файлов logback.xml приведены ниже в данном разделе.
Определить в файле
logback.xml, куда будет производиться отправка сообщений. Для этого необходимо заполнить блок настроек:
<logger name="ru.sbt.ss.reactive.stream.transformers.logging.MessageLogger" level="info" additivity="false" >
<appender-ref ref="GateLogger"/>
<appender-ref ref="STDOUT"/>
<appender-ref ref="file"/>
</logger>
В данном примере логирование сообщений, проходящих через EVPC, настроено на три приемника:
в централизованную систему журналирования: настройки задаются в appender
GateLogger;в консоль управления EVPC: настройки задаются в appender
STDOUT;в файл: настройки задаются в appender
file.
Прописать настройки в конфигурационном файле vars.yml.
Перед установкой (переустановкой) новой версии EVPC необходимо в конфигурационном файле vars.yml заполнить блок:
logback:
level: info
# loggers:
# - name: "ru.sbt.cep"
# level: info
# - name: "org.apache.kafka"
# level: warn
# - name: "com.typesafe.akka"
# level: info
# kafka: # Отправка логов в Apache Kafka
# systemLogsTopic: sys-topic # Топик для отправки системных логов
# systemLogsTopic_never_block: true # Блокировка работы приложения при недоступности Kafka (по умолчанию - блокируется, при true недоставленные сообщения в kafka отбрасываются)
# systemLogsTopic_discarding_threshold: 20 # Процент свободного места в очереди отправки сообщений при достижении которого будут удаляться сообщения уровня TRACE, DEBUG, INFO
# systemLogsTopic_queue_size: 512 # Размер очереди для отправки в Кафку
# businessLogsTopic: business-topic # Топик для отправки бизнес логов
# businessLogsTopic_never_block: true # Блокировка работы приложения при недоступности Kafka (по умолчанию - блокируется, при true недоставленные сообщения в kafka отбрасываются)
# businessLogsTopic_discarding_threshold: 20 # Процент свободного места в очереди отправки сообщений при достижении которого будут удаляться сообщения уровня TRACE, DEBUG, INFO
# businessLogsTopic_queue_size: 512 # Размер очереди для отправки в Кафку
# businessLogsTopic_log_level: "info" # Уровень логирования TRACE, DEBUG, INFO
# retries: 3 # Количество переиницилизации продьюсера, если параметр не задан, по умолчанию значение 3
# interval: 1000 # Интервал между переиницилизациями, по умолчанию 1000 мс. Задается в мс.
# multiplier: 1 # Множитель интервала переинициализации, по умолчанию значение 1.
# never_block: false # блокировка работы приложения при недоступности Kafka центральной системы журналирования Platform V Monitor (по умолчанию - блокируется, при true недоставленные сообщения отбрасываются)
# properties:
# "bootstrap.servers": "host:port,host2:port2"
# "client.id": "epf-cluster-test"
# "config.providers": decode
# "config.providers.decode.class": ru.sbt.ss.kafka.DecryptionConfigProvider
# "config.providers.decode.param.security.encoding.key": ssl/secret.pass
# "config.providers.decode.param.security.encoding.class": ru.sbt.ss.password.BaseEncryptor
#
# "security.protocol": SSL
# "ssl.endpoint.identification.algorithm": ""
# "ssl.keystore.location": "ssl/epf.jks"
# "ssl.truststore.location": "ssl/epf.jks"
#
# "ssl.keystore.password": <password>
# "ssl.truststore.password": <password>
# "ssl.key.password": <password>
Для настройки отправки сообщений в централизованную систему журналирования Platform V Monitor необходимо заполнить блок appender GateLogger файла logback.xml (пример описан ниже).
При заполнении файла logback.xml стоит обратить внимание на заполнение следующих параметров:
Параметр |
Описание |
Значение по умолчанию |
|---|---|---|
|
Тип сообщения. Доступные значения: XML или JSON |
JSON |
|
Путь до RqUID (case sensitive) в логируемых сообщениях xpath (//rqUID) или jsonpath ($…rqUID) |
$…rqUID |
|
Имя topic записи сообщений логов |
|
|
Идентификатор продюсера Kafka, по которому можно однозначно идентифицировать продюсер Apache Kafka |
пусто |
|
Объявление провайдера шифрования паролей. Значение не изменять |
decode |
|
Класс провайдера шифрования паролей. Значение не изменять |
|
|
Путь до файла, содержащего ключ шифрования паролей |
|
|
Класс шифрования паролей. Значение не изменять |
|
|
Тип протокола подключения к системе журналирования |
SSL |
|
Проверка сертификата на соответствия hostname |
|
|
Расположение файла keystore |
|
|
Расположение файла truststore |
|
|
Пароль keystore в зашифрованном виде |
|
|
Пароль truststore в зашифрованном виде |
|
|
Ключ шифрования паролей в зашифрованном виде |
|
|
Hosts подключения к системе журналирования |
host:port,host:port |
Пример конфигурации логирования в системный вывод#
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{60} %X{sourceThread} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
Логирование в централизованную систему журналирования Platform V Monitor#
Для EVPC может быть настроена отправка системных журналов в централизованную систему журналирования Platform V Monitor.
Предварительно необходимо выполнить следующие действия:
узнать адреса брокеров Apache Kafka централизованной системы журналирования Platform V Monitor;
узнать названия топиков централизованной системы журналирования Platform V Monitor, куда будут отправляться журналы EVPC;
выпустить сертификат подключения к Apache Kafka централизованной системы журналирования Platform V Monitor.
Пример файла logback.xml с заполненными настройками представлен в файле example_logback.
Доступные уровни логирования системного журнала#
Имя логирования |
Описание |
Примечание |
|---|---|---|
TRACE |
Отражает менее приоритетные события для отладки |
Уровень TRACE не рекомендуется включать в Промышленной среде |
DEBUG |
Отражает полную отладочную информацию. На этом уровне в системный журнал пишутся передаваемые клиентские запросы, а так же отправляемые ответы в адрес клиентов |
Уровень DEBUG не рекомендуется включать в Промышленной среде |
INFO |
Уровень логирования по умолчанию. События отражают информационные события системного журнала |
|
WARN |
Уровень отражает предупреждения и некритические ошибки обработки запросов/состояния сервиса |
|
ERROR |
Уровень отражает критические ошибки обработки запросов/состояния сервиса |
Конфигурация логирования с возможностью отправки логов в топик Kafka#
Пример файла logback.xml с заполненными настройками логирования с возможностью отправки логов в топик Kafka представлен в файле example_logback.
Схема логов#
Логи разделены на системные и бизнес логи. К бизнес логам относятся логи трансформации событий.
Системные логи (name=SystemLogAppender)#
В системных логах указаны следующие поля JSON-сообщения:
timestamp— время сообщения лога;level— уровень лога;projectName— название проекта(namespace) в k8s(DropApp);pod— название pod в проекте;deployment— имя манифеста с kind: Deployment;message— описание действий.
Бизнес логи (name=BusinessLogAppender)#
В бизнес логах трансформации событий указаны следующие поля JSON-сообщения:
timestamp— время сообщения лога;level— уровень лога;projectName— название проекта(namespace) в k8s(DropApp);pod— название pod в проекте;deployment— имя манифеста с kind: Deployment;operationName— имя интеграционного потока, получаем из поляnameблокаflowконфигурации обработчика;eventId— идентификатор события;source— источник данных;destination— назчение данных (topic/очередь);message— описание действий.
Для бизнес логов в параметрах appender необходимо указывать настройку transformationLog со значением true (по умолчанию false), для включения в логи полей eventId, source, destination.
Настройка appender бизнес логов при запуске Jenkins с использованием параметра logLevel#
Параметр logLevel определяет уровень логирования DSL-логов универсального обработчика для определенного задания Jenkins.
Для отправки логов в соответствии с настройками appender, необходимо в conf/logback.xml добавить logger с именем, совпадающим с именем задания Jenkins. Имя задания Jenkins определяется в настройках конфигурации потока обработки, в параметре name.
При запуске нескольких заданий Jenkins, необходимо для каждого задания Jenkins добавить соответствующий logger.
В случае, если задание Jenkins запускается без параметра logLevel, то используется logger класса ru.sbt.cep.flow.event.process.flow.function.EventHolderTransformer с настройками уровня логирования и используемым appender из conf/logback.xml. Подробнее указано в примере example_logback.
Изменение уровня логирования#
Возможно изменение уровня логирования при обращении к endpoint, на котором запущен healthCheck.
Схема:
openapi: 3.0.1
info:
description: "Logger runtime update"
version: "1.0.0"
title: "Logging swagger"
servers:
- url: "http://localhost:8080"
description: "Logger runtime update"
paths:
/loggers:
get:
summary: "Текущее состояние логеров"
description: |
**Текущее состояние логеров** \
curl http://localhost:8080/loggers
responses:
"200":
description: "Success"
content:
application/json:
schema:
type: array
items:
type: object
properties:
name:
type: string
example: "ru.sbt.ss"
level:
type: string
example: "INFO"
"405":
description: "Incorrect method"
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Incorrect method"
put:
summary: "Изменение уровня логирования логера с указанным именем"
description: |
**Изменение уровня логирования логера с указанным именем** \
curl -X PUT http://localhost:8080/loggers -d '{"name":"ru.sbt.ss","level":"info"}'
requestBody:
required: true
content:
"application/json":
schema:
type: object
required:
- name
- level
properties:
name:
type: string
example: "ru.sbt.ss"
level:
type: string
example: "INFO"
responses:
"200":
description: "Success"
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Change logger ru.sbt.ss to level info"
"400":
description: "Incorrect data"
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Incorrect data"
"403":
description: "Изменение незаданных в logback логеров"
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Changing level of org.apache.kafka logger is prohibited"
"404":
description: "Not found"
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Logger with name ru.sbt.ss not found"
"405":
description: "Incorrect method"
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Incorrect method"
/loggers/{loggerName}:
get:
summary: "Текущий уровень логирования логера с указанным именем"
description: |
**Текущий уровень логирования логера с указанным именем** \
curl -v http://localhost:8080/loggers/ru.sbt.ss
parameters:
- in: path
name: loggerName
schema:
type: string
required: true
description: "Имя логгера, информация о котором требуется"
responses:
"200":
description: "Success"
content:
application/json:
schema:
type: object
properties:
name:
type: string
example: "ru.sbt.ss"
level:
type: string
example: "INFO"
"400":
description: "Incorrect data"
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Incorrect data"
"404":
description: "Not found"
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Logger with name ru.sbt.ss not found"
"405":
description: "Incorrect method"
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Incorrect method"
Часто встречающиеся события в файлах логов#
Часто встречающиеся события в файлах логов типа ERROR#
Отсутствует egress EVTA:
15:48:19.823 [grpc-default-executor-0] ERROR r.s.s.r.s.g.c.GrpcClientStatusStreamObserver - Error on connect grpc stream: UNAVAILABLE: Unable to resolve host reactivestreamadapter-evta-os
io.grpc.StatusRuntimeException: UNAVAILABLE: Unable to resolve host reactivestreamadapter-evta-os
at io.grpc.Status.asRuntimeException(Status.java:535)
at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:487)
at io.grpc.internal.DelayedClientCall$DelayedListener$3.run(DelayedClientCall.java:470)
at io.grpc.internal.DelayedClientCall$DelayedListener.drainPendingCallbacks(DelayedClientCall.java:509)
at io.grpc.internal.DelayedClientCall$1DrainListenerRunnable.runInContext(DelayedClientCall.java:298)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.RuntimeException: java.net.UnknownHostException: reactivestreamadapter-evta-os: Name or service not known
at io.grpc.internal.DnsNameResolver.resolveAddresses(DnsNameResolver.java:223)
at io.grpc.internal.DnsNameResolver.doResolve(DnsNameResolver.java:282)
at io.grpc.grpclb.GrpclbNameResolver.doResolve(GrpclbNameResolver.java:63)
at io.grpc.internal.DnsNameResolver$Resolve.run(DnsNameResolver.java:318)
... 3 common frames omitted
Caused by: java.net.UnknownHostException: reactivestreamadapter-evta-os: Name or service not known
at java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
at java.base/java.net.InetAddress$PlatformNameService.lookupAllHostAddr(InetAddress.java:929)
at java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1515)
at java.base/java.net.InetAddress$NameServiceAddresses.get(InetAddress.java:848)
at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1505)
at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1364)
at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1298)
at io.grpc.internal.DnsNameResolver$JdkAddressResolver.resolveAddress(DnsNameResolver.java:631)
at io.grpc.internal.DnsNameResolver.resolveAddresses(DnsNameResolver.java:219)
... 6 common frames omitted
Не удалось расшифровать зашифрованный пароль:
16:24:04.916 [main] ERROR ru.sbt.ss.password.BaseEncryptor - Can't decrypt by the set parameters
Не удалось подключиться к Apache Kafka (подробную причину ищем в логах egress EVTA):
16:33:32.878 [grpc-default-executor-0] ERROR r.s.s.r.s.g.c.GrpcClientStatusStreamObserver - Error on connect grpc stream: INTERNAL: Failure create subscriber from configuration, Error message: org.apache.kafka.common.KafkaException: Failed to construct kafka producer
io.grpc.StatusRuntimeException: INTERNAL: Failure create subscriber from configuration, Error message: org.apache.kafka.common.KafkaException: Failed to construct kafka producer
at io.grpc.Status.asRuntimeException(Status.java:535)
at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:487)
at io.grpc.internal.DelayedClientCall$DelayedListener$3.run(DelayedClientCall.java:470)
at io.grpc.internal.DelayedClientCall$DelayedListener.delayOrExecute(DelayedClientCall.java:434)
at io.grpc.internal.DelayedClientCall$DelayedListener.onClose(DelayedClientCall.java:467)
at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:563)
at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:70)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:744)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:723)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Отсутствует/требуется блок в
conf/defaults.json:
Exception in thread "main" com.typesafe.config.ConfigException$UnresolvedSubstitution: mapping/flow-example.conf: 7: Could not resolve substitution to a value: ${defaults.grpc-example}
at com.typesafe.config.impl.ConfigReference.resolveSubstitutions(ConfigReference.java:111)
at com.typesafe.config.impl.ResolveContext.realResolve(ResolveContext.java:179)
at com.typesafe.config.impl.ResolveContext.resolve(ResolveContext.java:142)
at com.typesafe.config.impl.SimpleConfigObject$ResolveModifier.modifyChildMayThrow(SimpleConfigObject.java:380)
at com.typesafe.config.impl.SimpleConfigObject.modifyMayThrow(SimpleConfigObject.java:313)
at com.typesafe.config.impl.SimpleConfigObject.resolveSubstitutions(SimpleConfigObject.java:399)
at com.typesafe.config.impl.ResolveContext.realResolve(ResolveContext.java:179)
at com.typesafe.config.impl.ResolveContext.resolve(ResolveContext.java:142)
at com.typesafe.config.impl.SimpleConfigObject$ResolveModifier.modifyChildMayThrow(SimpleConfigObject.java:380)
at com.typesafe.config.impl.SimpleConfigObject.modifyMayThrow(SimpleConfigObject.java:313)
at com.typesafe.config.impl.SimpleConfigObject.resolveSubstitutions(SimpleConfigObject.java:399)
at com.typesafe.config.impl.ResolveContext.realResolve(ResolveContext.java:179)
at com.typesafe.config.impl.ResolveContext.resolve(ResolveContext.java:142)
at com.typesafe.config.impl.ResolveContext.resolve(ResolveContext.java:231)
at com.typesafe.config.impl.SimpleConfig.resolveWith(SimpleConfig.java:78)
at com.typesafe.config.impl.SimpleConfig.resolve(SimpleConfig.java:68)
at com.typesafe.config.impl.SimpleConfig.resolve(SimpleConfig.java:63)
at com.typesafe.config.impl.SimpleConfig.resolve(SimpleConfig.java:41)
at ru.sbt.cep.flow.event.process.akka.Main$.delayedEndpoint$ru$sbt$cep$flow$event$process$akka$Main$1(Main.scala:123)
at ru.sbt.cep.flow.event.process.akka.Main$delayedInit$body.apply(Main.scala:28)
at scala.Function0.apply$mcV$sp(Function0.scala:42)
at scala.Function0.apply$mcV$sp$(Function0.scala:42)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
at scala.App.$anonfun$main$1(App.scala:98)
at scala.App.$anonfun$main$1$adapted(App.scala:98)
at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:575)
at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:573)
at scala.collection.AbstractIterable.foreach(Iterable.scala:933)
at scala.App.main(App.scala:98)
at scala.App.main$(App.scala:96)
at ru.sbt.cep.flow.event.process.akka.Main$.main(Main.scala:28)
at ru.sbt.cep.flow.event.process.akka.Main.main(Main.scala)