1/* 2 * Copyright 2019 gRPC authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//go:generate protoc -I ./orca_v1 --go_out=plugins=grpc:./orca_v1 ./orca_v1/orca.proto 18 19// Package orca implements Open Request Cost Aggregation. 20package orca 21 22import ( 23 "github.com/golang/protobuf/proto" 24 "google.golang.org/grpc/grpclog" 25 "google.golang.org/grpc/internal/balancerload" 26 orcapb "google.golang.org/grpc/internal/balancerload/orca/orca_v1" 27 "google.golang.org/grpc/metadata" 28) 29 30const mdKey = "X-Endpoint-Load-Metrics-Bin" 31 32// toBytes converts a orca load report into bytes. 33func toBytes(r *orcapb.LoadReport) []byte { 34 if r == nil { 35 return nil 36 } 37 38 b, err := proto.Marshal(r) 39 if err != nil { 40 grpclog.Warningf("orca: failed to marshal load report: %v", err) 41 return nil 42 } 43 return b 44} 45 46// ToMetadata converts a orca load report into grpc metadata. 47func ToMetadata(r *orcapb.LoadReport) metadata.MD { 48 b := toBytes(r) 49 if b == nil { 50 return nil 51 } 52 return metadata.Pairs(mdKey, string(b)) 53} 54 55// fromBytes reads load report bytes and converts it to orca. 56func fromBytes(b []byte) *orcapb.LoadReport { 57 ret := new(orcapb.LoadReport) 58 if err := proto.Unmarshal(b, ret); err != nil { 59 grpclog.Warningf("orca: failed to unmarshal load report: %v", err) 60 return nil 61 } 62 return ret 63} 64 65// FromMetadata reads load report from metadata and converts it to orca. 66// 67// It returns nil if report is not found in metadata. 68func FromMetadata(md metadata.MD) *orcapb.LoadReport { 69 vs := md.Get(mdKey) 70 if len(vs) == 0 { 71 return nil 72 } 73 return fromBytes([]byte(vs[0])) 74} 75 76type loadParser struct{} 77 78func (*loadParser) Parse(md metadata.MD) interface{} { 79 return FromMetadata(md) 80} 81 82func init() { 83 balancerload.SetParser(&loadParser{}) 84} 85