github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/logger/remote_hook.go (about) 1 // Copyright © 2022 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package logger 16 17 import ( 18 "bytes" 19 "encoding/json" 20 "fmt" 21 "net/http" 22 "net/url" 23 "os" 24 "sync" 25 26 "github.com/google/uuid" 27 "github.com/sirupsen/logrus" 28 corev1 "k8s.io/api/core/v1" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 ) 31 32 // RemoteLogHook to send logs via remote URL. 33 type RemoteLogHook struct { 34 sync.RWMutex 35 36 TaskName string 37 URL string 38 } 39 40 func NewRemoteLogHook(remoteURL, taskName string) (*RemoteLogHook, error) { 41 reqURL, err := url.Parse(remoteURL) 42 if err != nil { 43 return nil, err 44 } 45 46 return &RemoteLogHook{ 47 TaskName: taskName, 48 URL: reqURL.String(), 49 }, err 50 } 51 52 // #nosec 53 func httpSend(url string, method string, body []byte) error { 54 var resp *http.Response 55 56 var err error 57 switch method { 58 case http.MethodGet: 59 resp, err = http.Get(url) 60 case http.MethodPost: 61 resp, err = http.Post(url, "application/json", bytes.NewBuffer(body)) 62 } 63 64 if err != nil { 65 return fmt.Errorf("bad %s request to server : %w", method, err) 66 } 67 defer func() { 68 _ = resp.Body.Close() 69 }() 70 71 if resp.StatusCode != http.StatusOK { 72 return fmt.Errorf("bad status code from server: [%d] %s ", resp.StatusCode, resp.Status) 73 } 74 75 return nil 76 } 77 78 func (hook *RemoteLogHook) Fire(entry *logrus.Entry) error { 79 line, err := entry.String() 80 if err != nil { 81 _, _ = fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) 82 return err 83 } 84 85 t := "Info" 86 if entry.Level <= logrus.ErrorLevel { 87 t = "Error" 88 } 89 90 event := &corev1.Event{ 91 ObjectMeta: metav1.ObjectMeta{ 92 Name: uuid.New().String(), 93 }, 94 InvolvedObject: corev1.ObjectReference{ 95 Name: hook.TaskName, 96 }, 97 Message: line, 98 Type: t, 99 } 100 101 bytesData, _ := json.Marshal(event) 102 103 hook.Lock() 104 defer hook.Unlock() 105 106 return httpSend(hook.URL, http.MethodPost, bytesData) 107 } 108 109 func (hook *RemoteLogHook) Levels() []logrus.Level { 110 return []logrus.Level{ 111 logrus.PanicLevel, 112 logrus.FatalLevel, 113 logrus.ErrorLevel, 114 logrus.WarnLevel, 115 logrus.InfoLevel, 116 } 117 }