github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/runtime/health.go (about) 1 /* 2 * Copyright 2023 Wang Min Xiang 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 18 package runtime 19 20 import ( 21 "bytes" 22 "github.com/aacfactory/avro" 23 "github.com/aacfactory/fns/commons/bytex" 24 "github.com/aacfactory/fns/context" 25 "github.com/aacfactory/fns/transports" 26 "github.com/aacfactory/json" 27 "time" 28 ) 29 30 var ( 31 healthPath = bytex.FromString("/health") 32 ) 33 34 func CheckHealth(ctx context.Context, client transports.Client) (ok bool) { 35 status, header, body, _ := client.Do(ctx, transports.MethodGet, healthPath, nil, nil) 36 if status != 200 { 37 return 38 } 39 health := Health{} 40 if bytes.Equal(header.Get(transports.ContentTypeHeaderName), transports.ContentTypeAvroHeaderValue) { 41 decodeErr := avro.Unmarshal(body, &health) 42 if decodeErr != nil { 43 return 44 } 45 } else { 46 decodeErr := json.Unmarshal(body, &health) 47 if decodeErr != nil { 48 return 49 } 50 } 51 ok = health.Running 52 return 53 } 54 55 func HealthHandler() transports.MuxHandler { 56 return &healthHandler{ 57 launch: time.Now(), 58 } 59 } 60 61 type healthHandler struct { 62 launch time.Time 63 } 64 65 func (handler *healthHandler) Name() string { 66 return "health" 67 } 68 69 func (handler *healthHandler) Construct(_ transports.MuxHandlerOptions) error { 70 return nil 71 } 72 73 func (handler *healthHandler) Match(_ context.Context, method []byte, path []byte, _ transports.Header) bool { 74 ok := bytes.Equal(method, transports.MethodGet) && bytes.Equal(path, healthPath) 75 return ok 76 } 77 78 func (handler *healthHandler) Handle(w transports.ResponseWriter, r transports.Request) { 79 rt := Load(r) 80 running, serving := rt.Running() 81 w.Succeed(Health{ 82 Id: bytex.ToString(rt.AppId()), 83 Name: rt.AppName(), 84 Version: rt.AppVersion().String(), 85 Running: running, 86 Serving: serving, 87 Launch: handler.launch, 88 Now: time.Now(), 89 }) 90 return 91 } 92 93 type Health struct { 94 Id string `json:"id" avro:"id"` 95 Name string `json:"name" avro:"name"` 96 Version string `json:"version" avro:"version"` 97 Running bool `json:"running" avro:"running"` 98 Serving bool `json:"serving" avro:"serving"` 99 Launch time.Time `json:"launch" avro:"launch"` 100 Now time.Time `json:"now" avro:"now"` 101 }