- PVSM.RU - https://www.pvsm.ru -
В этой статье я покажу несколько работающих решений задачи передачи и анализа логов из Java приложений в MS Azure. Мы рассмотрим решения как для windows, так и для linux виртуальных машин, находящихся как в облаке, так и on-premise. В качестве подсистемы логирования для Java будем использовать log4j2.
Для анализа логов будем использовать Azure Stream Analytics.
Чтобы понять о чём вообще идёт речь в статье — желательно обладать базовыми знаниями по log4j2 и некоторым ресурсам Azure, а именно stream analytics, event hub, blob storage.
Если у вас есть желание их (знания) освежить — вот ссылки
Apache Log4j 2 [1]
Azure Stream Analytics Documentation [2]
Azure Event Hubs [3]
Azure Storage [4]
Возможно кому-то покажется странным сама идея
Хотя Azure поддерживает Java [7] давно, особенно на уровне PaaS, предоставляя SDK для Java,
Для java есть несколько подсистем для логирования. Мы будем использовать именно log4j потому что
В качестве тествого приложения я брал самый обычный springboot starter app [8] с модулем spring-boot-starter-log4j2 но последней версии 2.0.0.M5, т.к. для одного из сценариев нужна будет последняя версия log4j.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>log4j2-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>log4j2-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M5</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<repositories>
<repository>
<id>sboot</id>
<name>your custom repo</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.0.M5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>2.0.0.M5</version>
</dependency>
<!-- Exclude Spring Boot's Default Logging -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Add Log4j2 Dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.0.0.M5</version>
</dependency>
</dependencies>
<pluginRepositories>
<pluginRepository>
<id>sbootplug</id>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.0.0.M5</version>
</plugin>
</plugins>
</build>
</project>
Для тестирования возможности добавить функционал по стримингу логов для уже готового приложения я ставил эксперименты над java minecraft сервером :)
А дальше будет несколько сценариев с указанием способа их реализации и присущими им ограничениям.
Смысл сценариев — организация пайплайна по
Особенности: Windows или Linux OS, VM в Azure или On-premise
Ограничения: нужна <определённая> версия log4j2
Настройка Log4j
В конфиге log4j2 должен быть определён HTTP appender
<Http name="Http" url='https://<event hubs namespace>.servicebus.windows.net/<event hub>/messages?timeout=60&api-version=2014-01'>
<Property name="Authorization" value="SharedAccessSignature sr=xxxsig=yyyse=zzzskn=<event hub poicy>" />
<Property name="Content-Type" value="application/atom+xml;type=entry;charset=utf-8" />
<Property name="Host" value="<event hubs namespace>.servicebus.windows.net" />
<JsonLayout properties="true"/>
</Http>
Чуть подробнее про Authorization хедер.
Для того, чтобы работать с REST API EventHub требуется авторизация по т.н. SaS токену [9]. Это по сути, хеш урла ресурса и времени жизни токена.
Для формирования sas токена кроме event hub namespace и event hub также потребуется знать имя и ключ policy event hub'а с правами на отсылку сообщений. Вся информация есть на portal.azure.com.
Майкрософт предоставляет примеры кода [10] для генерации Authorization хедера на различных языках, в т.ч. на Java.
Я же пользуюсь вот этим html снипетом [11], который нашёл в интернетах и слегка доработал — он генерирует Authorization хедер для EventHub с временем жизни равным году.
Настройка Stream Analytics
В Stream Analytics джобе настраивается input с EventHub с параметрами
Event serialization format = JSON, Encoding = UTF-8, Event compression type = None
При этом доступ к данным, которые пушит http appender log4j выполняется просто, непосредственно через select * from (и так будет не всегда)
Чтобы хоть чуть-чуть показать мощь Stream Analytics посмотрите пожалуйста на вот такой запрос
WITH errors as (
SELECT
*
FROM
javahub
WHERE level='FATAL' OR level='ERROR'
),
activity as (
SELECT
System.TimeStamp AS WindowEnd, level, COUNT(*)
FROM
javahub
GROUP BY TumblingWindow( second , 10 ), level
)
select * into pbierrors from errors;
select * into pbiactivity from activity;
Этим запросом мы
Пара кликов мышкой в power bi и мы можем мониторить не только ошибки приложения, но и следить за общей активностью.
Особенности: не нужен EventHub. Меньший объём трафика (логи архивируются перед передачей), не надо заморачиваться с SaS токенами.
Ограничения: VM только в Azure. Логи поступают с небольшой задержкой.
Настройка Log4j
Обязательно надо обратить внимание, что
<RollingRandomAccessFile name='File' fileName="latest.log" filePattern="logs%d{yyyy-MM-dd}%d{HH}%d{HH-mm-ss}-%i.log.gz">
<PatternLayout pattern='%d{yyyy-MM-dd HH:mm:ss};%level;%msg%n'>
<header>TS;LEVEL;MESSAGE%n</header>
</PatternLayout>
<Policies>
<CronTriggeringPolicy schedule='10 * * * * ?' evaluateOnStartup='true'/>
<SizeBasedTriggeringPolicy size='10 MB'/>
</Policies>
<DefaultRolloverStrategy max='100'/>
</RollingRandomAccessFile>
Настройка Azure Monitoring & Diagnostics Extension для VM
az vm extension set --name IaaSDiagnostics
--publisher "Microsoft.Azure.Diagnostics"
--resource-group <group name>
--vm-name <vm name>
--protected-settings "privateSettings.json"
--settings "publicSettings.json"
--version "1.11.1.0"
{
"WadCfg": {
"DiagnosticMonitorConfiguration": {
"overallQuotaInMB": 10000,
"DiagnosticInfrastructureLogs": {
"scheduledTransferLogLevelFilter": "Error"
},
"Directories": {
"scheduledTransferPeriod": "PT1M",
"DataSources": [
{
"containerName": "<blob container name in your storage account>",
"Absolute": {
"path": "C:\<folder>\<to monitor>",
"expandEnvironment": false
}
}
]
}
}
},
"StorageAccount": "<your storage account name>",
"StorageType": "Table"
}
{
"storageAccountName": "<your storage account name>",
"storageAccountKey": "<storage account access key (use portal to obtain it)>"
}
Настройка Stream Analytics
В качестве input используется Blob storage с параметрами:
PathPattern — путь до файлов с архивированными логами в Blob storage. Если вы делали иерархию директорий (как в примере выше) — то тут она также должна быть учтена.
Пример: WAD/be7f1c92-2841-4ea1-b9d8-ec83c211b8ea/IaaS/_minesrv/{date}/{time}/
DateFormat должен быть задан в соответствии с форматом паттерна %d в log4j
Event serialization format = CSV, Delimeter = semicolon, Encoding= UTF-8, Event compression type = GZIP
Доступ к данным в запросах Steam Analytics также непосредственный.
select * from вернёт таблицу с полями TS, LEVEL, MESSAGE (в соответствии с хедером, определённым в log4j)
WITH
SessionInfo AS (
SELECT
TS, 'START' as EVENT, SUBSTRING(MESSAGE, 0, REGEXMATCH(MESSAGE, '[ ]*joined the game')) as PLAYER
FROM
logslob
TIMESTAMP BY TS
WHERE REGEXMATCH(MESSAGE, 'joined the game') > 0
UNION
SELECT
TS, 'END' as EVENT, SUBSTRING(MESSAGE, 0, REGEXMATCH(MESSAGE, '[ ]*left the game')) as PLAYER
FROM
logslob
TIMESTAMP BY TS
WHERE REGEXMATCH(MESSAGE, 'left the game') > 0
),
RawLogs AS (
SELECT
TS, LEVEL, MESSAGE
FROM
logslob
TIMESTAMP BY TS
)
SELECT * INTO sbq from SessionInfo;
SELECT * INTO pbi from RawLogs;
Тут мы пересылаем в оутпут RawLogs все логи, а вот в SessionInfo отдельно записи о старте и остановке сессии с указанием имени игрока — для последующих уведомлений
Особенности: минимальная настройка Log4j (и минимальные требования к версии log4j) — просто запись в файл. Обрабатываются все новые записи в файле (без задержки)
Ограничения: VM только в Azure, запись в файл только в json, более сложный доступ к данным из stream analytics job
Настройка Log4j
Логи должны писаться в формате json и обязательно — каждый объект на одну строчку файла с логами
К счастью, с помощью log4j это можно настроить просто
<File name="FileLog" fileName="app.log">
<JsonLayout properties="true" compact="true" eventEol="true"/>
</File>
Настройка Azure Linux Diagnostics Extension для VM
az vm extension set --name LinuxDiagnostic
--publisher "Microsoft.Azure.Diagnostics"
--resource-group <group name>
--vm-name <vm name>
--protected-settings "linux_privateSettings.json"
--settings "linux_publicSettings.json"
--version "3.0.109"
linux_publicSettings.json:
{
"StorageAccount": "<your storage account>",
"sampleRateInSeconds": 15,
"ladCfg": {
"diagnosticMonitorConfiguration": {
"metrics": {
"metricAggregation": [
{
"scheduledTransferPeriod": "PT1H"
},
{
"scheduledTransferPeriod": "PT1M"
}
],
"resourceId": "/subscriptions/<subscription id>/resourceGroups/<resource group>/providers/Microsoft.Compute/virtualMachines/<vm name>"
}
}
},
"fileLogs": [
{
"file": "/<path>/<to>/<log file>",
"sinks": "LinuxEH"
}
]
}
{
"storageAccountName" : "<your storage account>",
"storageAccountSasToken": "<sas token for storage account - generate it on the portal>",
"sinksConfig": {
"sink": [
{
"name": "LinuxEH",
"type": "EventHub",
"sasURL": "https://<event hub namespace>.servicebus.windows.net/<event hub>?sr=xxxxxx&sig=yyyy&se=zzzz&skn=<policy name>"
}
]
}
}
Настройка Stream Analytics
В Stream Analytics джобе настраивается input с EventHub с параметрами
Event serialization format = JSON, Encoding = UTF-8, Event compression type = None
При этом доступ к данным, которые логируются, не такой простой. Если мы просто выполним select * from мы увидим примерно вот такую картину
т.е. нужны нам данные скрыты где-то в проперти json объекта, хранимого в поле PROPERTIES
Но и эту проблему в stream analytics можно решить красиво (да, мне очень нравится эта штука :)), например вот таким запросом
with events as (
select UDF.to_json(properties.MSG) as obj
from ehtest
)
select obj.* from events
где UDF.to_json — это написанная нами функция по конвертации строки в JSON объект (да, там ещё и функции можно писать, на javascript...)
В результате мы получаем простой доступ к данным лога
Надеюсь, эта статья окажется кому-нибудь полезна.
Мне она уже принесла большую пользу, т.к. только с помощью реализации практических кейсов можно реально понять возможности и зрелость той или иной технологии.
Если вдруг я какие-нибудь сценарии упустил — напишите пожалуйста об этом в комментах.
Автор: Потураев Андрей
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/java/267638
Ссылки в тексте:
[1] Apache Log4j 2: https://logging.apache.org/log4j/2.x/
[2] Azure Stream Analytics Documentation: https://docs.microsoft.com/en-us/azure/stream-analytics/
[3] Azure Event Hubs: https://docs.microsoft.com/en-us/azure/event-hubs/
[4] Azure Storage: https://docs.microsoft.com/en-us/azure/
[5] хостинга: https://www.reg.ru/?rlink=reflink-717
[6] отчета по анализу рынка IaaS 20011-2026 в Германии от Colorbridge Gmbh: https://digest.colobridge.net/iaas#form
[7] поддерживает Java: https://docs.microsoft.com/en-us/java/azure/java-sdk-azure-install
[8] springboot starter app: https://spring.io/guides/gs/spring-boot/
[9] SaS токену: https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-sas
[10] примеры кода: https://docs.microsoft.com/en-us/rest/api/eventhub/generate-sas-token
[11] html снипетом: https://jsfiddle.net/Dronopotamus/m1sLrouw/7/
[12] Azure CLI 2: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest
[13] Источник: https://habrahabr.ru/post/341660/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.