| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | package commands | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	_ "net/http/pprof" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/signal" | 
					
						
							|  |  |  | 	"runtime/debug" | 
					
						
							| 
									
										
										
										
											2022-11-23 00:53:43 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | 	"syscall" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-16 18:58:35 +08:00
										 |  |  | 	_ "github.com/grafana/pyroscope-go/godeltaprof/http/pprof" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-30 16:26:42 +08:00
										 |  |  | 	"github.com/urfave/cli/v2" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/api" | 
					
						
							| 
									
										
										
										
											2023-10-04 20:51:35 +08:00
										 |  |  | 	gcli "github.com/grafana/grafana/pkg/cmd/grafana-cli/commands" | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/log" | 
					
						
							| 
									
										
										
										
											2023-12-07 05:34:23 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/metrics" | 
					
						
							| 
									
										
										
										
											2021-09-13 23:46:47 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/process" | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/server" | 
					
						
							|  |  |  | 	_ "github.com/grafana/grafana/pkg/services/alerting/conditions" | 
					
						
							|  |  |  | 	_ "github.com/grafana/grafana/pkg/services/alerting/notifiers" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/setting" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type ServerOptions struct { | 
					
						
							| 
									
										
										
										
											2023-09-22 19:17:10 +08:00
										 |  |  | 	Version          string | 
					
						
							|  |  |  | 	Commit           string | 
					
						
							|  |  |  | 	EnterpriseCommit string | 
					
						
							|  |  |  | 	BuildBranch      string | 
					
						
							|  |  |  | 	BuildStamp       string | 
					
						
							|  |  |  | 	Context          *cli.Context | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-22 19:17:10 +08:00
										 |  |  | func ServerCommand(version, commit, enterpriseCommit, buildBranch, buildstamp string) *cli.Command { | 
					
						
							| 
									
										
										
										
											2022-12-25 11:33:18 +08:00
										 |  |  | 	return &cli.Command{ | 
					
						
							|  |  |  | 		Name:  "server", | 
					
						
							|  |  |  | 		Usage: "run the grafana server", | 
					
						
							| 
									
										
										
										
											2023-08-04 20:03:47 +08:00
										 |  |  | 		Flags: commonFlags, | 
					
						
							| 
									
										
										
										
											2022-12-25 11:33:18 +08:00
										 |  |  | 		Action: func(context *cli.Context) error { | 
					
						
							|  |  |  | 			return RunServer(ServerOptions{ | 
					
						
							| 
									
										
										
										
											2023-09-22 19:17:10 +08:00
										 |  |  | 				Version:          version, | 
					
						
							|  |  |  | 				Commit:           commit, | 
					
						
							|  |  |  | 				EnterpriseCommit: enterpriseCommit, | 
					
						
							|  |  |  | 				BuildBranch:      buildBranch, | 
					
						
							|  |  |  | 				BuildStamp:       buildstamp, | 
					
						
							|  |  |  | 				Context:          context, | 
					
						
							| 
									
										
										
										
											2022-12-25 11:33:18 +08:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2023-09-07 01:11:57 +08:00
										 |  |  | 		Subcommands: []*cli.Command{TargetCommand(version, commit, buildBranch, buildstamp)}, | 
					
						
							| 
									
										
										
										
											2022-12-25 11:33:18 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-04 20:03:47 +08:00
										 |  |  | func RunServer(opts ServerOptions) error { | 
					
						
							|  |  |  | 	if Version || VerboseVersion { | 
					
						
							| 
									
										
										
										
											2023-10-04 20:51:35 +08:00
										 |  |  | 		if opts.EnterpriseCommit != gcli.DefaultCommitValue && opts.EnterpriseCommit != "" { | 
					
						
							|  |  |  | 			fmt.Printf("Version %s (commit: %s, branch: %s, enterprise-commit: %s)\n", opts.Version, opts.Commit, opts.BuildBranch, opts.EnterpriseCommit) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			fmt.Printf("Version %s (commit: %s, branch: %s)\n", opts.Version, opts.Commit, opts.BuildBranch) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-08-04 20:03:47 +08:00
										 |  |  | 		if VerboseVersion { | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | 			fmt.Println("Dependencies:") | 
					
						
							|  |  |  | 			if info, ok := debug.ReadBuildInfo(); ok { | 
					
						
							|  |  |  | 				for _, dep := range info.Deps { | 
					
						
							|  |  |  | 					fmt.Println(dep.Path, dep.Version) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-12-25 11:33:18 +08:00
										 |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-04 20:03:47 +08:00
										 |  |  | 	logger := log.New("cli") | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err := log.Close(); err != nil { | 
					
						
							|  |  |  | 			fmt.Fprintf(os.Stderr, "Failed to close log: %s\n", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-04 20:03:47 +08:00
										 |  |  | 	if err := setupProfiling(Profile, ProfileAddr, ProfilePort); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := setupTracing(Tracing, TracingFile, logger); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-25 11:33:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-12 21:43:16 +08:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		// If we've managed to initialize them, this is the last place
 | 
					
						
							|  |  |  | 		// where we're able to log anything that'll end up in Grafana's
 | 
					
						
							|  |  |  | 		// log files.
 | 
					
						
							|  |  |  | 		// Since operators are not always looking at stderr, we'll try
 | 
					
						
							|  |  |  | 		// to log any and all panics that are about to crash Grafana to
 | 
					
						
							|  |  |  | 		// our regular log locations before exiting.
 | 
					
						
							|  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  | 			reason := fmt.Sprintf("%v", r) | 
					
						
							| 
									
										
										
										
											2023-08-04 20:03:47 +08:00
										 |  |  | 			logger.Error("Critical error", "reason", reason, "stackTrace", string(debug.Stack())) | 
					
						
							| 
									
										
										
										
											2022-08-12 21:43:16 +08:00
										 |  |  | 			panic(r) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-05 22:34:07 +08:00
										 |  |  | 	setBuildInfo(opts) | 
					
						
							|  |  |  | 	checkPrivileges() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-04 20:03:47 +08:00
										 |  |  | 	configOptions := strings.Split(ConfigOverrides, " ") | 
					
						
							| 
									
										
										
										
											2023-09-01 20:09:54 +08:00
										 |  |  | 	cfg, err := setting.NewCfgFromArgs(setting.CommandLineArgs{ | 
					
						
							|  |  |  | 		Config:   ConfigFile, | 
					
						
							|  |  |  | 		HomePath: HomePath, | 
					
						
							|  |  |  | 		// tailing arguments have precedence over the options string
 | 
					
						
							|  |  |  | 		Args: append(configOptions, opts.Context.Args().Slice()...), | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-11-23 00:53:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-07 05:34:23 +08:00
										 |  |  | 	metrics.SetBuildInformation(metrics.ProvideRegisterer(cfg), opts.Version, opts.Commit, opts.BuildBranch, getBuildstamp(opts)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 23:45:56 +08:00
										 |  |  | 	s, err := server.Initialize( | 
					
						
							| 
									
										
										
										
											2023-09-01 20:09:54 +08:00
										 |  |  | 		cfg, | 
					
						
							| 
									
										
										
										
											2022-11-23 00:53:43 +08:00
										 |  |  | 		server.Options{ | 
					
						
							| 
									
										
										
										
											2023-08-04 20:03:47 +08:00
										 |  |  | 			PidFile:     PidFile, | 
					
						
							|  |  |  | 			Version:     opts.Version, | 
					
						
							|  |  |  | 			Commit:      opts.Commit, | 
					
						
							|  |  |  | 			BuildBranch: opts.BuildBranch, | 
					
						
							| 
									
										
										
										
											2022-11-23 00:53:43 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		api.ServerOptions{}, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx := context.Background() | 
					
						
							|  |  |  | 	go listenToSystemSignals(ctx, s) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:19:01 +08:00
										 |  |  | 	return s.Run() | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func validPackaging(packaging string) string { | 
					
						
							|  |  |  | 	validTypes := []string{"dev", "deb", "rpm", "docker", "brew", "hosted", "unknown"} | 
					
						
							|  |  |  | 	for _, vt := range validTypes { | 
					
						
							|  |  |  | 		if packaging == vt { | 
					
						
							|  |  |  | 			return packaging | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return "unknown" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-07 01:11:57 +08:00
										 |  |  | // a small interface satisfied by the server and moduleserver
 | 
					
						
							|  |  |  | type gserver interface { | 
					
						
							|  |  |  | 	Shutdown(context.Context, string) error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func listenToSystemSignals(ctx context.Context, s gserver) { | 
					
						
							| 
									
										
										
										
											2021-08-26 21:42:22 +08:00
										 |  |  | 	signalChan := make(chan os.Signal, 1) | 
					
						
							|  |  |  | 	sighupChan := make(chan os.Signal, 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	signal.Notify(sighupChan, syscall.SIGHUP) | 
					
						
							|  |  |  | 	signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-sighupChan: | 
					
						
							|  |  |  | 			if err := log.Reload(); err != nil { | 
					
						
							|  |  |  | 				fmt.Fprintf(os.Stderr, "Failed to reload loggers: %s\n", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case sig := <-signalChan: | 
					
						
							|  |  |  | 			ctx, cancel := context.WithTimeout(ctx, 30*time.Second) | 
					
						
							|  |  |  | 			defer cancel() | 
					
						
							|  |  |  | 			if err := s.Shutdown(ctx, fmt.Sprintf("System signal: %s", sig)); err != nil { | 
					
						
							|  |  |  | 				fmt.Fprintf(os.Stderr, "Timed out waiting for server to shut down\n") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-08-04 20:03:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func checkPrivileges() { | 
					
						
							|  |  |  | 	elevated, err := process.IsRunningWithElevatedPrivileges() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Fprintf(os.Stderr, "Error checking server process execution privilege. error: %s\n", err.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if elevated { | 
					
						
							|  |  |  | 		fmt.Println("Grafana server is running with elevated privileges. This is not recommended") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |