// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may // not use this file except in compliance with the License. A copy of the // License is located at // // http://aws.amazon.com/apache2.0/ // // or in the "license" file accompanying this file. This file is distributed // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either // express or implied. See the License for the specific language governing // permissions and limitations under the License. package logger import ( "runtime" "strconv" "time" "github.com/cihub/seelog" ) var ( prevStats = &runtime.MemStats{} runtimeStatsLogger seelog.LoggerInterface initTime = time.Now() statsTicker = time.NewTicker(time.Minute * 2) ) func StartRuntimeStatsLogger(runtimeStatsLogFile string) (flush func()) { l, err := seelog.LoggerFromConfigAsString(runtimeStatsLogConfig(runtimeStatsLogFile)) if err != nil { seelog.Errorf("Error initializing the runtime stats log: %v", err) // If the logger cannot be initialized, use the provided dummy seelog.LoggerInterface, seelog.Disabled. l = seelog.Disabled } runtimeStatsLogger = l go run() return func() { statsTicker.Stop() runtimeStatsLogger.Flush() } } func run() { logStats() for range statsTicker.C { logStats() } } func logStats() { curStats := &runtime.MemStats{} runtimeStatsStart := time.Now() runtime.ReadMemStats(curStats) numGoRoutines := runtime.NumGoroutine() readMemStatsOverhead := time.Since(runtimeStatsStart) runtimeStatsLogger.Infof( "Time=%s, "+ "FreesCount=%d, "+ "HeapMemoryAlloc=%d, "+ "HeapMemoryInUse=%d, "+ "HeapMemoryIdle=%d, "+ "HeapMemoryReleased=%d, "+ "MallocCount=%d, "+ "StackMemoryInUse=%d, "+ "GarbageCollectionCount=%d, "+ "GarbageCollectionTime=%v, "+ "GCCPUFraction=%f, "+ "GoroutineCount=%d, "+ "UpTime=%v, "+ "ReadMemStatsOverhead=%s", time.Now().UTC().Format(time.RFC3339), curStats.Frees-prevStats.Frees, curStats.HeapAlloc, curStats.HeapInuse, curStats.HeapIdle, curStats.HeapReleased, curStats.Mallocs-prevStats.Mallocs, curStats.StackInuse, curStats.NumGC-prevStats.NumGC, time.Duration(curStats.PauseTotalNs-prevStats.PauseTotalNs)*time.Nanosecond, curStats.GCCPUFraction, numGoRoutines, time.Since(initTime), readMemStatsOverhead, ) prevStats = curStats } func runtimeStatsLogConfig(runtimeStatsLogFile string) string { config := ` ` return config }