コンテンツにスキップ

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 ファイルを新規作成します。

cd /usr/local/datakit/conf.d/log
vi 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 の再起動
systemctl restart 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 の再起動
kubectl delete -f datakit.yaml
kubectl apply -f datakit.yaml

パラメータ説明

  • 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
kubectl apply -f pay-deployment.yaml

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 が外部から渡されたパラメータに置き換えられていることが確認できます。

image

image

フィードバック

このページは役に立ちましたか?