github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/server/ingest/server.go (about)

     1  /*
     2  Copyright 2023.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package ingestserver
    18  
    19  import (
    20  	"net"
    21  	"time"
    22  
    23  	"github.com/siglens/siglens/pkg/hooks"
    24  	"github.com/siglens/siglens/pkg/segment/query"
    25  	log "github.com/sirupsen/logrus"
    26  
    27  	"github.com/fasthttp/router"
    28  	"github.com/oklog/run"
    29  	"github.com/siglens/siglens/pkg/config"
    30  	"github.com/siglens/siglens/pkg/ingest"
    31  	"github.com/siglens/siglens/pkg/segment/writer"
    32  	server_utils "github.com/siglens/siglens/pkg/server/utils"
    33  	"github.com/valyala/fasthttp"
    34  	"github.com/valyala/fasthttp/pprofhandler"
    35  )
    36  
    37  type ingestionServerCfg struct {
    38  	Config config.WebConfig
    39  	Addr   string
    40  	//	Log    *zap.Logger //ToDo implement debug logger
    41  	ln     net.Listener
    42  	router *router.Router
    43  	debug  bool
    44  }
    45  
    46  var (
    47  	corsAllowHeaders = "Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Max-Age, Access-Control-Allow-Credentials, Content-Type, Authorization, Origin, X-Requested-With , Accept"
    48  	corsAllowMethods = "HEAD, GET, POST, PUT, DELETE, OPTIONS"
    49  	corsAllowOrigin  = "*"
    50  )
    51  
    52  // ConstructHttpServer new fasthttp server
    53  func ConstructIngestServer(cfg config.WebConfig, ServerAddr string) *ingestionServerCfg {
    54  
    55  	s := &ingestionServerCfg{
    56  		Config: cfg,
    57  		Addr:   ServerAddr,
    58  		router: router.New(),
    59  		debug:  true,
    60  	}
    61  	return s
    62  }
    63  
    64  func (hs *ingestionServerCfg) Close() {
    65  	_ = hs.ln.Close()
    66  }
    67  
    68  func getMyIds() []uint64 {
    69  	myids := make([]uint64, 1)
    70  
    71  	alreadyHandled := false
    72  	if hook := hooks.GlobalHooks.GetIdsConditionHook; hook != nil {
    73  		alreadyHandled = hook(myids)
    74  	}
    75  
    76  	if !alreadyHandled {
    77  		myids[0] = 0
    78  	}
    79  
    80  	return myids
    81  }
    82  
    83  func (hs *ingestionServerCfg) Run() (err error) {
    84  
    85  	//Register all the method handlers here
    86  	ingest.InitIngestionMetrics()
    87  	writer.InitWriterNode()
    88  
    89  	if !config.IsQueryNode() && config.IsIngestNode() {
    90  		go query.InitQueryInfoRefresh(getMyIds)
    91  	}
    92  
    93  	hs.router.GET(server_utils.API_PREFIX+"/health", hs.Recovery(getHealthHandler()))
    94  	hs.router.POST(server_utils.API_PREFIX+"/sampledataset_bulk", hs.Recovery(sampleDatasetBulkHandler()))
    95  
    96  	hs.router.POST("/setconfig/transient", hs.Recovery(postSetconfigHandler(false)))
    97  	hs.router.POST("/setconfig/persistent", hs.Recovery(postSetconfigHandler(true)))
    98  	hs.router.GET("/config", hs.Recovery(getConfigHandler()))
    99  	hs.router.POST("/config/reload", hs.Recovery(getConfigReloadHandler()))
   100  
   101  	//elasticsearch endpoints
   102  	hs.router.HEAD(server_utils.ELASTIC_PREFIX+"/", hs.Recovery(esGreetHandler()))
   103  	hs.router.GET(server_utils.ELASTIC_PREFIX+"/", hs.Recovery(esGreetHandler()))
   104  	hs.router.GET(server_utils.ELASTIC_PREFIX+"/_xpack", hs.Recovery(esGreetHandler()))
   105  	hs.router.POST(server_utils.ELASTIC_PREFIX+"/_bulk", hs.Recovery(esPostBulkHandler()))
   106  	hs.router.PUT(server_utils.ELASTIC_PREFIX+"/{indexName}", hs.Recovery(EsPutIndexHandler()))
   107  
   108  	// Loki endpoints
   109  	hs.router.POST(server_utils.LOKI_PREFIX+"/api/v1/push", hs.Recovery(lokiPostBulkHandler()))
   110  
   111  	// Splunk Handlers
   112  	hs.router.POST("/services/collector/event", hs.Recovery(splunkHecIngestHandler()))
   113  	hs.router.GET("/services/collector/health", hs.Recovery(getHealthHandler()))
   114  	hs.router.GET("/services/collector/health/1.0", hs.Recovery(getHealthHandler()))
   115  
   116  	// OpenTSDB Handlers
   117  	hs.router.PUT(server_utils.OTSDB_PREFIX+"/api/put", hs.Recovery(otsdbPutMetricsHandler()))
   118  	hs.router.POST(server_utils.OTSDB_PREFIX+"/api/put", hs.Recovery(otsdbPutMetricsHandler()))
   119  
   120  	// Influx Handlers
   121  	hs.router.POST(server_utils.INFLUX_PREFIX+"/api/v2/write", hs.Recovery(influxPutMetricsHandler()))
   122  
   123  	// Prometheus Handlers
   124  	hs.router.POST(server_utils.PROMQL_PREFIX+"/api/v1/write", hs.Recovery(prometheusPutMetricsHandler()))
   125  
   126  	// OTLP Handlers
   127  	hs.router.POST(server_utils.OTLP_PREFIX+"/v1/traces", hs.Recovery(otlpIngestTracesHandler()))
   128  
   129  	if config.IsDebugMode() {
   130  		hs.router.GET("/debug/pprof/{profile:*}", pprofhandler.PprofHandler)
   131  	}
   132  
   133  	if hook := hooks.GlobalHooks.ExtraIngestEndpointsHook; hook != nil {
   134  		hook(hs.router, hs.Recovery)
   135  	}
   136  
   137  	hs.ln, err = net.Listen("tcp4", hs.Addr)
   138  	if err != nil {
   139  		return err
   140  	}
   141  
   142  	s := &fasthttp.Server{
   143  		Handler:            cors(hs.router.Handler),
   144  		Name:               hs.Config.Name,
   145  		ReadBufferSize:     hs.Config.ReadBufferSize,
   146  		MaxConnsPerIP:      hs.Config.MaxConnsPerIP,
   147  		MaxRequestsPerConn: hs.Config.MaxRequestsPerConn,
   148  		MaxRequestBodySize: hs.Config.MaxRequestBodySize, //  100 << 20, // 100MB // 1024 * 4, // MaxRequestBodySize:
   149  		Concurrency:        hs.Config.Concurrency,
   150  	}
   151  
   152  	// run fasthttp server
   153  	var g run.Group
   154  
   155  	if config.IsTlsEnabled() {
   156  		g.Add(func() error {
   157  			return s.ServeTLS(hs.ln, config.GetTLSCertificatePath(), config.GetTLSPrivateKeyPath())
   158  		}, func(e error) {
   159  			_ = hs.ln.Close()
   160  		})
   161  	} else {
   162  		g.Add(func() error {
   163  			return s.Serve(hs.ln)
   164  		}, func(e error) {
   165  			_ = hs.ln.Close()
   166  		})
   167  	}
   168  	return g.Run()
   169  }
   170  
   171  func (hs *ingestionServerCfg) RunSafeServer() (err error) {
   172  	hs.router.GET("/health", hs.Recovery(getSafeHealthHandler()))
   173  	hs.ln, err = net.Listen("tcp4", hs.Addr)
   174  	if err != nil {
   175  		return err
   176  	}
   177  
   178  	s := &fasthttp.Server{
   179  		Handler:            cors(hs.router.Handler),
   180  		Name:               hs.Config.Name,
   181  		ReadBufferSize:     hs.Config.ReadBufferSize,
   182  		MaxConnsPerIP:      hs.Config.MaxConnsPerIP,
   183  		MaxRequestsPerConn: hs.Config.MaxRequestsPerConn,
   184  		MaxRequestBodySize: hs.Config.MaxRequestBodySize, //  100 << 20, // 100MB // 1024 * 4, // MaxRequestBodySize:
   185  		Concurrency:        hs.Config.Concurrency,
   186  	}
   187  
   188  	log.Infof("Starting Ingestion Server on safe mode...")
   189  	ticker := time.NewTicker(1 * time.Minute)
   190  	go func() {
   191  		for range ticker.C {
   192  			log.Infof("Siglens Ingestion Server has started in safe mode...")
   193  		}
   194  	}()
   195  
   196  	// run fasthttp server
   197  	var g run.Group
   198  	g.Add(func() error {
   199  		return s.Serve(hs.ln)
   200  	}, func(e error) {
   201  		_ = hs.ln.Close()
   202  	})
   203  	return g.Run()
   204  }
   205  
   206  func cors(next fasthttp.RequestHandler) fasthttp.RequestHandler {
   207  	return func(ctx *fasthttp.RequestCtx) {
   208  		ctx.Response.Header.Set("Access-Control-Allow-Headers", corsAllowHeaders)
   209  		ctx.Response.Header.Set("Access-Control-Allow-Methods", corsAllowMethods)
   210  		ctx.Response.Header.Set("Access-Control-Allow-Origin", corsAllowOrigin)
   211  		ctx.Response.Header.Set("Access-Control-Allow-Credentials", "true")
   212  		next(ctx)
   213  	}
   214  }