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  }