Source File
main.go
Belonging Package
golang.org/x/pkgsite/cmd/prober
BypassCache bool
}
var probes = []*Probe{
{
Name: "home",
RelativeURL: "",
},
{
Name: "search-help",
RelativeURL: "search-help",
},
{
Name: "license-policy",
RelativeURL: "license-policy",
},
{
Name: "pkg-firestore",
RelativeURL: "cloud.google.com/go/firestore",
},
{
Name: "pkg-firestore-nocache",
RelativeURL: "cloud.google.com/go/firestore",
BypassCache: true,
},
{
Name: "pkg-firestore-versions",
RelativeURL: "cloud.google.com/go/firestore?tab=versions",
},
{
Name: "pkg-firestore-versions-nocache",
RelativeURL: "cloud.google.com/go/firestore?tab=versions",
BypassCache: true,
},
{
Name: "pkg-firestore-imports",
RelativeURL: "cloud.google.com/go/firestore?tab=imports",
},
{
Name: "pkg-firestore-imports-nocache",
RelativeURL: "cloud.google.com/go/firestore?tab=imports",
BypassCache: true,
},
{
Name: "pkg-firestore-importedby",
RelativeURL: "cloud.google.com/go/firestore?tab=importedby",
},
{
Name: "pkg-firestore-importedby-nocache",
RelativeURL: "cloud.google.com/go/firestore?tab=importedby",
BypassCache: true,
},
{
Name: "pkg-firestore-licenses",
RelativeURL: "cloud.google.com/go/firestore?tab=licenses",
},
{
Name: "pkg-firestore-licenses-nocache",
RelativeURL: "cloud.google.com/go/firestore?tab=licenses",
BypassCache: true,
},
{
Name: "pkg-errors-importedby",
RelativeURL: "github.com/pkg/errors?tab=importedby",
},
{
Name: "pkg-errors-importedby-nocache",
RelativeURL: "github.com/pkg/errors?tab=importedby",
BypassCache: true,
},
{
Name: "pkg-hortonworks-versions",
RelativeURL: "github.com/hortonworks/cb-cli?tab=versions",
BypassCache: true,
},
{
Name: "pkg-xtoolsgo-directory",
RelativeURL: "golang.org/x/tools/go",
BypassCache: true,
},
{
Name: "xtools-nocache",
RelativeURL: "golang.org/x/tools",
BypassCache: true,
},
{
Name: "xtools-versions-nocache",
RelativeURL: "golang.org/x/tools?tab=versions",
BypassCache: true,
},
{
Name: "xtools-licenses-nocache",
RelativeURL: "golang.org/x/tools?tab=licenses",
BypassCache: true,
},
{
Name: "search-github",
RelativeURL: "search?q=github",
},
{
Name: "search-github-nocache",
RelativeURL: "search?q=github",
BypassCache: true,
},
}
:= map[string]bool{}
for , := range probes {
if [.Name] {
log.Fatalf(context.Background(), "duplicate probe name %q", .Name)
}
[.Name] = true
}
}
var (
baseURL string
authValue string
client *http.Client
metricExporter *stackdriver.Exporter
metricReader *metricexport.Reader
keyName = tag.MustNewKey("probe.name")
keyStatus = tag.MustNewKey("probe.status")
firstByteLatency = stats.Float64(
"go-discovery/first_byte_latency",
"Time between first byte of request headers sent to first byte of response received, or error",
stats.UnitMilliseconds,
)
firstByteLatencyDistribution = &view.View{
Name: "go-discovery/prober/first_byte_latency",
Measure: firstByteLatency,
Aggregation: ochttp.DefaultLatencyDistribution,
Description: "first-byte latency, by probe name and response status",
TagKeys: []tag.Key{keyName, keyStatus},
}
probeCount = &view.View{
Name: "go-discovery/prober/probe_count",
Measure: firstByteLatency,
Aggregation: view.Count(),
Description: "probe count, by probe name and response status",
TagKeys: []tag.Key{keyName, keyStatus},
}
)
func () {
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "usage: %s [flags]\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
:= context.Background()
baseURL = config.GetEnv("PROBER_BASE_URL", "")
if baseURL == "" {
log.Fatal(, "must set PROBER_BASE_URL")
}
log.Infof(, "base URL %s", baseURL)
authValue = config.GetEnv("GO_DISCOVERY_PROBER_AUTH_VALUE", "")
if authValue == "" {
log.Warningf(, "missing GO_DISCOVERY_PROBER_AUTH_VALUE; won't bypass cache or quota")
}
, := config.Init()
if != nil {
log.Fatal(, )
}
.Dump(os.Stderr)
log.SetLevel(.LogLevel)
if .OnGCP() {
if , := log.UseStackdriver(, , "prober-log"); != nil {
log.Fatal(, )
}
}
var []byte
if *credsFile != "" {
, = ioutil.ReadFile(*credsFile)
if != nil {
log.Fatal(, )
}
metricReader = metricexport.NewReader()
http.HandleFunc("/favicon.ico", func( http.ResponseWriter, *http.Request) {
http.ServeFile(, , "content/static/img/favicon.ico")
})
http.HandleFunc("/", handleProbe)
http.HandleFunc("/check", handleCheck)
:= .HostAddr("localhost:8080")
log.Infof(, "Listening on addr %s", )
log.Fatal(, http.ListenAndServe(, nil))
}
func ( http.ResponseWriter, *http.Request) {
:= runProbes(.Context())
var = struct {
time.Time
string
[]*ProbeStatus
}{
: time.Now(),
: baseURL,
: ,
}
var bytes.Buffer
:= statusTemplate.Execute(&, )
if != nil {
http.Error(, fmt.Sprintf("template execution failed: %v", ), http.StatusInternalServerError)
} else {
.WriteTo() // ignore error; nothing we can do about it
}
}
func ( http.ResponseWriter, *http.Request) {
:= runProbes(.Context())
var []*ProbeStatus
for , := range {
if .Code != http.StatusOK {
= append(, )
}
}
.Header().Set("Content-Type", "text/plain")
if len() == 0 {
fmt.Fprintf(, "All probes succeeded.\n")
} else {
.WriteHeader([0].Code)
fmt.Fprintf(, "SOME PROBES FAILED:\n")
for , := range {
fmt.Fprintf(, "%3d /%s\n", .Code, .Probe.RelativeURL)
}
}
}
func ( context.Context) []*ProbeStatus {
var []*ProbeStatus
for , := range probes {
:= runProbe(, )
= append(, )
}
metricReader.ReadAndExport(metricExporter)
metricExporter.Flush()
log.Info(, "metrics exported to StackDriver")
return
}
func ( context.Context, *Probe) *ProbeStatus {
:= &ProbeStatus{
Probe: ,
Code: 499, // not a real code; means request never sent
}
:= baseURL + "/" + .RelativeURL
log.Infof(, "running %s = %s", .Name, )
defer func() {
log.Infof(, "%s in %dms", .Text, .Latency)
}()
, := context.WithTimeout(context.Background(), 15*time.Second)
defer ()
, := http.NewRequest(http.MethodGet, , nil)
if authValue != "" {
if .BypassCache {
.Header.Set(config.BypassCacheAuthHeader, authValue)
}
.Header.Set(config.BypassQuotaAuthHeader, authValue)
}
if != nil {
.Text = fmt.Sprintf("FAILED making request: %v", )
return
}
:= time.Now()
, := client.Do(.WithContext())
:= float64(time.Since()) / float64(time.Millisecond)
.Latency = int()
:= func( string) {
stats.RecordWithTags(, []tag.Mutator{
tag.Upsert(keyName, .Name),
tag.Upsert(keyStatus, ),
}, firstByteLatency.M())
}
if != nil {
.Text = fmt.Sprintf("FAILED call: %v", )
("FAILED call")
return
}
defer .Body.Close()
.Code = .StatusCode
if .StatusCode != http.StatusOK {
.Text = fmt.Sprintf("FAILED with status %s", .Status)
(.Status)
return
}
, := ioutil.ReadAll(.Body)
if != nil {
.Text = fmt.Sprintf("FAILED reading body: %v", )
("FAILED read body")
return
}
if !bytes.Contains(, []byte("go.dev")) {
.Text = "FAILED: body does not contain 'go.dev'"
("FAILED wrong body")
return
}
.Text = "OK"
("200 OK")
return
}
var statusTemplate = template.Must(template.New("").Parse(`
<html>
<head>
<title>Go Discovery Prober</title>
</head>
<body>
<h1>Probes at at {{with .Start}}{{.Format "2006-1-2 15:04"}}{{end}}</h1>
Base URL: {{.BaseURL}}<br/>
<table cellspacing="10rem">
<tr><th>Name</th><th>URL</th><th>Latency (ms)</th><th>Status</th></tr>
{{range .Statuses}}
<tr>
<td>{{.Probe.Name}}</td>
<td>{{.Probe.RelativeURL}}</td>
<td>{{.Latency}}</td>
<td>{{.Text}}</td>
</tr>
{{end}}
</table>
</body>
</html>
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |