Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/variables/go-versions.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
latest=1.26
penultimate=1.25
min=1.18
min=1.24
27 changes: 0 additions & 27 deletions .github/workflows/common_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,6 @@ jobs:
enforce: 'false'


unit-test-easyjson:
runs-on: ubuntu-latest
name: 'Unit Tests (easyjson)'
steps:
- uses: actions/checkout@v4
- name: Setup Go ${{ inputs.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ inputs.go-version }}
- uses: ./.github/actions/unit-tests
with:
lint: 'true'
make-target: 'test-easyjson'


benchmarks:
name: 'Benchmarks'
runs-on: ubuntu-latest
Expand All @@ -51,15 +36,3 @@ jobs:
go-version: ${{ inputs.go-version }}
- uses: ./.github/actions/benchmarks

benchmarks-easyjson:
name: 'Benchmarks (easyjson)'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go ${{ inputs.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ inputs.go-version }}
- uses: ./.github/actions/benchmarks
with:
make-target: 'benchmarks-easyjson'
17 changes: 3 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,24 @@ COVERAGE_PROFILE_RAW=./build/coverage_raw.out
COVERAGE_PROFILE_RAW_HTML=./build/coverage_raw.html
COVERAGE_PROFILE_FILTERED=./build/coverage.out
COVERAGE_PROFILE_FILTERED_HTML=./build/coverage.html
COVERAGE_ENFORCER_FLAGS=-package github.com/launchdarkly/go-server-sdk-evaluation/v3 -skipcode "// COVERAGE" -packagestats -filestats -showcode
COVERAGE_ENFORCER_FLAGS=-package github.com/launchdarkly/go-server-sdk-evaluation/v4 -skipcode "// COVERAGE" -packagestats -filestats -showcode
Comment thread
cursor[bot] marked this conversation as resolved.

TEST_BINARY=./go-server-sdk-evaluation.test
ALLOCATIONS_LOG=./allocations.out

EASYJSON_TAG=-tags launchdarkly_easyjson
.PHONY: all build clean test lint test-coverage benchmarks benchmark-allocs

.PHONY: all build build-easyjson clean test test-easyjson lint test-coverage benchmarks benchmark-allocs

all: build build-easyjson
all: build

build:
go build ./...

build-easyjson:
go build $(EASYJSON_TAG) ./...

clean:
go clean

test: build
go test -v -race -count 1 ./...

test-easyjson: build-easyjson
go test -v -race -count 1 $(EASYJSON_TAG) ./...

test-coverage: $(COVERAGE_PROFILE_RAW)
go run github.com/launchdarkly-labs/go-coverage-enforcer@latest $(COVERAGE_ENFORCER_FLAGS) -outprofile $(COVERAGE_PROFILE_FILTERED) $(COVERAGE_PROFILE_RAW)
go tool cover -html $(COVERAGE_PROFILE_FILTERED) -o $(COVERAGE_PROFILE_FILTERED_HTML)
Expand All @@ -49,9 +41,6 @@ benchmarks: build
go test -benchmem '-run=^$$' '-bench=.*' ./... | tee build/benchmarks.out
@if grep <build/benchmarks.out 'NoAlloc.*[1-9][0-9]* allocs/op'; then echo "Unexpected heap allocations detected in benchmarks!"; exit 1; fi

benchmarks-easyjson: build-easyjson
go test $(EASYJSON_TAG) -benchmem '-run=^$$' '-bench=.*' ./...

# See CONTRIBUTING.md regarding the use of the benchmark-allocs target. Notes about this implementation:
# 1. We precompile the test code because otherwise the allocation traces will include the actions of the compiler itself.
# 2. "benchtime=3x" means the run count (b.N) is set to 3. Setting it to 1 would produce less redundant output, but the
Expand Down
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# LaunchDarkly Go SDK Evaluation Engine

