2019-05-22 21:16:55 +00:00
package main
import (
"flag"
2020-10-06 11:54:39 +00:00
"fmt"
2020-12-14 11:36:48 +00:00
"io"
2019-05-22 21:16:55 +00:00
"net/http"
2020-05-16 08:59:30 +00:00
"os"
2020-12-14 11:36:48 +00:00
"path"
2019-05-22 21:16:55 +00:00
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vminsert"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmselect"
2020-12-14 11:08:22 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmselect/promql"
2019-05-22 21:16:55 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/buildinfo"
2020-02-10 11:26:18 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/envflag"
2019-11-12 14:18:09 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fs"
2019-05-22 21:16:55 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/procutil"
2020-11-25 20:59:13 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape"
2020-02-10 11:03:52 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/storage"
2019-05-22 21:16:55 +00:00
)
2020-02-10 11:03:52 +00:00
var (
httpListenAddr = flag . String ( "httpListenAddr" , ":8428" , "TCP address to listen for http connections" )
minScrapeInterval = flag . Duration ( "dedup.minScrapeInterval" , 0 , "Remove superflouos samples from time series if they are located closer to each other than this duration. " +
"This may be useful for reducing overhead when multiple identically configured Prometheus instances write data to the same VictoriaMetrics. " +
"Deduplication is disabled if the -dedup.minScrapeInterval is 0" )
2020-11-25 20:59:13 +00:00
dryRun = flag . Bool ( "dryRun" , false , "Whether to check only -promscrape.config and then exit. " +
"Unknown config entries are allowed in -promscrape.config by default. This can be changed with -promscrape.config.strictParse" )
2020-02-10 11:03:52 +00:00
)
2019-05-22 21:16:55 +00:00
func main ( ) {
2020-05-16 08:59:30 +00:00
// Write flags and help message to stdout, since it is easier to grep or pipe.
flag . CommandLine . SetOutput ( os . Stdout )
2020-02-10 11:26:18 +00:00
envflag . Parse ( )
2019-05-22 21:16:55 +00:00
buildinfo . Init ( )
logger . Init ( )
2020-11-25 20:59:13 +00:00
if promscrape . IsDryRun ( ) {
* dryRun = true
}
if * dryRun {
if err := promscrape . CheckConfig ( ) ; err != nil {
logger . Fatalf ( "error when checking -promscrape.config: %s" , err )
}
logger . Infof ( "-promscrape.config is ok; exitting with 0 status code" )
return
}
2019-12-19 12:32:08 +00:00
logger . Infof ( "starting VictoriaMetrics at %q..." , * httpListenAddr )
2019-05-22 21:16:55 +00:00
startTime := time . Now ( )
2020-02-10 11:03:52 +00:00
storage . SetMinScrapeIntervalForDeduplication ( * minScrapeInterval )
2020-12-14 11:08:22 +00:00
vmstorage . Init ( promql . ResetRollupResultCacheIfNeeded )
2019-05-22 21:16:55 +00:00
vmselect . Init ( )
vminsert . Init ( )
2020-01-25 17:19:23 +00:00
startSelfScraper ( )
2019-05-22 21:16:55 +00:00
go httpserver . Serve ( * httpListenAddr , requestHandler )
2020-01-22 16:27:44 +00:00
logger . Infof ( "started VictoriaMetrics in %.3f seconds" , time . Since ( startTime ) . Seconds ( ) )
2019-05-22 21:16:55 +00:00
sig := procutil . WaitForSigterm ( )
logger . Infof ( "received signal %s" , sig )
2020-01-25 17:19:23 +00:00
stopSelfScraper ( )
2019-05-22 21:16:55 +00:00
logger . Infof ( "gracefully shutting down webservice at %q" , * httpListenAddr )
startTime = time . Now ( )
if err := httpserver . Stop ( * httpListenAddr ) ; err != nil {
logger . Fatalf ( "cannot stop the webservice: %s" , err )
}
vminsert . Stop ( )
2020-01-22 16:27:44 +00:00
logger . Infof ( "successfully shut down the webservice in %.3f seconds" , time . Since ( startTime ) . Seconds ( ) )
2019-05-22 21:16:55 +00:00
vmstorage . Stop ( )
vmselect . Stop ( )
2019-11-12 14:18:09 +00:00
fs . MustStopDirRemover ( )
2020-01-22 16:27:44 +00:00
logger . Infof ( "the VictoriaMetrics has been stopped in %.3f seconds" , time . Since ( startTime ) . Seconds ( ) )
2019-05-22 21:16:55 +00:00
}
func requestHandler ( w http . ResponseWriter , r * http . Request ) bool {
2020-12-14 11:36:48 +00:00
if r . URL . Path == "/" {
fmt . Fprintf ( w , "<h2>Single-node VictoriaMetrics.</h2></br>" )
fmt . Fprintf ( w , "See docs at <a href='https://victoriametrics.github.io/'>https://victoriametrics.github.io/</a></br>" )
2020-12-14 12:07:58 +00:00
fmt . Fprintf ( w , "Useful endpoints: </br>" )
2020-12-14 11:36:48 +00:00
writeAPIHelp ( w , [ ] [ ] string {
{ "/targets" , "discovered targets list" } ,
{ "/api/v1/targets" , "advanced information about discovered targets in JSON format" } ,
{ "/metrics" , "available service metrics" } ,
{ "/api/v1/status/tsdb" , "tsdb status page" } ,
} )
2020-10-06 11:54:39 +00:00
return true
}
2019-05-22 21:16:55 +00:00
if vminsert . RequestHandler ( w , r ) {
return true
}
if vmselect . RequestHandler ( w , r ) {
return true
}
if vmstorage . RequestHandler ( w , r ) {
return true
}
return false
}
2020-12-14 11:36:48 +00:00
func writeAPIHelp ( w io . Writer , pathList [ ] [ ] string ) {
pathPrefix := httpserver . GetPathPrefix ( )
for _ , p := range pathList {
p , doc := p [ 0 ] , p [ 1 ]
p = path . Join ( pathPrefix , p )
fmt . Fprintf ( w , "<a href='%s'>%q</a> - %s<br/>" , p , p , doc )
}
}