Gemini
Initial commit
fce10de
package profiler
import (
"context"
"fmt"
"os"
"runtime"
"strconv"
"time"
"log/slog"
"math"
)
// Profile represents performance metrics for an operation
type Profile struct {
Operation string `json:"operation"`
Duration time.Duration `json:"duration_ns"`
MemoryBefore uint64 `json:"memory_before_bytes"`
MemoryAfter uint64 `json:"memory_after_bytes"`
MemoryDelta int64 `json:"memory_delta_bytes"`
LinesCount int `json:"lines_count,omitempty"`
BytesCount int64 `json:"bytes_count,omitempty"`
Timestamp time.Time `json:"timestamp"`
}
// String returns a human-readable representation of the profile
func (p *Profile) String() string {
return fmt.Sprintf("[%s] %s: duration=%v, memory_delta=%+dB, lines=%d, bytes=%d",
p.Timestamp.Format("15:04:05.000"),
p.Operation,
p.Duration,
p.MemoryDelta,
p.LinesCount,
p.BytesCount,
)
}
func safeMemoryDelta(after, before uint64) int64 {
if after > math.MaxInt64 || before > math.MaxInt64 {
if after >= before {
diff := after - before
if diff > math.MaxInt64 {
return math.MaxInt64
}
return int64(diff)
}
diff := before - after
if diff > math.MaxInt64 {
return -math.MaxInt64
}
return -int64(diff)
}
return int64(after) - int64(before)
}
// Profiler provides minimal performance profiling capabilities
type Profiler struct {
logger *slog.Logger
enabled bool
}
// New creates a new Profiler instance
func New(logger *slog.Logger, enabled bool) *Profiler {
return &Profiler{
logger: logger,
enabled: enabled,
}
}
// ProfileFunc profiles a function execution
func (p *Profiler) ProfileFunc(ctx context.Context, operation string, fn func() error) (*Profile, error) {
if !p.enabled {
return nil, fn()
}
profile := &Profile{
Operation: operation,
Timestamp: time.Now(),
}
var memBefore runtime.MemStats
runtime.ReadMemStats(&memBefore)
profile.MemoryBefore = memBefore.Alloc
start := time.Now()
err := fn()
profile.Duration = time.Since(start)
var memAfter runtime.MemStats
runtime.ReadMemStats(&memAfter)
profile.MemoryAfter = memAfter.Alloc
profile.MemoryDelta = safeMemoryDelta(memAfter.Alloc, memBefore.Alloc)
if p.logger != nil {
p.logger.InfoContext(ctx, "Performance profile", "profile", profile.String())
}
return profile, err
}
// ProfileFuncWithMetrics profiles a function execution and captures additional metrics
func (p *Profiler) ProfileFuncWithMetrics(ctx context.Context, operation string, fn func() (int, int64, error)) (*Profile, error) {
if !p.enabled {
_, _, err := fn()
return nil, err
}
profile := &Profile{
Operation: operation,
Timestamp: time.Now(),
}
var memBefore runtime.MemStats
runtime.ReadMemStats(&memBefore)
profile.MemoryBefore = memBefore.Alloc
start := time.Now()
lines, bytes, err := fn()
profile.Duration = time.Since(start)
profile.LinesCount = lines
profile.BytesCount = bytes
var memAfter runtime.MemStats
runtime.ReadMemStats(&memAfter)
profile.MemoryAfter = memAfter.Alloc
profile.MemoryDelta = safeMemoryDelta(memAfter.Alloc, memBefore.Alloc)
if p.logger != nil {
p.logger.InfoContext(ctx, "Performance profile", "profile", profile.String())
}
return profile, err
}
// Start begins timing an operation and returns a function to complete the profiling
func (p *Profiler) Start(ctx context.Context, operation string) func(lines int, bytes int64) *Profile {
if !p.enabled {
return func(int, int64) *Profile { return nil }
}
profile := &Profile{
Operation: operation,
Timestamp: time.Now(),
}
var memBefore runtime.MemStats
runtime.ReadMemStats(&memBefore)
profile.MemoryBefore = memBefore.Alloc
start := time.Now()
return func(lines int, bytes int64) *Profile {
profile.Duration = time.Since(start)
profile.LinesCount = lines
profile.BytesCount = bytes
var memAfter runtime.MemStats
runtime.ReadMemStats(&memAfter)
profile.MemoryAfter = memAfter.Alloc
profile.MemoryDelta = safeMemoryDelta(memAfter.Alloc, memBefore.Alloc)
if p.logger != nil {
p.logger.InfoContext(ctx, "Performance profile", "profile", profile.String())
}
return profile
}
}
var globalProfiler *Profiler
// IsProfilingEnabled checks if profiling is enabled via environment variables
func IsProfilingEnabled() bool {
if enabled, err := strconv.ParseBool(os.Getenv("GITHUB_MCP_PROFILING_ENABLED")); err == nil {
return enabled
}
return false
}
// Init initializes the global profiler
func Init(logger *slog.Logger, enabled bool) {
globalProfiler = New(logger, enabled)
}
// InitFromEnv initializes the global profiler using environment variables
func InitFromEnv(logger *slog.Logger) {
globalProfiler = New(logger, IsProfilingEnabled())
}
// ProfileFunc profiles a function using the global profiler
func ProfileFunc(ctx context.Context, operation string, fn func() error) (*Profile, error) {
if globalProfiler == nil {
return nil, fn()
}
return globalProfiler.ProfileFunc(ctx, operation, fn)
}
// ProfileFuncWithMetrics profiles a function with metrics using the global profiler
func ProfileFuncWithMetrics(ctx context.Context, operation string, fn func() (int, int64, error)) (*Profile, error) {
if globalProfiler == nil {
_, _, err := fn()
return nil, err
}
return globalProfiler.ProfileFuncWithMetrics(ctx, operation, fn)
}
// Start begins timing using the global profiler
func Start(ctx context.Context, operation string) func(int, int64) *Profile {
if globalProfiler == nil {
return func(int, int64) *Profile { return nil }
}
return globalProfiler.Start(ctx, operation)
}