[![Actions Status](https://github.com/launchdarkly/go-server-sdk-evaluation/actions/workflows/ci.yml/badge.svg?branch=v3)](https://github.com/launchdarkly/go-server-sdk-evaluation/actions/workflows/ci.yml)
[![Documentation](https://img.shields.io/static/v1?label=go.dev&message=reference&color=00add8)](https://pkg.go.dev/github.com/launchdarkly/go-server-sdk-evaluation/v3)
[![Actions Status](https://github.com/launchdarkly/go-server-sdk-evaluation/actions/workflows/ci.yml/badge.svg?branch=v4)](https://github.com/launchdarkly/go-server-sdk-evaluation/actions/workflows/ci.yml)
[![Documentation](https://img.shields.io/static/v1?label=go.dev&message=reference&color=00add8)](https://pkg.go.dev/github.com/launchdarkly/go-server-sdk-evaluation/v4)

## Overview

Expand All @@ -11,12 +11,6 @@ This repository contains the internal feature flag evaluation logic and data mod

This version of the project requires a Go version of 1.18 or higher.

## Integration with easyjson

By default, `go-server-sdk-evaluation` uses LaunchDarkly's open-source JSON library [`go-jsonstream`](https://github.com/launchdarkly/go-jsonstream) to convert its data model types like `FeatureFlag` to and from JSON; this is considerably faster than Go's built-in `encoding/json` and does not depend on any third-party code. However, it can optionally integrate with the third-party library [`easyjson`](https://github.com/mailru/easyjson), which may be even faster in some cases, without requiring any changes in your code. To enable this, set the build tag `launchdarkly_easyjson` when you run `go build`, which both switches `go-jsonstream` to use `easyjson` internally and also generates `MarshalEasyJSON`/`UnmarshalEasyJSON` methods for each JSON-serializable type. The `easyjson` library is still under development and has some potential compatibility issues; see its documentation for more details.

If you do not set the `launchdarkly_easyjson` build tag, `go-server-sdk-evaluation` does not use any code from `easyjson`.

## Learn more

Check out our [documentation](http://docs.launchdarkly.com) for in-depth instructions on configuring and using LaunchDarkly. You can also head straight to the [complete reference guide for the Go SDK](http://docs.launchdarkly.com/docs/go-sdk-reference), or the [generated API documentation](https://pkg.go.dev/github.com/launchdarkly/go-server-sdk-evaluation/v3) for this project.
Expand Down
2 changes: 1 addition & 1 deletion errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package evaluation
import (
"fmt"

"github.com/launchdarkly/go-sdk-common/v3/ldreason"
"github.com/launchdarkly/go-sdk-common/v4/ldreason"
)

// These error types are used only internally to distinguish between reasons an evaluation might fail.
Expand Down
2 changes: 1 addition & 1 deletion errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
"testing"

"github.com/launchdarkly/go-sdk-common/v3/ldreason"
"github.com/launchdarkly/go-sdk-common/v4/ldreason"

"github.com/stretchr/testify/assert"
)
Expand Down
25 changes: 12 additions & 13 deletions evaluator.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package evaluation

import (
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldlog"
"github.com/launchdarkly/go-sdk-common/v3/ldreason"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldmodel"
"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldlog"
"github.com/launchdarkly/go-sdk-common/v4/ldreason"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldmodel"
)

// Notes on some implementation details in this file:
Expand All @@ -16,10 +16,9 @@ import (
// nested function/method calls; passing a pointer instead is faster. It is safe for us to do this
// as long as the pointer value is not being retained outside the scope of this call.
//
// - In some for loops, we are deliberately taking the address of the range variable and using a
// "//nolint:gosec" directive to turn off the usual linter warning about this:
// - In some for loops, we are deliberately taking the address of the range variable:
// for _, x := range someThings {
// doSomething(&x) //nolint:gosec
// doSomething(&x)
// }
// The rationale is the same as above, and is safe as long as the same conditions apply.

Expand Down Expand Up @@ -154,7 +153,7 @@ func (es *evaluationScope) evaluate(stack evaluationStack) (ldreason.EvaluationD

// Now walk through the rules and see if any match
for ruleIndex, rule := range es.flag.Rules {
match, err := es.ruleMatchesContext(&rule, stack) //nolint:gosec // see comments at top of file
match, err := es.ruleMatchesContext(&rule, stack)
if err != nil {
es.logEvaluationError(err)
return ldreason.NewEvaluationDetailForError(errorKindForError(err), ldvalue.Null()), false
Expand Down Expand Up @@ -277,7 +276,7 @@ func (es *evaluationScope) anyTargetMatchVariation() ldvalue.OptionalInt {
// If ContextTargets is empty but Targets is not empty, then this is flag data that originally
// came from a non-context-aware LD endpoint or SDK. In that case, just look at Targets.
for _, t := range es.flag.Targets {
if variation := es.targetMatchVariation(&t); variation.IsDefined() { //nolint:gosec // see comments at top of file
if variation := es.targetMatchVariation(&t); variation.IsDefined() {
return variation
}
}
Expand All @@ -289,12 +288,12 @@ func (es *evaluationScope) anyTargetMatchVariation() ldvalue.OptionalInt {
if (t.ContextKind == "" || t.ContextKind == ldcontext.DefaultKind) && len(t.Values) == 0 {
for _, t1 := range es.flag.Targets {
if t1.Variation == t.Variation {
variation = es.targetMatchVariation(&t1) //nolint:gosec // see comments at top of file
variation = es.targetMatchVariation(&t1)
break
}
}
} else {
variation = es.targetMatchVariation(&t) //nolint:gosec // see comments at top of file
variation = es.targetMatchVariation(&t)
}
if variation.IsDefined() {
return variation
Expand All @@ -316,7 +315,7 @@ func (es *evaluationScope) targetMatchVariation(t *ldmodel.Target) ldvalue.Optio
func (es *evaluationScope) ruleMatchesContext(rule *ldmodel.FlagRule, stack evaluationStack) (bool, error) {
// Note that rule is passed by reference only for efficiency; we do not modify it
for _, clause := range rule.Clauses {
match, err := es.clauseMatchesContext(&clause, stack) //nolint:gosec // see comments at top of file
match, err := es.clauseMatchesContext(&clause, stack)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These gosec changes were made because the version of Go (in go.mod) was upgraded from 1.18 to 1.24. Sometime in that version gap, gosec no longer flags using the variable's address.

if !match || err != nil {
return match, err
}
Expand Down
12 changes: 6 additions & 6 deletions evaluator_base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import (
"fmt"
"testing"

"github.com/launchdarkly/go-sdk-common/v3/ldattr"
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldreason"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldmodel"
"github.com/launchdarkly/go-sdk-common/v4/ldattr"
"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldreason"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldmodel"
"github.com/stretchr/testify/assert"
)

Expand Down
10 changes: 5 additions & 5 deletions evaluator_benchmarks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import (
"fmt"
"testing"

"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldmodel"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldmodel"

"github.com/launchdarkly/go-sdk-common/v3/ldattr"
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-sdk-common/v4/ldattr"
"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
)

// Note about heap allocations:
Expand Down
12 changes: 6 additions & 6 deletions evaluator_big_segment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import (
"fmt"
"testing"

"github.com/launchdarkly/go-sdk-common/v3/ldattr"
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldreason"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldmodel"
"github.com/launchdarkly/go-sdk-common/v4/ldattr"
"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldreason"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldmodel"

"github.com/stretchr/testify/assert"
)
Expand Down
8 changes: 4 additions & 4 deletions evaluator_bucketing.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"crypto/sha1" //nolint:gosec // SHA1 is cryptographically weak but we are not using it to hash any credentials
"encoding/hex"

"github.com/launchdarkly/go-server-sdk-evaluation/v3/internal"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/internal"

"github.com/launchdarkly/go-sdk-common/v3/ldattr"
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-sdk-common/v4/ldattr"
"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
)

const (
Expand Down
6 changes: 3 additions & 3 deletions evaluator_bucketing_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package evaluation
import (
"testing"

"github.com/launchdarkly/go-sdk-common/v3/ldattr"
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-sdk-common/v4/ldattr"
"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
)

func BenchmarkComputeBucketValueNoAlloc(b *testing.B) {
Expand Down
10 changes: 5 additions & 5 deletions evaluator_bucketing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import (
"strconv"
"testing"

"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldmodel"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldmodel"

"github.com/launchdarkly/go-sdk-common/v3/ldattr"
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-sdk-common/v4/ldattr"
"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
2 changes: 1 addition & 1 deletion evaluator_bucketing_testdata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package evaluation
import (
"fmt"

"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
)

// These parameters are used in evaluator_bucketing_test.go. In each case, we have precomputed
Expand Down
8 changes: 4 additions & 4 deletions evaluator_clause.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"strings"
"time"

"github.com/launchdarkly/go-sdk-common/v3/ldattr"
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldmodel"
"github.com/launchdarkly/go-sdk-common/v4/ldattr"
"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldmodel"
)

func (es *evaluationScope) clauseMatchesContext(clause *ldmodel.Clause, stack evaluationStack) (bool, error) {
Expand Down
8 changes: 4 additions & 4 deletions evaluator_clause_operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"fmt"
"testing"

"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldmodel"
"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldmodel"

"github.com/stretchr/testify/assert"
)
Expand Down
10 changes: 5 additions & 5 deletions evaluator_clause_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"fmt"
"testing"

"github.com/launchdarkly/go-sdk-common/v3/ldattr"
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldmodel"
"github.com/launchdarkly/go-sdk-common/v4/ldattr"
"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldmodel"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
16 changes: 8 additions & 8 deletions evaluator_flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package evaluation
import (
"testing"

"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v3/ldmodel"

"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/go-sdk-common/v3/ldlog"
"github.com/launchdarkly/go-sdk-common/v3/ldlogtest"
"github.com/launchdarkly/go-sdk-common/v3/ldreason"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldbuilders"
"github.com/launchdarkly/go-server-sdk-evaluation/v4/ldmodel"

"github.com/launchdarkly/go-sdk-common/v4/ldcontext"
"github.com/launchdarkly/go-sdk-common/v4/ldlog"
"github.com/launchdarkly/go-sdk-common/v4/ldlogtest"
"github.com/launchdarkly/go-sdk-common/v4/ldreason"
"github.com/launchdarkly/go-sdk-common/v4/ldvalue"
m "github.com/launchdarkly/go-test-helpers/v3/matchers"

"github.com/stretchr/testify/assert"
Expand Down
2 changes: 1 addition & 1 deletion evaluator_options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package evaluation

import "github.com/launchdarkly/go-sdk-common/v3/ldlog"
import "github.com/launchdarkly/go-sdk-common/v4/ldlog"

// EvaluatorOption is an optional parameter for NewEvaluator.
type EvaluatorOption interface {
Expand Down
Loading
Loading