vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletmanager/vreplication/stats_test.go (about)

     1  /*
     2  Copyright 2019 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 vreplication
    18  
    19  import (
    20  	"bytes"
    21  	"html/template"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/stretchr/testify/require"
    27  
    28  	"vitess.io/vitess/go/mysql"
    29  	"vitess.io/vitess/go/vt/binlog/binlogplayer"
    30  	"vitess.io/vitess/go/vt/proto/binlogdata"
    31  )
    32  
    33  var wantOut = `
    34  VReplication state: Open</br>
    35  <table>
    36    <tr>
    37      <th>Index</th>
    38      <th>Source</th>
    39      <th>Source Tablet</th>
    40      <th>State</th>
    41      <th>Stop Position</th>
    42      <th>Last Position</th>
    43      <th>VReplication Lag</th>
    44      <th>Counts</th>
    45      <th>Rates</th>
    46      <th>Last Message</th>
    47    </tr>
    48    <tr>
    49        <td>1</td>
    50        <td>keyspace:&#34;ks&#34; shard:&#34;0&#34; </td>
    51        <td>src1</td>
    52        <td>Running</td>
    53        <td>MariaDB/1-2-4</td>
    54        <td>1-2-3</td>
    55        <td>2</td>
    56        <td><b>All</b>: 0<br></td>
    57        <td></td>
    58        <td>Test Message2<br>Test Message1<br></td>
    59      </tr><tr>
    60        <td>2</td>
    61        <td>keyspace:&#34;ks&#34; shard:&#34;1&#34; </td>
    62        <td>src2</td>
    63        <td>Stopped</td>
    64        <td>MariaDB/1-2-5</td>
    65        <td>1-2-3</td>
    66        <td>2</td>
    67        <td><b>All</b>: 0<br></td>
    68        <td></td>
    69        <td>Test Message2<br>Test Message1<br></td>
    70      </tr>
    71  </table>
    72  `
    73  
    74  func TestStatusHtml(t *testing.T) {
    75  	pos, err := mysql.DecodePosition("MariaDB/1-2-3")
    76  	if err != nil {
    77  		t.Fatal(err)
    78  	}
    79  
    80  	blpStats := binlogplayer.NewStats()
    81  	blpStats.SetLastPosition(pos)
    82  	blpStats.ReplicationLagSeconds.Set(2)
    83  	blpStats.History.Add(&binlogplayer.StatsHistoryRecord{Time: time.Now(), Message: "Test Message1"})
    84  	blpStats.History.Add(&binlogplayer.StatsHistoryRecord{Time: time.Now(), Message: "Test Message2"})
    85  
    86  	testStats := &vrStats{}
    87  	testStats.isOpen = true
    88  	testStats.controllers = map[int]*controller{
    89  		1: {
    90  			id: 1,
    91  			source: &binlogdata.BinlogSource{
    92  				Keyspace: "ks",
    93  				Shard:    "0",
    94  			},
    95  			stopPos:  "MariaDB/1-2-4",
    96  			blpStats: blpStats,
    97  			done:     make(chan struct{}),
    98  		},
    99  		2: {
   100  			id: 2,
   101  			source: &binlogdata.BinlogSource{
   102  				Keyspace: "ks",
   103  				Shard:    "1",
   104  			},
   105  			stopPos:  "MariaDB/1-2-5",
   106  			blpStats: blpStats,
   107  			done:     make(chan struct{}),
   108  		},
   109  	}
   110  	testStats.controllers[1].sourceTablet.Set("src1")
   111  	testStats.controllers[2].sourceTablet.Set("src2")
   112  	close(testStats.controllers[2].done)
   113  
   114  	tpl := template.Must(template.New("test").Parse(vreplicationTemplate))
   115  	buf := bytes.NewBuffer(nil)
   116  	tpl.Execute(buf, testStats.status())
   117  	if strings.Contains(buf.String(), wantOut) {
   118  		t.Errorf("output: %v, want %v", buf, wantOut)
   119  	}
   120  }
   121  
   122  func TestVReplicationStats(t *testing.T) {
   123  	blpStats := binlogplayer.NewStats()
   124  
   125  	testStats := &vrStats{}
   126  	testStats.isOpen = true
   127  	testStats.controllers = map[int]*controller{
   128  		1: {
   129  			id: 1,
   130  			source: &binlogdata.BinlogSource{
   131  				Keyspace: "ks",
   132  				Shard:    "0",
   133  			},
   134  			blpStats: blpStats,
   135  			done:     make(chan struct{}),
   136  		},
   137  	}
   138  	testStats.controllers[1].sourceTablet.Set("src1")
   139  
   140  	sleepTime := 1 * time.Millisecond
   141  	record := func(phase string) {
   142  		defer blpStats.PhaseTimings.Record(phase, time.Now())
   143  		time.Sleep(sleepTime)
   144  	}
   145  	want := int64(1.2 * float64(sleepTime)) //allow 10% overhead for recording timing
   146  
   147  	record("fastforward")
   148  	require.Greater(t, want, testStats.status().Controllers[0].PhaseTimings["fastforward"])
   149  	record("catchup")
   150  	require.Greater(t, want, testStats.status().Controllers[0].PhaseTimings["catchup"])
   151  	record("copy")
   152  	require.Greater(t, want, testStats.status().Controllers[0].PhaseTimings["copy"])
   153  
   154  	blpStats.QueryCount.Add("replicate", 11)
   155  	blpStats.QueryCount.Add("fastforward", 23)
   156  	require.Equal(t, int64(11), testStats.status().Controllers[0].QueryCounts["replicate"])
   157  	require.Equal(t, int64(23), testStats.status().Controllers[0].QueryCounts["fastforward"])
   158  
   159  	blpStats.CopyLoopCount.Add(100)
   160  	blpStats.CopyRowCount.Add(200)
   161  	require.Equal(t, int64(100), testStats.status().Controllers[0].CopyLoopCount)
   162  	require.Equal(t, int64(200), testStats.status().Controllers[0].CopyRowCount)
   163  
   164  	var tm int64 = 1234567890
   165  	blpStats.RecordHeartbeat(tm)
   166  	require.Equal(t, tm, blpStats.Heartbeat())
   167  }