github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/worker/status.go (about) 1 // Copyright 2019 PingCAP, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package worker 15 16 import ( 17 "encoding/json" 18 "sort" 19 20 "github.com/gogo/protobuf/jsonpb" 21 "github.com/pingcap/tiflow/dm/common" 22 "github.com/pingcap/tiflow/dm/pb" 23 "github.com/pingcap/tiflow/dm/pkg/binlog" 24 "go.uber.org/zap" 25 ) 26 27 // Status returns the status of the current sub task. 28 func (st *SubTask) Status() interface{} { 29 if cu := st.CurrUnit(); cu != nil { 30 return cu.Status(nil) 31 } 32 return nil 33 } 34 35 // StatusJSON returns the status of the current sub task as json string. 36 func (st *SubTask) StatusJSON() string { 37 status := st.Status() 38 sj, err := json.Marshal(status) 39 if err != nil { 40 st.l.Error("fail to marshal status", zap.Reflect("status", status), zap.Error(err)) 41 return "" 42 } 43 return string(sj) 44 } 45 46 // Status returns the status of the worker (and sub tasks) 47 // if stName is empty, all sub task's status will be returned. 48 func (w *SourceWorker) Status(stName string, sourceStatus *binlog.SourceStatus) []*pb.SubTaskStatus { 49 sts := w.subTaskHolder.getAllSubTasks() 50 51 if len(sts) == 0 { 52 return nil // no sub task started 53 } 54 55 status := make([]*pb.SubTaskStatus, 0, len(sts)) 56 57 // return status order by name 58 names := make([]string, 0, len(sts)) 59 if len(stName) > 0 { 60 names = append(names, stName) 61 } else { 62 for name := range sts { 63 names = append(names, name) 64 } 65 } 66 sort.Strings(names) 67 68 for _, name := range names { 69 st, ok := sts[name] 70 var stStatus pb.SubTaskStatus 71 if !ok { 72 stStatus = pb.SubTaskStatus{ 73 Name: name, 74 Status: &pb.SubTaskStatus_Msg{Msg: common.NoSubTaskMsg(name)}, 75 } 76 } else { 77 lockID := "" 78 op := st.ShardDDLOperation() 79 if op != nil { 80 lockID = op.ID 81 } 82 cu := st.CurrUnit() 83 84 stStatus = pb.SubTaskStatus{ 85 Name: name, 86 Stage: st.Stage(), 87 Result: st.Result(), 88 UnresolvedDDLLockID: lockID, 89 } 90 91 if cu != nil { 92 stStatus.Unit = cu.Type() 93 // oneof status 94 us := cu.Status(sourceStatus) 95 switch stStatus.Unit { 96 case pb.UnitType_Check: 97 stStatus.Status = &pb.SubTaskStatus_Check{Check: us.(*pb.CheckStatus)} 98 case pb.UnitType_Dump: 99 stStatus.Status = &pb.SubTaskStatus_Dump{Dump: us.(*pb.DumpStatus)} 100 case pb.UnitType_Load: 101 stStatus.Status = &pb.SubTaskStatus_Load{Load: us.(*pb.LoadStatus)} 102 case pb.UnitType_Sync: 103 stStatus.Status = &pb.SubTaskStatus_Sync{Sync: us.(*pb.SyncStatus)} 104 if v := st.getValidator(); v != nil { 105 stStatus.Validation = v.GetValidatorStatus() 106 } 107 } 108 } 109 } 110 status = append(status, &stStatus) 111 } 112 113 return status 114 } 115 116 // GetUnitAndSourceStatusJSON returns the status of the worker and its unit as json string. 117 // This function will also cause every unit to print its status to log. 118 func (w *SourceWorker) GetUnitAndSourceStatusJSON(stName string, sourceStatus *binlog.SourceStatus) string { 119 sl := &pb.SubTaskStatusList{Status: w.Status(stName, sourceStatus)} 120 mar := jsonpb.Marshaler{EmitDefaults: true, Indent: " "} 121 s, err := mar.MarshalToString(sl) 122 if err != nil { 123 w.l.Error("fail to marshal status", zap.Any("status", sl), zap.Error(err)) 124 return "" 125 } 126 return s 127 }