func (hw *HandlerWrapper) Metric(name string, value interface{}) {
	if hw.report == nil {
		hw.Log.Warn("Attempting to add metrics before function decorated with IOpipe. This metric will not be recorded.")
		return
	}
	if utf8.RuneCountInString(name) > 128 {
		hw.Log.Warn(fmt.Sprintf("Metric of name %s is longer than allowed limit of 128 characters. This metric will not be recorded.", name))
		return
	}
	s := coerceString(value)
	if s != nil {
		if !strings.HasPrefix(name, "@iopipe") {
			hw.Label("@iopipe/metrics")
		}
		hw.report.CustomMetrics = append(hw.report.CustomMetrics, CustomMetric{Name: name, S: s})
	}
	n := coerceNumeric(value)
	if n != nil {
		if !strings.HasPrefix(name, "@iopipe") {
			hw.Label("@iopipe/metrics")
		}
		hw.report.CustomMetrics = append(hw.report.CustomMetrics, CustomMetric{Name: name, N: n})
	}
}
Metric adds a custom metric to the report
package iopipe
import (
	"context"
	"fmt"
	"strings"
	"sync"
	"time"
	"unicode/utf8"
	"github.com/aws/aws-lambda-go/lambdacontext"
	log "github.com/sirupsen/logrus"
)
type HandlerWrapper struct {
	agent           *Agent
	deadline        time.Time
	lambdaContext   *lambdacontext.LambdaContext
	originalHandler interface{}
	report          *Report
	wrappedHandler  lambdaHandler
	Log *log.Logger
}
func NewHandlerWrapper(handler interface{}, agent *Agent) *HandlerWrapper {
	return &HandlerWrapper{
		agent:           agent,
		originalHandler: handler,
		wrappedHandler:  newHandler(handler),
		Log:             agent.log,
	}
}
func (hw *HandlerWrapper) Invoke(ctx context.Context, payload interface{}) (response interface{}, err error) {
	lc, _ := lambdacontext.FromContext(ctx)
	hw.lambdaContext = lc
	cw := NewContextWrapper(lc, hw)
	ctx = NewContext(ctx, cw)
	hw.deadline, _ = ctx.Deadline()
	hw.report = NewReport(hw)
	hw.preInvoke(ctx, payload)
	defer func() {
		if panicErr := recover(); panicErr != nil {
			hw.Label("@iopipe/error")
			hw.report.prepare(NewPanicInvocationError(panicErr))
			hw.report.send()
			panic(panicErr)
		}
	}()
	go func() {
		if hw.deadline.IsZero() {
			hw.Log.Debug("Deadline is zero, disabling timeout handling")
			return
		}
		timeoutWindow := 0 * time.Millisecond
		if hw.agent != nil && hw.agent.TimeoutWindow != nil {
			timeoutWindow = *hw.agent.TimeoutWindow
		}
		timeoutDuration := hw.deadline.Add(-timeoutWindow)
		if time.Now().After(timeoutDuration) {
			hw.Log.Debug("Timeout deadline is in the past, disabling timeout handling")
			return
		}
		hw.Log.Debug("Setting function to timeout in ", time.Until(timeoutDuration).String())
		timeoutChannel := time.After(time.Until(timeoutDuration))
		select {
		case <-timeoutChannel:
			hw.Log.Debug("Function is about to timeout, sending report")
			hw.Label("@iopipe/timeout")
			hw.report.prepare(fmt.Errorf("Timeout Exceeded"))
			hw.report.send()
			return
		case <-ctx.Done():
			return
		}
	}()
	response, err = hw.wrappedHandler(ctx, payload)
	if coldStart {
		hw.Label("@iopipe/coldstart")
	}
	coldStart = false
	if err != nil {
		hw.Label("@iopipe/error")
	}
	hw.postInvoke(ctx, payload)
	if hw.report != nil {
		hw.report.prepare(err)
		hw.report.send()
	}
	return response, err
}
func (hw *HandlerWrapper) Error(err error) {
	if hw.report == nil {
		hw.Log.Warn("Attempting to add error before function decorated with IOpipe. This error will not be recorded.")
		return
	}
	hw.Label("@iopipe/error")
	hw.report.prepare(err)
	hw.report.send()
}
func (hw *HandlerWrapper) Label(name string) {
	if hw.report == nil {
		hw.Log.Warn("Attempting to add labels before function decorated with IOpipe. This metric will not be recorded.")
		return
	}
	if utf8.RuneCountInString(name) > 128 {
		hw.Log.Warn(fmt.Sprintf("Label name %s is longer than allowed limit of 128 characters. This label will not be recorded.", name))
		return
	}
	if _, ok := hw.report.labels[name]; !ok {
		hw.report.labels[name] = struct{}{}
	}
}