pkg/rules/elasticsearch/es_client_setup.go (64 lines of code) (raw):
// Copyright (c) 2024 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package elasticsearch
import (
"context"
"net/http"
"os"
"strings"
_ "unsafe"
"github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/api"
"github.com/elastic/elastic-transport-go/v8/elastictransport"
elasticsearch "github.com/elastic/go-elasticsearch/v8"
)
var esInstrumenter = BuildElasticSearchInstrumenter()
type esInnerEnabler struct {
enabled bool
}
func (g esInnerEnabler) Enable() bool {
return g.enabled
}
var esEnabler = esInnerEnabler{os.Getenv("OTEL_INSTRUMENTATION_ELASTICSEARCH_ENABLED") != "false"}
//go:linkname beforeElasticSearchPerform github.com/elastic/go-elasticsearch/v8.beforeElasticSearchPerform
func beforeElasticSearchPerform(call api.CallContext, client *elasticsearch.BaseClient, request *http.Request) {
if !esEnabler.Enable() {
return
}
var addresses []string
for _, u := range client.Transport.(*elastictransport.Client).URLs() {
addresses = append(addresses, u.String())
}
op, params := getEsOpAndParams(request)
er := &esRequest{
request: request,
address: strings.Join(addresses, ","),
op: op,
params: params,
}
newCtx := esInstrumenter.Start(request.Context(), er)
call.SetKeyData("ctx", newCtx)
call.SetKeyData("request", er)
}
//go:linkname afterElasticSearchPerform github.com/elastic/go-elasticsearch/v8.afterElasticSearchPerform
func afterElasticSearchPerform(call api.CallContext, response *http.Response, err error) {
if !esEnabler.Enable() {
return
}
newCtx := call.GetKeyData("ctx").(context.Context)
er := call.GetKeyData("request").(*esRequest)
esInstrumenter.End(newCtx, er, response, err)
}
func getEsOpAndParams(req *http.Request) (string, []any) {
if req == nil || req.URL == nil {
return "UNKNOWN", nil
}
path := req.URL.Path
paths := strings.Split(path, "/")
if len(paths) <= 1 {
return "UNKNOWN", nil
}
if len(paths) == 2 {
return strings.ToLower(req.Method), nil
}
params := make([]any, len(paths)-2)
// path[0] should be the index name
for i := 2; i < len(paths); i++ {
params[i-2] = paths[i]
}
return paths[2], params
}