vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/repltracker/poller.go (about) 1 /* 2 Copyright 2020 The Vitess 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 package repltracker 18 19 import ( 20 "sync" 21 "time" 22 23 "vitess.io/vitess/go/stats" 24 25 "vitess.io/vitess/go/vt/mysqlctl" 26 vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" 27 "vitess.io/vitess/go/vt/vterrors" 28 ) 29 30 var replicationLagSeconds = stats.NewGauge("replicationLagSec", "replication lag in seconds") 31 32 type poller struct { 33 mysqld mysqlctl.MysqlDaemon 34 35 mu sync.Mutex 36 lag time.Duration 37 timeRecorded time.Time 38 } 39 40 func (p *poller) InitDBConfig(mysqld mysqlctl.MysqlDaemon) { 41 p.mysqld = mysqld 42 } 43 44 func (p *poller) Status() (time.Duration, error) { 45 p.mu.Lock() 46 defer p.mu.Unlock() 47 48 status, err := p.mysqld.ReplicationStatus() 49 if err != nil { 50 return 0, err 51 } 52 53 // If replication is not currently running or we don't know what the lag is -- most commonly 54 // because the replica mysqld is in the process of trying to start replicating from its source 55 // but it hasn't yet reached the point where it can calculate the seconds_behind_master 56 // value and it's thus NULL -- then we will estimate the lag ourselves using the last seen 57 // value + the time elapsed since. 58 if !status.Healthy() || status.ReplicationLagUnknown { 59 if p.timeRecorded.IsZero() { 60 return 0, vterrors.Errorf(vtrpcpb.Code_UNAVAILABLE, "replication is not running") 61 } 62 return time.Since(p.timeRecorded) + p.lag, nil 63 } 64 65 p.lag = time.Duration(status.ReplicationLagSeconds) * time.Second 66 p.timeRecorded = time.Now() 67 replicationLagSeconds.Set(int64(p.lag.Seconds())) 68 return p.lag, nil 69 }