Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(spanner): add new open census metrics for long-running sessions removal #8975

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

harshachinta
Copy link
Contributor

@harshachinta harshachinta commented Nov 4, 2023

[DO NOT MERGE]

This PR adds a new session pool metrics using open census.
cloud.google.com/go/spanner/num_long_running_sessions_removed - The number of long-running sessions removed from the session pool.

This num_long_running_sessions_removed metric will be emitted only when ActionOnInactiveTransaction is either WarnAndClose or Close. This is because in rest of the cases there will be no change to this value and will always be 0.

Wrote unit test for testing the new metric emitted.

Real time testing
Metric dashboard - (https://screenshot.googleplex.com/9YqA4bmHoDGwsbo)
image

Used the below sample code to test the metric

package main

import (
	"context"
	"fmt"
	"log"
	"regexp"
	"time"

	"cloud.google.com/go/spanner"
	"google.golang.org/api/iterator"

	"contrib.go.opencensus.io/exporter/stackdriver"
)

var validDatabasePattern = regexp.MustCompile("^projects/(?P<project>[^/]+)/instances/(?P<instance>[^/]+)/databases/(?P<database>[^/]+)$")
var db = "projects/span-cloud-testing/instances/harsha-test-gcloud/databases/database1"

func main() {
	projectID, _, _, err := parseDatabaseName(db)
	if err != nil {
		log.Fatalf("Failed: %v", err)
	}

	ctx := context.Background()
	client, err := spanner.NewClientWithConfig(ctx, db, spanner.ClientConfig{
		SessionPoolConfig: spanner.SessionPoolConfig{
			MinOpened:                 0,
			MaxOpened:                 1,
			HealthCheckInterval:       1 * time.Second,
			healthCheckSampleInterval: 1 * time.Second,
			InactiveTransactionRemovalOptions: spanner.InactiveTransactionRemovalOptions{
				actionOnInactiveTransaction: spanner.WarnAndClose, // Make default to Warn from NoAction later
				executionFrequency:          1 * time.Second,
				idleTimeThreshold:           1 * time.Second,
				usedSessionsRatioThreshold:  0.95,
			},
		},
	})
	if err != nil {
		log.Fatalf("Failed: %v", err)
	}
	defer client.Close()

	// Register OpenCensus views.
	/*if err := view.Register(spanner.NumLongRunningSessionsRemovedCountView); err != nil {
		log.Fatalf("Failed: %v", err)
	}*/
	if err := spanner.EnableStatViews(); err != nil {
		log.Fatalf("Failed: %v", err)
	}

	// Create OpenCensus Stackdriver exporter.
	sd, err := stackdriver.NewExporter(stackdriver.Options{
		ProjectID: projectID,
		//ReportingInterval: 8 * time.Second,
	})
	if err != nil {
		log.Fatalf("Failed: %v", err)
	}
	// It is imperative to invoke flush before your main function exits
	defer sd.Flush()

	// Start the metrics exporter
	sd.StartMetricsExporter()
	defer sd.StopMetricsExporter()

	stmt := spanner.Statement{SQL: `SELECT SingerId, FirstName, LastName FROM Singers`}
	iter := client.Single().Query(ctx, stmt)
	for {
		row, err := iter.Next()
		time.Sleep(10 * time.Second)
		if err == iterator.Done {
			break
		}
		if err != nil {
			log.Printf("No data: %v", err)
		}
		var singerID int64
		var firstName, lastName string
		if err := row.Columns(&singerID, &firstName, &lastName); err != nil {
			log.Printf("Error: %v", err)
		}
		log.Printf("%d %s %s\n", singerID, firstName, lastName)
	}
	iter.Stop()

	iter = client.Single().Query(ctx, stmt)
	iter.Next()
	time.Sleep(10 * time.Second)
	log.Println("Main completed")
}

func parseDatabaseName(databaseUri string) (project, instance, database string, err error) {
	matches := validDatabasePattern.FindStringSubmatch(databaseUri)
	if len(matches) == 0 {
		return "", "", "", fmt.Errorf("failed to parse database name from %q according to pattern %q",
			databaseUri, validDatabasePattern.String())
	}
	return matches[1], matches[2], matches[3], nil
}

@harshachinta harshachinta requested review from a team as code owners November 4, 2023 05:41
@product-auto-label product-auto-label bot added size: m Pull request size is medium. api: spanner Issues related to the Spanner API. labels Nov 4, 2023
@harshachinta harshachinta added the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Nov 7, 2023
@product-auto-label product-auto-label bot added the stale: old Pull request is old and needs attention. label Dec 4, 2023
@product-auto-label product-auto-label bot added stale: extraold Pull request is critically old and needs prioritization. and removed stale: old Pull request is old and needs attention. labels Jan 3, 2024
@codyoss
Copy link
Member

codyoss commented Jul 24, 2024

@harshachinta can we close or merge this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: spanner Issues related to the Spanner API. do not merge Indicates a pull request not ready for merge, due to either quality or timing. size: m Pull request size is medium. stale: extraold Pull request is critically old and needs prioritization.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants