Example #1
0
func (s *WorkerTestSuite) SetUpSuite(t *C) {
	s.dsn = os.Getenv("PCT_TEST_MYSQL_DSN")
	s.logChan = make(chan *proto.LogEntry, 100)
	s.logger = pct.NewLogger(s.logChan, "qan-worker")
	s.now = time.Now()
	s.mysqlInstance = proto.ServiceInstance{Service: "mysql", InstanceId: 1}
	s.config = qan.Config{
		ServiceInstance: s.mysqlInstance,
		Start: []mysql.Query{
			mysql.Query{Set: "SET GLOBAL slow_query_log=OFF"},
			mysql.Query{Set: "SET GLOBAL long_query_time=0.123"},
			mysql.Query{Set: "SET GLOBAL slow_query_log=ON"},
		},
		Stop: []mysql.Query{
			mysql.Query{Set: "SET GLOBAL slow_query_log=OFF"},
			mysql.Query{Set: "SET GLOBAL long_query_time=10"},
		},
		Interval:          60,         // 1 min
		MaxSlowLogSize:    1073741824, // 1 GiB
		RemoveOldSlowLogs: true,
		ExampleQueries:    true,
		WorkerRunTime:     60, // 1 min
		CollectFrom:       "slowlog",
	}
	s.nullmysql = mock.NewNullMySQL()
}
func (i *InstallerTestSuite) TestIsSupportedMySQLVersion(t *C) {
	var got bool
	var err error

	agentConfig := &agent.Config{}
	flags := installer.Flags{}

	apiConnector := pct.NewAPI()
	api := api.New(apiConnector, false)
	logChan := make(chan *proto.LogEntry, 100)
	logger := pct.NewLogger(logChan, "instance-repo")
	instanceRepo := instance.NewRepo(logger, pct.Basedir.Dir("config"), apiConnector)
	terminal := term.NewTerminal(os.Stdin, false, true)
	inst := installer.NewInstaller(terminal, "", api, instanceRepo, agentConfig, flags)
	conn := mock.NewNullMySQL()
	errSomethingWentWrong := fmt.Errorf("Something went wrong")

	conn.SetAtLeastVersion(false, errSomethingWentWrong)
	got, err = inst.IsVersionSupported(conn)
	t.Assert(conn.Version, Equals, agent.MIN_SUPPORTED_MYSQL_VERSION)
	t.Assert(err, Equals, errSomethingWentWrong)
	t.Assert(got, Equals, false)

	conn.SetAtLeastVersion(true, nil)
	got, err = inst.IsVersionSupported(conn)
	t.Assert(conn.Version, Equals, agent.MIN_SUPPORTED_MYSQL_VERSION)
	t.Assert(err, IsNil)
	t.Assert(got, Equals, true)

	conn.Close()
}
Example #3
0
func (s *WorkerTestSuite) TestWorkerSlow001Half(t *C) {
	// This tests that the worker will stop processing events before
	// the end of the slow log file.  358 is the last byte of the first
	// (of 2) events.
	i := &qan.Interval{
		Number:      1,
		StartTime:   s.now,
		StopTime:    s.now.Add(1 * time.Minute),
		Filename:    inputDir + "slow001.log",
		StartOffset: 0,
		EndOffset:   358,
	}
	got, err := s.RunWorker(s.config, mock.NewNullMySQL(), i)
	t.Check(err, IsNil)
	expect := &qan.Result{}
	if err := test.LoadMmReport(outputDir+"slow001-half.json", expect); err != nil {
		t.Fatal(err)
	}
	sort.Sort(ByQueryId(got.Class))
	sort.Sort(ByQueryId(expect.Class))
	if ok, diff := IsDeeply(got, expect); !ok {
		Dump(got)
		t.Error(diff)
	}
}
Example #4
0
func (s *TestSuite) TestStartStop(t *C) {
	mockConn := mock.NewNullMySQL()
	mockConnFactory := &mock.ConnectionFactory{
		Conn: mockConn,
	}
	m := monitor.NewMonitor(s.logger, mockConnFactory)
	dsn := "fake:dsn@tcp(127.0.0.1:3306)/?parseTime=true"

	/**
	 * Register new subscriber
	 */
	// Set initial uptime
	mockConn.SetUptime(10)
	t.Assert(mockConn.GetUptimeCount(), Equals, uint(0))
	subChan, err := m.Add(dsn)
	t.Assert(err, IsNil)
	t.Assert(mockConn.GetUptimeCount(), Equals, uint(1), Commentf("MRMS didn't checked uptime after adding first subscriber"))

	/**
	 * Start MRMS
	 */
	interval := 1 * time.Second
	err = m.Start(interval)
	t.Assert(err, IsNil)

	// Imitate MySQL restart by setting uptime to 5s (previously 10s)
	mockConn.SetUptime(5)

	// After max 1 second it should notify subscriber about MySQL restart
	var notified bool
	select {
	case notified = <-subChan:
	case <-time.After(1 * time.Second):
	}
	t.Assert(notified, Equals, true, Commentf("MySQL was restarted but MRMS didn't notify subscribers"))

	/**
	 * Stop MRMS
	 */
	err = m.Stop()
	t.Assert(err, IsNil)

	// Check status
	status := m.Status()
	t.Assert(status, DeepEquals, map[string]string{
		monitor.MONITOR_NAME: "Stopped",
	})

	// Imitate MySQL restart by setting uptime to 1s (previously 5s)
	mockConn.SetUptime(1)

	// After stopping service it should not notify subscribers anymore
	time.Sleep(2 * time.Second)
	select {
	case notified = <-subChan:
	default:
	}
	t.Assert(notified, Equals, true, Commentf("MRMS notified subscribers after being stopped"))
}
Example #5
0
func (s *ManagerTestSuite) SetUpSuite(t *C) {
	s.dsn = os.Getenv("PCT_TEST_MYSQL_DSN")
	if s.dsn == "" {
		t.Fatal("PCT_TEST_MYSQL_DSN is not set")
	}
	s.realmysql = mysql.NewConnection(s.dsn)
	if err := s.realmysql.Connect(1); err != nil {
		t.Fatal(err)
	}
	s.reset = []mysql.Query{
		mysql.Query{Set: "SET GLOBAL slow_query_log=OFF"},
		mysql.Query{Set: "SET GLOBAL long_query_time=10"},
	}

	s.nullmysql = mock.NewNullMySQL()

	s.logChan = make(chan *proto.LogEntry, 1000)
	s.logger = pct.NewLogger(s.logChan, "qan-test")

	s.intervalChan = make(chan *qan.Interval, 1)
	s.iter = mock.NewMockIntervalIter(s.intervalChan)
	s.iterFactory = &mock.IntervalIterFactory{
		Iters:     []qan.IntervalIter{s.iter},
		TickChans: make(map[qan.IntervalIter]chan time.Time),
	}

	s.dataChan = make(chan interface{}, 2)
	s.spool = mock.NewSpooler(s.dataChan)
	s.workerFactory = &qan.SlowLogWorkerFactory{}

	var err error
	s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test")
	t.Assert(err, IsNil)

	if err := pct.Basedir.Init(s.tmpDir); err != nil {
		t.Fatal(err)
	}
	s.configDir = pct.Basedir.Dir("config")

	s.im = instance.NewRepo(pct.NewLogger(s.logChan, "im-test"), s.configDir, s.api)
	data, err := json.Marshal(&proto.MySQLInstance{
		Hostname: "db1",
		DSN:      s.dsn,
	})
	t.Assert(err, IsNil)
	s.im.Add("mysql", 1, data, false)
	s.mysqlInstance = proto.ServiceInstance{Service: "mysql", InstanceId: 1}

	links := map[string]string{
		"agent":     "http://localhost/agent",
		"instances": "http://localhost/instances",
	}
	s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links)
}
Example #6
0
func (s *TestSuite) TestGlobalSubscribe(t *C) {
	mockConn := mock.NewNullMySQL()
	mockConnFactory := &mock.ConnectionFactory{
		Conn: mockConn,
	}
	m := monitor.NewMonitor(s.logger, mockConnFactory)
	dsn := "fake:dsn@tcp(127.0.0.1:3306)/?parseTime=true"
	subChan, err := m.Add(dsn)
	t.Assert(err, IsNil)
	t.Assert(subChan, NotNil)

	gc, err := m.GlobalSubscribe()
	t.Assert(err, IsNil)
	t.Assert(gc, NotNil)
}
Example #7
0
func (s *TestSuite) Test2Subscribers(t *C) {
	mockConn := mock.NewNullMySQL()
	mockConnFactory := &mock.ConnectionFactory{
		Conn: mockConn,
	}
	m := monitor.NewMonitor(s.logger, mockConnFactory)
	dsn := "fake:dsn@tcp(127.0.0.1:3306)/?parseTime=true"

	c1, err := m.Add(dsn)
	t.Assert(err, IsNil)

	c2, err := m.Add(dsn)
	t.Assert(err, IsNil)

	var notified bool

	mockConn.SetUptime(1)
	m.Check()
	select {
	case notified = <-c1:
	default:
	}
	t.Check(notified, Equals, false)
	select {
	case notified = <-c2:
	default:
	}
	t.Check(notified, Equals, false)

	mockConn.SetUptime(2)
	m.Check()
	select {
	case notified = <-c1:
	default:
	}
	t.Check(notified, Equals, false)
	select {
	case notified = <-c2:
	default:
	}
	t.Check(notified, Equals, false)
}
Example #8
0
func (s *WorkerTestSuite) TestWorkerSlow001(t *C) {
	i := &qan.Interval{
		Number:      1,
		StartTime:   s.now,
		StopTime:    s.now.Add(1 * time.Minute),
		Filename:    inputDir + "slow001.log",
		StartOffset: 0,
		EndOffset:   524,
	}
	got, err := s.RunWorker(s.config, mock.NewNullMySQL(), i)
	t.Check(err, IsNil)
	expect := &qan.Result{}
	test.LoadMmReport(outputDir+"slow001.json", expect)
	sort.Sort(ByQueryId(got.Class))
	sort.Sort(ByQueryId(expect.Class))
	if ok, diff := IsDeeply(got, expect); !ok {
		Dump(got)
		t.Error(diff)
	}
}
Example #9
0
func (s *AnalyzerTestSuite) SetUpSuite(t *C) {
	s.nullmysql = mock.NewNullMySQL()

	s.logChan = make(chan *proto.LogEntry, 1000)
	s.logger = pct.NewLogger(s.logChan, "qan-test")

	s.intervalChan = make(chan *qan.Interval, 1)

	s.iter = mock.NewIter(s.intervalChan)

	s.dataChan = make(chan interface{}, 1)
	s.spool = mock.NewSpooler(s.dataChan)

	var err error
	s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test")
	t.Assert(err, IsNil)

	if err := pct.Basedir.Init(s.tmpDir); err != nil {
		t.Fatal(err)
	}
	s.configDir = pct.Basedir.Dir("config")

	s.im = instance.NewRepo(pct.NewLogger(s.logChan, "im-test"), s.configDir, s.api)
	data, err := json.Marshal(&proto.MySQLInstance{
		Hostname: "bm-cloud-db01",
		Alias:    "db01",
		DSN:      "user:pass@tcp/",
	})
	t.Assert(err, IsNil)
	s.im.Add("mysql", 1, data, false)
	s.mysqlInstance = proto.ServiceInstance{Service: "mysql", InstanceId: 1}

	links := map[string]string{
		"agent":     "http://localhost/agent",
		"instances": "http://localhost/instances",
	}
	s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links)

	s.restartChan = make(chan bool, 1)
}
Example #10
0
func (s *ReportTestSuite) TestResult014(t *C) {
	si := proto.ServiceInstance{Service: "mysql", InstanceId: 1}
	config := qan.Config{
		ServiceInstance: si,
		CollectFrom:     "slowlog",
		Interval:        60,
		WorkerRunTime:   60,
		ReportLimit:     500,
		MaxSlowLogSize:  1024 * 1024 * 1000,
	}
	logChan := make(chan *proto.LogEntry, 1000)
	w := slowlog.NewWorker(pct.NewLogger(logChan, "w"), config, mock.NewNullMySQL())
	i := &qan.Interval{
		Filename:    inputDir + "slow014.log",
		StartOffset: 0,
		EndOffset:   127118681,
	}
	w.Setup(i)
	result, err := w.Run()
	t.Assert(err, IsNil)
	w.Cleanup()

	start := time.Now().Add(-1 * time.Second)
	stop := time.Now()
	interval := &qan.Interval{
		Filename:    "slow.log",
		StartTime:   start,
		StopTime:    stop,
		StartOffset: 0,
		EndOffset:   127118680,
	}
	report := qan.MakeReport(config, interval, result)

	t.Check(report.Global.TotalQueries, Equals, uint64(4))
	t.Check(report.Global.UniqueQueries, Equals, uint64(4))
	t.Assert(report.Class, HasLen, 4)
	// This query required improving the log parser to get the correct checksum ID:
	t.Check(report.Class[0].Id, Equals, "DB9EF18846547B8C")
}
Example #11
0
func (s *WorkerTestSuite) TestWorkerSlow011(t *C) {
	// Percona Server rate limit
	i := &qan.Interval{
		Number:      1,
		StartTime:   s.now,
		StopTime:    s.now.Add(1 * time.Minute),
		Filename:    inputDir + "slow011.log",
		StartOffset: 0,
		EndOffset:   3000,
	}
	got, err := s.RunWorker(s.config, mock.NewNullMySQL(), i)
	t.Check(err, IsNil)
	expect := &qan.Result{}
	if err := test.LoadMmReport(outputDir+"slow011.json", expect); err != nil {
		t.Fatal(err)
	}
	sort.Sort(ByQueryId(got.Class))
	sort.Sort(ByQueryId(expect.Class))
	if same, diff := IsDeeply(got, expect); !same {
		Dump(got)
		t.Error(diff)
	}
}
Example #12
0
func (s *WorkerTestSuite) TestWorkerSlow001Resume(t *C) {
	// This tests that the worker will resume processing events from
	// somewhere in the slow log file.  359 is the first byte of the
	// second (of 2) events.
	i := &qan.Interval{
		Number:      2,
		StartTime:   s.now,
		StopTime:    s.now.Add(1 * time.Minute),
		Filename:    inputDir + "slow001.log",
		StartOffset: 359,
		EndOffset:   524,
	}
	got, err := s.RunWorker(s.config, mock.NewNullMySQL(), i)
	t.Check(err, IsNil)
	expect := &qan.Result{}
	test.LoadMmReport(outputDir+"slow001-resume.json", expect)
	sort.Sort(ByQueryId(got.Class))
	sort.Sort(ByQueryId(expect.Class))
	if ok, diff := IsDeeply(got, expect); !ok {
		Dump(got)
		t.Error(diff)
	}
}
Example #13
0
func (s *WorkerTestSuite) TestWorkerSlow001NoExamples(t *C) {
	i := &qan.Interval{
		Number:      99,
		StartTime:   s.now,
		StopTime:    s.now.Add(1 * time.Minute),
		Filename:    inputDir + "slow001.log",
		StartOffset: 0,
		EndOffset:   524,
	}
	config := s.config
	config.ExampleQueries = false
	got, err := s.RunWorker(config, mock.NewNullMySQL(), i)
	t.Check(err, IsNil)
	expect := &qan.Result{}
	if err := test.LoadMmReport(outputDir+"slow001-no-examples.json", expect); err != nil {
		t.Fatal(err)
	}
	sort.Sort(ByQueryId(got.Class))
	sort.Sort(ByQueryId(expect.Class))
	if same, diff := IsDeeply(got, expect); !same {
		Dump(got)
		t.Error(diff)
	}
}
func (s *WorkerTestSuite) SetUpSuite(t *C) {
	s.dsn = os.Getenv("PCT_TEST_MYSQL_DSN")
	s.logChan = make(chan *proto.LogEntry, 100)
	s.logger = pct.NewLogger(s.logChan, "qan-worker")
	s.nullmysql = mock.NewNullMySQL()
}
Example #15
0
func (s *TestSuite) SetUpSuite(t *C) {
	s.nullmysql = mock.NewNullMySQL()
	s.logChan = make(chan *proto.LogEntry, 1000)
	s.logger = pct.NewLogger(s.logChan, "mrms-monitor-test")
}
Example #16
0
func (s *TestSuite) TestNotifications(t *C) {
	mockConn := mock.NewNullMySQL()
	mockConnFactory := &mock.ConnectionFactory{
		Conn: mockConn,
	}
	m := monitor.NewMonitor(s.logger, mockConnFactory)
	dsn := "fake:dsn@tcp(127.0.0.1:3306)/?parseTime=true"

	/**
	 * Register new subscriber
	 */
	// Set initial uptime
	mockConn.SetUptime(10)
	subChan, err := m.Add(dsn)
	t.Assert(err, IsNil)

	/**
	 * MRMS should not send notification after first check for given dsn
	 */
	var notified bool
	select {
	case notified = <-subChan:
	default:
	}
	t.Assert(notified, Equals, false, Commentf("MySQL was not restarted (first check of MySQL server), but MRMS notified subscribers"))

	/**
	 * If MySQL was restarted then MRMS should notify subscriber
	 */
	// Imitate MySQL restart by returning 0s uptime (previously 10s)
	mockConn.SetUptime(0)
	m.Check()
	notified = false
	select {
	case notified = <-subChan:
	default:
	}
	t.Assert(notified, Equals, true, Commentf("MySQL was restarted, but MRMS didn't notify subscribers"))

	/**
	 * If MySQL was not restarted then MRMS should not notify subscriber
	 */
	// 2s uptime is higher than previous 0s, this indicates MySQL was not restarted
	mockConn.SetUptime(2)
	m.Check()
	notified = false
	select {
	case notified = <-subChan:
	default:
	}
	t.Assert(notified, Equals, false, Commentf("MySQL was not restarted, but MRMS notified subscribers"))

	/**
	 * Now let's imitate MySQL server restart and let's wait 3 seconds before next check.
	 * Since MySQL server was restarted and we waited 3s then uptime=3s
	 * which is higher than last registered uptime=2s
	 *
	 * However we expect in this test that this is properly detected as MySQL restart
	 * and the MRMS notifies subscribers
	 */
	waitTime := int64(3)
	time.Sleep(time.Duration(waitTime) * time.Second)
	mockConn.SetUptime(waitTime)
	m.Check()
	select {
	case notified = <-subChan:
	default:
	}
	t.Assert(notified, Equals, true, Commentf("MySQL was restarted (uptime overlaped last registered uptime), but MRMS didn't notify subscribers"))

	/**
	 * After removing subscriber MRMS should not notify it anymore about MySQL restarts
	 */
	// Imitate MySQL restart by returning 0s uptime (previously 3s)
	mockConn.SetUptime(0)
	m.Remove(dsn, subChan)
	m.Check()
	notified = false
	select {
	case notified = <-subChan:
	default:
	}
	t.Assert(notified, Equals, false, Commentf("Subscriber was removed but MRMS still notified it about MySQL restart"))
}