Skip to content

Commit

Permalink
[target-allocator] marshal with jsoniter (#1323)
Browse files Browse the repository at this point in the history
* benchmarking jsoniter

* fix imports

* fix lint issues

* add chlog file

* remove duplicate funcs used for benchmarking

* fix imports
  • Loading branch information
Kristina Pathak committed Jan 5, 2023
1 parent fde6b95 commit 74581ea
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 31 deletions.
17 changes: 17 additions & 0 deletions .chloggen/use-json-iterator.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. operator, target allocator, github action)
component: Target Allocator

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Use json-iter to marshal json

# One or more tracking issues related to the change
issues:
- 1336

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:
2 changes: 1 addition & 1 deletion cmd/otel-allocator/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/go-kit/log v0.2.1
github.com/go-logr/logr v1.2.3
github.com/gorilla/mux v1.8.0
github.com/json-iterator/go v1.1.12
github.com/mitchellh/hashstructure v1.1.0
github.com/oklog/run v1.1.0
github.com/prometheus-operator/prometheus-operator v0.53.1
Expand Down Expand Up @@ -111,7 +112,6 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b // indirect
github.com/linode/linodego v1.8.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
Expand Down
53 changes: 34 additions & 19 deletions cmd/otel-allocator/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,19 @@ package server

import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"time"

yaml2 "github.com/ghodss/yaml"
"github.com/go-logr/logr"
"github.com/gorilla/mux"
jsoniter "github.com/json-iterator/go"
"github.com/mitchellh/hashstructure"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
"gopkg.in/yaml.v2"
promconfig "github.com/prometheus/prometheus/config"

"github.com/open-telemetry/opentelemetry-operator/cmd/otel-allocator/allocation"
"github.com/open-telemetry/opentelemetry-operator/cmd/otel-allocator/target"
Expand All @@ -42,27 +41,49 @@ var (
}, []string{"path"})
)

var (
yamlConfig = jsoniter.Config{
EscapeHTML: false,
MarshalFloatWith6Digits: true,
ObjectFieldMustBeSimpleString: true,
TagKey: "yaml",
}.Froze()
jsonConfig = jsoniter.Config{
EscapeHTML: false,
MarshalFloatWith6Digits: true,
ObjectFieldMustBeSimpleString: true,
}.Froze()
)

type collectorJSON struct {
Link string `json:"_link"`
Jobs []*target.Item `json:"targets"`
}

type DiscoveryManager interface {
GetScrapeConfigs() map[string]*promconfig.ScrapeConfig
}

type Server struct {
logger logr.Logger
allocator allocation.Allocator
discoveryManager *target.Discoverer
discoveryManager DiscoveryManager
server *http.Server
yamlMarshaller jsoniter.API // TODO: for testing, it would make a lot of sense to have a simpler interface
jsonMarshaller jsoniter.API // TODO: for testing, it would make a lot of sense to have a simpler interface

compareHash uint64
scrapeConfigResponse []byte
}

func NewServer(log logr.Logger, allocator allocation.Allocator, discoveryManager *target.Discoverer, listenAddr *string) *Server {
func NewServer(log logr.Logger, allocator allocation.Allocator, discoveryManager DiscoveryManager, listenAddr *string) *Server {
s := &Server{
logger: log,
allocator: allocator,
discoveryManager: discoveryManager,
compareHash: uint64(0),
yamlMarshaller: yamlConfig,
jsonMarshaller: jsonConfig,
}
router := mux.NewRouter().UseEncodedPath()
router.Use(s.PrometheusMiddleware)
Expand All @@ -87,7 +108,7 @@ func (s *Server) Shutdown(ctx context.Context) error {
// ScrapeConfigsHandler returns the available scrape configuration discovered by the target allocator.
// The target allocator first marshals these configurations such that the underlying prometheus marshaling is used.
// After that, the YAML is converted in to a JSON format for consumers to use.
func (s *Server) ScrapeConfigsHandler(w http.ResponseWriter, r *http.Request) {
func (s *Server) ScrapeConfigsHandler(w http.ResponseWriter, _ *http.Request) {
configs := s.discoveryManager.GetScrapeConfigs()

hash, err := hashstructure.Hash(configs, nil)
Expand All @@ -98,19 +119,13 @@ func (s *Server) ScrapeConfigsHandler(w http.ResponseWriter, r *http.Request) {
}
// if the hashes are different, we need to recompute the scrape config
if hash != s.compareHash {
var configBytes []byte
configBytes, err = yaml.Marshal(configs)
if err != nil {
s.errorHandler(w, err)
return
}
var jsonConfig []byte
jsonConfig, err = yaml2.YAMLToJSON(configBytes)
if err != nil {
s.errorHandler(w, err)
configBytes, mErr := s.yamlMarshaller.Marshal(configs)
if mErr != nil {
s.errorHandler(w, mErr)
return
}
s.scrapeConfigResponse = jsonConfig
// Update the response and the hash
s.scrapeConfigResponse = configBytes
s.compareHash = hash
}
// We don't use the jsonHandler method because we don't want our bytes to be re-encoded
Expand All @@ -121,7 +136,7 @@ func (s *Server) ScrapeConfigsHandler(w http.ResponseWriter, r *http.Request) {
}
}

func (s *Server) JobHandler(w http.ResponseWriter, r *http.Request) {
func (s *Server) JobHandler(w http.ResponseWriter, _ *http.Request) {
displayData := make(map[string]target.LinkJSON)
for _, v := range s.allocator.TargetItems() {
displayData[v.JobName] = target.LinkJSON{Link: v.Link.Link}
Expand Down Expand Up @@ -172,7 +187,7 @@ func (s *Server) errorHandler(w http.ResponseWriter, err error) {

func (s *Server) jsonHandler(w http.ResponseWriter, data interface{}) {
w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(data)
err := s.jsonMarshaller.NewEncoder(w).Encode(data)
if err != nil {
s.logger.Error(err, "failed to encode data for http response")
}
Expand Down
Loading

0 comments on commit 74581ea

Please sign in to comment.