2017-11-07 8 views
0

Client.ContainerStats(ctx context.Context, containerID string, stream bool)メソッドを使用して、コンテナのストリーミングの統計情報を取得します。
truestreamパラメータを渡すと、Dockerは接続を閉じず、定期的にコンテナの統計情報を含むJSONを送信します。 しかし、私はJSONのデコード方法がわからないので、JSONデータの開始と終了の場所がわからないためです。データのストリームからJSONをデコードするDocker GO SDK

私が今使っているのは、ストリームオプションを使用せず、データを定期的に取得してから、このようにデコードすることです。

stats, err := dockerClient.ContainerStats(ctx, container.ContainerID, false) 
msgBytes, _ := ioutil.ReadAll(stats.Body) 
var containerStats ContainerStats 
err = json.Unmarshal(msgBytes, &containerStats) 

私は何を探していますが、私はそれを呼び出すときにブロックする機能である、それは(私がデコードすることができる完全なJSONデータを意味する)JSONデータを受信したとき、それはからデコードされたデータを含む構造体を返します。 JSONを呼び出すと、Dockerに新しいリクエストを行うことなく次のstatを取得するためにその関数を再度呼び出すことができます。

  • カスタムを使用してマッピングしたい場合は、カスタム構造体
  • 上の結果はmap[string]interface{}

に結果を地図マップ:あなたのケースでは

答えて

2

、あなたは複数のオプションを持っていますあなたはこのような何かを行うことができます構造:

type myStruct struct { 
    Id  string `json:"id"` 
    Read string `json:"read"` 
    Preread string `json:"preread"` 
} 

// perform actions to retrieve logs in stats 
//... 

var containerStats myStruct 
json.NewDecoder(stats.Body).Decode(&containerStats) 
fmt.Println(containerStats.Id) 

このソリューションでは、あなたはマップしたいフィールドを決めなければなりません。しかし

、あなたはこのような何かを実行することができ、フィールドを指定しない場合:あなたはあなたのデータを操作する必要がある場合は、私が使用して最初のソリューションを使用することをお勧めいたします、と結論するに

//Perform actions to retrieve logs in stats 
//... 

var containerStats map[string]interface{} 
json.NewDecoder(stats.Body).Decode(&containerStats) 
fmt.Println(containerStats["id"]) 

をカスタム構造。


EDITED:truestreamパラメータを渡すことによって、ストリーム

を扱う、ドッキングウィンドウAPIが更新されますio.ReadCloserを返します。それから、io.ReadCloserを終了するのは発信者の責任です。

あなたがしなければならないことは、バッファ値をperdiodically読み取ることです。この例では

type myStruct struct { 
    Id  string `json:"id"` 
    Read  string `json:"read"` 
    Preread string `json:"preread"` 
    CpuStats cpu `json:"cpu_stats"` 
} 

type cpu struct { 
    Usage cpuUsage `json:"cpu_usage"` 
} 

type cpuUsage struct { 
    Total float64 `json:"total_usage"` 
} 

func main() { 
    ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second) 
    cli, e := client.NewEnvClient() 
    if e != nil { 
     panic(e) 
    } 
    stats, e := cli.ContainerStats(ctx, "container_id", true) 
    if e != nil { 
     fmt.Errorf("%s", e.Error()) 
    } 
    decoder := json.NewDecoder(stats.Body) 
    var containerStats myStruct 
    for { 
     select { 
     case <-ctx.Done(): 
      stats.Body.Close() 
      fmt.Println("Stop logging") 
      return 
     default: 
      if err := decoder.Decode(&containerStats); err == io.EOF { 
       return 
      } else if err != nil { 
       cancel() 
      } 
      fmt.Println(containerStats.CpuStats.Usage.Total) 
     } 
    } 
} 

、私たちは、新しいデータが到着したときに、stats.Body ReadCloserをデコード総CPU使用率を印刷し、5秒後にストリームをクローズしています。

+0

ありがとうございました。私の質問があなたを誤解させてしまってとても残念です。ストリーミングではない応答からJSONデータをデコードすることができます.Dockerは定期的にJSON統計データを送信します。つまり、同じ接続でデータを送信します。 ContainerStateは、[stats API](https://docs.docker.com/engine/api/v1.32/#operation/ContainerStats)からJSONの戻り値に一致するフィールドを持つカスタム構造体ですが、同じことがわかりませんでしたGO SDKの構造体としての名前。私は質問を更新しました。 – witoong623

+1

問題ありません、私は答えを更新します –

+0

ありがとう、私の場合、私はループでデコードを呼び出し、停止信号を受け取ったときに停止します。それで、json.DecoderはJSONデータの開始と終了を知っていますか?たとえば、JSON '{" name ":" witoong623 "}' DecoderはJSONの先頭に "{"があり、どこに"}"はデータの終わりで、正しいバイト数をデコードしますか? – witoong623

関連する問題