Serverlessのための動的ログ制御


Serverlessアプリは非常にスケーラブルで利用可能なサービスを構築する非常に強力な方法です.
しかし、Serverlessアプリはまた、監視、デバッグ、および管理コンポーネントは、分散コンポーネントのために一意に困難ですが、ステートレスな性質、短い実行寿命と構成へのアクセス制限.
Observability “あなたの機能を冗長に”と“すべてのサービスの境界線をラップすることで、このジレンマの解決策として一般化されている”ログの要約.

However, this can degrade critical production performance and send logging and metric costs spiraling.


では、解決策は?
このポストは、動的なログコントロールを介して、シンプルで効果的なソリューションを探る.

可観測性


分散セルレスシステムは,現在と将来の故障に対して容易に監視する必要がある.これを達成するために、そのようなシステムは「観測可能」である必要がある.
可観測性は、現在のエラーを診断して、潜在的な失敗を予想するために豊かな前後関係を有するシステムのふるまいに、粒状の洞察を提供することを目指します.観測可能なシステムは,ログメトリック,イベント,トレースを介してシステムを監視するテレメトリを統合する.

Easy you say, just add lots of logging and metrics.


しかし、観測可能性を持つ痛ましいトレードオフは、遠隔測定の困難なコストであり、将来のその観測可能性の潜在的利益である.ログとログストレージの各ラインの各ライン.粗雑な伐採コストの驚きにつながることができます.
必要なのはテレメトリのコストを最小限に抑え、必要に応じて上下にスケールアップする方法である.
もちろん、あなたのサービスの正確な評価を持つことができますので、ログとメトリクスのベースラインレベルが必要です.しかし、あなたはしばしば特定のアラームまたはトリガーに応じてより大きな洞察を必要とします.

ダイナミックログ制御


Serverlessアプリは、動的なスケーリングとロギングのダウンの課題を提起します.
Serverless関数は一時的です.彼らはEC 2サーバや長寿命のDockerアプリケーションのようではありません.彼らはしばしば終了する前にミリ秒しか続かない.データベースからの状態やフェッチ状態をほとんど維持しないことは、すべての関数呼び出しで発生するようなオーバヘッドが大きすぎる場合があります.
しかし,環境変数がよく証明され,理解されている動的ログ制御に適応できる手法がある.

環境管理


AWSラムダが関数をロードするとき、それはゼロ遅延の関数によって読み取ることができる環境変数のセットを提供します.これらの変数を使用すると、ログコントロールの指示を使用してログの量とフォーカスを変更できます.
AWSコンソールのラムダ環境設定ページです.

環境変数を変更した場合(関数を再配備または変更せずに)、次の呼び出しは新しい環境値で実行されます.

So using special LOG environment variables, we can communicate our desired log level, filtering and sampling, and have our functions respond to these settings without modifying code or redeploying.
Sweet!


環境変数を変更すると、次の関数が起動されたときにコールドスタートが発生します.

ログコントロール


