func (s *Adapter) HandleMetric(ctx context.Context, r *metric.HandleMetricRequest) (*v1beta1.ReportResult, error) {
	for _, inst := range r.Instances {
		dimensions := decodeValueMap(inst.Dimensions)
		apiKey := dimensions["api_key"].(string)
		responseCode := dimensions["response_code"].(int64)
		authorized := responseCode != 403
		if !authorized {
			return &v1beta1.ReportResult{}, nil
		}
		requestTimestamp := decodeTimestamp(dimensions["request_timestamp"])
		requestMethod := dimensions["request_method"].(string)
		requestHost := dimensions["request_host"].(string)
		requestURL := dimensions["request_url"].(string)
		req := map[string]interface{}{
			"apiKey":           apiKey,
			"requestMethod":    requestMethod,
			"requestHost":      requestHost,
			"requestURL":       requestURL,
			"requestTimestamp": requestTimestamp,
		}
		ipAddr := dimensions["user_ip"]
		ipValue := ipAddr.(*policy.IPAddress).Value
		req["userIP"] = net.IP(ipValue).String()
		req["userAgent"] = dimensions["user_agent"].(string)
		responseTimestamp := decodeTimestamp(dimensions["response_timestamp"])
		req["responseTimestamp"] = responseTimestamp
		req["responseSize"] = dimensions["response_size"].(int64)
		req["responseCode"] = dimensions["response_code"].(int64)
		_, _, err := fsClient.Collection("requests").Add(ctx, req)
		if err != nil {
			log.Errorf("add request: %s", err)
			continue
		}
	}
	return &v1beta1.ReportResult{}, nil
}
HandleMetric records metric entries
package main
import (
	"context"
	"fmt"
	"net"
	"os"
	"time"
	"cloud.google.com/go/firestore"
	firebase "firebase.google.com/go"
	"google.golang.org/api/option"
	"google.golang.org/grpc"
	"istio.io/api/mixer/adapter/model/v1beta1"
	policy "istio.io/api/policy/v1beta1"
	"istio.io/istio/mixer/pkg/status"
	"istio.io/istio/mixer/template/authorization"
	"istio.io/istio/mixer/template/metric"
	"istio.io/pkg/log"
)
type (
	Server interface {
		Addr() string
		Close() error
		Run(shutdown chan error)
	}
	Adapter struct {
		listener net.Listener
		server   *grpc.Server
	}
)
var _ authorization.HandleAuthorizationServiceServer = &Adapter{}
var _ metric.HandleMetricServiceServer = &Adapter{}
var fsClient *firestore.Client
var ctx context.Context
func decodeValue(in interface{}) interface{} {
	switch t := in.(type) {
	case *policy.Value_StringValue:
		return t.StringValue
	case *policy.Value_Int64Value:
		return t.Int64Value
	case *policy.Value_DoubleValue:
		return t.DoubleValue
	case *policy.Value_IpAddressValue:
		return t.IpAddressValue
	case *policy.Value_TimestampValue:
		return t.TimestampValue
	default:
		return fmt.Sprintf("%v", in)
	}
}
func decodeValueMap(in map[string]*policy.Value) map[string]interface{} {
	out := make(map[string]interface{}, len(in))
	for k, v := range in {
		out[k] = decodeValue(v.GetValue())
	}
	return out
}
func decodeTimestamp(t interface{}) time.Time {
	if t == nil {
		return time.Time{}
	}
	tm := t.(*policy.TimeStamp)
	return time.Unix(tm.GetValue().Seconds, int64(tm.GetValue().Nanos))
}
func getUnixTimeStr(t time.Time) string {
	return fmt.Sprintf("%v", t.UnixNano())
}
func (s *Adapter) HandleAuthorization(ctx context.Context, r *authorization.HandleAuthorizationRequest) (*v1beta1.CheckResult, error) {
	props := decodeValueMap(r.Instance.Subject.Properties)
	apiKey := props["api_key"].(string)
	if apiKey == "" {
		return &v1beta1.CheckResult{
			Status: status.WithPermissionDenied("Unauthorized: API Key Missing"),
		}, nil
	}
	keyEntry, err := fsClient.Collection("keys").Doc(apiKey).Get(ctx)
	if err != nil {
		errMsg := fmt.Sprintf("Can't find key entry... %v", apiKey)
		return &v1beta1.CheckResult{
			Status: status.WithInvalidArgument(errMsg),
		}, nil
	}
	quotas := keyEntry.Data()["quotas"].(int64)
	if quotas <= 0 {
		return &v1beta1.CheckResult{
			Status: status.WithResourceExhausted("Quotas exhausted."),
		}, nil
	}
	return &v1beta1.CheckResult{
		Status: status.OK,
	}, nil
}