Logback Socket ログ収集ベストプラクティス¶
概要¶
企業では、Guanceのワークスペースに複数のアプリケーションのログが収集されます。これらのログがどの Service に由来するかを区別することが課題となります。ここでは、Pipeline を使用してログに Service タグを追加し、ログの出所を区別する方法を説明します。
DataKit には多くのログ収集方法がありますが、この記事では主に Java の Spring Boot アプリケーションで Socket を介してログを収集し、Logback の Socket を使用してログを DataKit に転送する方法に焦点を当てます。まず、運用担当者が DataKit で Socket コレクターを有効にし、DataKit を再起動します。次に、開発者がアプリケーションの logback-spring.xml ファイルに Appender を追加し、springProperty を宣言して、jar 起動時に Service 名をログに書き込めるようにします。その後、開発者は jar を起動し、ログに書き込む Service 名をアプリケーションに渡します。最後に、開発者はGuanceにログインし、ログモジュールの Pipeline タブで新しい Pipeline を作成し、運用担当者が有効にした Socket コレクターの Source を指定します。これにより、ログにタグが付与されて区別されるようになります。
以下に示すソリューションでは、開発者と運用担当者の両方の視点からこの機能を実現します。
ソリューション¶
運用担当者¶
Linux 環境¶
1 コレクターの有効化¶
DataKit がデプロイされた Linux サーバーにログインし、logging-socket.conf ファイルを新規作成します。
logging-socket.conf のファイル内容は以下の通りです。
[[inputs.logging]]
# only two protocols are supported:TCP and UDP
sockets = [
"tcp://0.0.0.0:9542",
#"udp://0.0.0.0:9531",
]
ignore = [""]
source = "socketdefault"
service = ""
pipeline = ""
ignore_status = []
character_encoding = ""
# multiline_match = '''^\S'''
remove_ansi_escape_codes = false
[inputs.logging.tags]
# some_tag = "some_value"
# more_tag = "some_other_value"
2 DataKit の再起動¶
Kubernetes 環境¶
Guanceにログインし、【インテグレーション】->【Datakit】-> 【Kubernetes】の順に進み、ガイドに従って DataKit をインストールします。デプロイに使用する datakit.yaml は後で修正する必要があります。手順は、logging-socket.conf ファイルを作成し、DataKit にマウントすることです。
1 ConfigMap への設定追加¶
logging-socket.conf: |-
[[inputs.logging]]
# only two protocols are supported:TCP and UDP
sockets = [
"tcp://0.0.0.0:9542",
#"udp://0.0.0.0:9531",
]
ignore = [""]
source = "pay-socket-service"
service = ""
pipeline = ""
ignore_status = []
character_encoding = ""
# multiline_match = '''^\S'''
remove_ansi_escape_codes = false
[inputs.logging.tags]
# some_tag = "some_value"
# more_tag = "some_other_value"
2 logging-socket.conf のマウント¶
- mountPath: /usr/local/datakit/conf.d/log/logging-socket.conf
name: datakit-conf
subPath: logging-socket.conf
3 DataKit の再起動¶
パラメータ説明¶
- sockets: プロトコルとポートです。
- ignore: ファイルパスのフィルタリングに使用します。glob ルールに従い、いずれかのフィルタ条件に一致するファイルは収集されません。
- source: データソースです。
- service: 新しく追加するタグです。空の場合は、デフォルトで $source が使用されます。
- pipeline: Pipeline を使用する際に、スクリプトのパスを定義します。
- character_encoding: エンコーディングを選択します。
- multiline_match: 複数行のマッチングを行います。
- remove_ansi_escape_codes: ANSI エスケープコード(標準出力のテキスト色など)を削除するかどうかです。値は true または false です。
開発者¶
1 依存関係の追加¶
プロジェクトの pom.xml に以下の依存関係を追加します。
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>4.9</version>
</dependency>
2 ログ設定への Appender 追加¶
この手順では、DataKit のアドレス、Socket ポート、Service、Source を外部から渡せるパラメータとして定義します。プロジェクトの logback-spring.xml ファイルに Appender を追加し、datakitHostIP、datakitSocketPort、datakitSource、datakitService を定義します。これらの値は、それぞれ guangce.datakit.host_ip、guangce.datakit.socket_port、guangce.datakit.source、guangce.datakit.service を介して外部から渡されます。
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<springProperty scope="context" name="datakitHostIP" source="guangce.datakit.host_ip" />
<springProperty scope="context" name="datakitSocketPort" source="guangce.datakit.socket_port" />
<springProperty scope="context" name="datakitSource" source="guangce.datakit.source" />
<springProperty scope="context" name="datakitService" source="guangce.datakit.service" />
<contextName>logback</contextName>
<!-- ログのルートディレクトリ -->
<property name="log.path" value="./logs/order"/>
<!-- ログ出力形式 -->
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - - %msg%n" />
<!-- コンソールへのログ出力 -->
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
...
<appender name="socket" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>${datakitHostIP:-}:${datakitSocketPort:-}</destination>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<timeZone>UTC+8</timeZone>
</timestamp>
<pattern>
<pattern>
{
"severity": "%level",
"source": "${datakitSource}",
"service": "${datakitService}",
"method": "%method",
"line": "%line",
"thread": "%thread",
"class": "%logger{40}",
"msg": "%message\n%exception"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="Console"/>
...
<appender-ref ref="socket" />
</root>
</configuration>
3 デフォルト値の設定¶
application.yml ファイルに以下の設定を追加します。これらのデフォルトパラメータは Logback に渡されます。
guangce:
datakit:
host_ip: 127.0.0.1 # datakit アドレス
socket_port: 9542 # datakit socket ポート
#source: mySource # コメントを解除しない場合、socket コレクターで定義された source が使用されます
#service: myService # コメントを解除しない場合、socket コレクターで定義された service が使用されます
4 アプリケーションの実行¶
1 Linux 環境¶
以下のコマンドを実行してアプリケーションを起動します。パラメータを渡さない場合は、application.yml のデフォルト値が使用されます。
java -jar pay-service-1.0-SNAPSHOT.jar --guangce.datakit.host_ip=172.26.0.231 --guangce.datakit.socket_port=9542 --guangce.datakit.source=pay-socket-source --guangce.datakit.service=pay-socket-service
2 Kubernetes 環境¶
Dockerfile に PARAMS を追加し、外部からパラメータを受け取れるようにします。
FROM openjdk:8u292
RUN echo 'Asia/Shanghai' >/etc/timezone
ENV jar pay-service-1.0-SNAPSHOT.jar
ENV workdir /data/app/
RUN mkdir -p ${workdir}
COPY ${jar} ${workdir}
WORKDIR ${workdir}
ENTRYPOINT ["sh", "-ec", "exec java ${JAVA_OPTS} -jar ${jar} ${PARAMS} 2>&1 > /dev/null"]
docker build -t 172.16.0.238/df-demo/istio-pay:v1 -f DockerfilePay .
docker push 172.16.0.238/df-demo/istio-pay:v1
deploy pay-deployment.yaml ファイルを作成し、PARAMS 環境変数を追加します。ここで guangce.datakit.host_ip、guangce.datakit.socket_port、guangce.datakit.source、guangce.datakit.service の値を渡します。渡さない場合はデフォルト値が使用されます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-pay-deployment
spec:
replicas: 1
selector:
matchLabels:
app: istio-pay-pod
template:
metadata:
labels:
app: istio-pay-pod
spec:
containers:
- env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: DD_AGENT_HOST
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.hostIP
- name: PARAMS
value: "--guangce.datakit.host_ip=$(DD_AGENT_HOST) --guangce.datakit.socket_port=9542 --guangce.datakit.source=pay-socket-source --guangce.datakit.service=pay-socket-service"
name: pay-container
image: 172.16.0.238/df-demo/istio-pay:v1
ports:
- containerPort: 8091
protocol: TCP
resources:
limits:
memory: 512Mi
requests:
memory: 256Mi
restartPolicy: Always
volumes:
- emptyDir: {}
name: datadir
5 Pipeline の設定¶
Socket Appender が出力するログは JSON 形式であるため、DataKit は Pipeline を使用して JSON 文字列を解析する必要があります。source と service はデフォルトのタグであるため、set_tag を使用する必要があります。
Guanceにログインし、【ログ】->【Pipelines】の順に進み、【Pipelines を作成】をクリックし、運用担当者が Socket コレクターを有効にする際に定義した source 名である socketdefault を選択します。解析ルールを以下のように定義します。
json(_,msg,"message")
json(_,class,"class")
json(_,thread,"thread")
json(_,severity,"status")
json(_,method,"method")
json(_,line,"line")
json(_,source,"source")
json(_,service,"service")
json(_,`@timestamp`,"time")
set_tag(service)
set_tag(source)
default_time(time)
ログサンプルを使用してテストが成功したら、【保存】をクリックします。ここでの解析ルールは、logback-spring.xml ファイルに追加した pattern と対応しています。
<pattern>
{
"severity": "%level",
"source": "${datakitSource}",
"service": "${datakitService}",
"method": "%method",
"line": "%line",
"thread": "%thread",
"class": "%logger{40}",
"msg": "%message\n%exception"
}
ログファイルの確認¶
アプリケーションのインターフェースにアクセスし、アプリケーションログを生成します。Guanceにログインし、【ログ】->【データ収集】-> pay-socket-source を選択してログの詳細を確認します。ここで、source と service が外部から渡されたパラメータに置き換えられていることが確認できます。