ログを制御するには、3つのログ環境変数を提案します.
  • ログフィルタ
  • ログオンオーバーライド
  • ログサンプル
  • あなたのログライブラリ(senselogs、ピノ、ウィンストン、…)に従いますこれらの変数を使用して、ログレベルまたはチャネルを指定します.
    LogHandフィルタは、有効なログレベルまたはチャネルのセットを定義します.有効なレベルは、出力を放出します.無効レベルが沈黙されます.
    例えば、
    LOG_FILTER='error,warn'
    
    これは、あなたのランムダスでロギング出力を有効にしますlog.error() and log.warn() にコールするtrace or debug .
    logCountオーバーライドは、logCountフィルタの設定に戻る前に、指定された時間の間LogHandフィルタを置き換える.LogSumオーバーライドは、1970年1月1日からミリ秒でUNIXエポックとして表された満了時間でプレフィックスされます.
    例えば、
    LOG_OVERRIDE='1629806612164:debug,trace'
    
    LogCountサンプルはリクエストの与えられたパーセンテージに適用されるサンプリングフィルタです.レベルのリストはパーセンテージでプリフィックスされます.
    例えば、これはリクエストの5 %を追跡します.
    LOG_SAMPLE='5%:trace'
    

    ライブラリのログ記録


    このテクニックは、ノード、PythonおよびJavaラムダ関数で動作します.これは、次のような最も人気のあるログライブラリを設定する簡単です.Bunyan , Debug , Pino , SenseLogs or Winston .
    理想的なログ記録ライブラリは、潜在的なログコードがほとんどの呼び出しのランタイムオーバーヘッドを発生させることなく、あなたの機能に埋め込まれることができるようにカスタムレベルを許可します.必要に応じて、そのカスタムレベルをLogCountフィルタまたはLogCountオーバーライドし、そのカスタムログ出力をオンに追加することができます.カスタムレベルを有効にすることができますし、他のレベルに影響を与えることなく無効にする必要があります.
    あなたのログ記録ライブラリが無効なログレベルのために非常に低いオーバーヘッドを持つことは非常に重要です.さもなければ、動的にスケーリングする利点は失われます.

    実装


    私はnoseljsのいくつかの例の下にsenselogsとpinoログライブラリを使用している.
    コードサンプルを表示するにはBunyan , Debug , Winston またはPythonをチェックアウトDynamic Logging Samples これらのテクニックを使用して各ライブラリとPythonの詳細なコードのサンプルがあります.
    github gists経由でも利用できます.Dynamic Log Control Gist
  • SenseLogs
  • Pino
  • 制御


    ここでは、このテクニックを使用する方法のサンプルですSenseLogs これには、logCountフィルタ、logCountオーバーライド、およびLogCountサンプル環境変数に対応する組み込みサポートがあります.Senselogsは、カスタムのログチャネルをサポートする非常に高速なserverlessログガーです.これは無効になったログレベルのほぼゼロコストです.
    import SenseLogs from 'senselogs'
    
    let log = new SenseLogs()
    
    exports.handler = async (event, context) => {
        //  This will be emitted if LOG_FILTER contains 'debug' as a log level
        log.debug('Hello world')
    
        //  EMF metrics can also be dynamically controlled
        log.metrics('trace', 'AcmeRockets/CriticalLaunchFailure', {explosion: 1})
    }
    
    もっと学ぶServerless Logging with SenseLogs .

    制御Pino


    ここでは、人気の使用方法のサンプルですPino 汎用ロガー.
    このサンプルでは、ログ環境変数を解析し、Pinoロガーを設定するために少量のコードを使用します.
    import Pino from 'pino'
    
    let {LOG_FILTER, LOG_OVERRIDE, LOG_SAMPLE} = process.env
    
    if (LOG_OVERRIDE != null) {
        let [expire, level] = LOG_OVERRIDE.split(':')
        if (level && Date.now() < expire) {
            LOG_FILTER = level
        }
    }
    let sample = 0, sampleRate, sampleLevels
    if (LOG_SAMPLE != null) {
        [sampleRate, sampleLevel]s = LOG_SAMPLE.split(':')
    }
    
    const pino = Pino({name: 'pino', level: LOG_FILTER})
    
    exports.handler = async (event, context) => {
        if (sampleRate && (sample++ % (100 / sampleRate)) == 0) {
            //  Apply the sample levels
            pino.level = sampleLevel
        }
        pino.debug('Debug message')
    }
    

    ログ設定管理


    診断に重要な問題がある場合は、ログレベルを増加させるためにLogCountオーバーライド環境変数を設定することで、ログをスケールアップできます.あなたのログライブラリに応じて、また、カスタムレベルを使用して特定のモジュールにログを集中することができます.
    APIを介して環境設定を変更することができますSenseDeep 開発スタジオ.

    All CLI


    AWS CLIは、関数の設定をupdate-function-configuration .
    例えば、
    EXPIRES=$((($(date +%s) + 3600) * 1000))
    aws lambda update-function-configuration --function-name MyFunction \
        --environment "Variables={LOG_OVERRIDE=${EXPIRES}:error,info,debug,trace,commerce}"
    
    これは、エラー時間、情報、デバッグ、トレースレベルとカスタムを含むように1時間のログレベルを上書きし、期限を計算しますcommerce レベル.

    コンソール


    これらの環境値をAWSコンソールを使って変更することもできます.
    単に機能に移動し、選択Configuration then Environment Variables then Edit を変更して保存します.

    Sensedeep Serverlessスタジオ


    より良い静けさSenseDeep Serverless Developer Studio これらのフィルタ設定を管理する統合された、高レベルの方法を提供します.

    概要


    このテクニックを使用すると、簡単かつ迅速にスケールアップすることができますし、必要に応じてログを集中します.あなたは、銀行を壊すことなく、ログとメトリックの良いベースレベルを維持することができますし、オンデマンドのログを増加します.

    もっと?


    ログライブラリライブラリのコードサンプルはLog Control Samples .
    senselogsはGitHub SenseLogs or NPM SenseLogs .
    そして、あなたはsensedeepのための無料開発ライセンスを取得することができますSenseDeep App またはhttps://www.sensedeep.com .