Skip to content

Commit

Permalink
feat: new built.WithOrchestrion constant (#387)
Browse files Browse the repository at this point in the history
Expose a `built.WithOrchestrion` constant so that usages where it is
possible to take a direct dependency on `github.com/DataDog/orchestrion`
is possible are simpler; as a readily available variable is provided.

This reduces the amount of places where the `//dd:orchestrion-enabled`
directive is necessary, which may improve compilation speeds (as
directive join points may be dispandious to evaluate).
  • Loading branch information
RomainMuller authored Nov 8, 2024
1 parent 28c50eb commit 3d60a25
Show file tree
Hide file tree
Showing 15 changed files with 258 additions and 122 deletions.
1 change: 0 additions & 1 deletion LICENSE-3rdparty.csv
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ orchestrion,github.com/charmbracelet/x/ansi,MIT,"Copyright (c) 2023 Charmbracele
orchestrion,github.com/cpuguy83/go-md2man/v2/md2man,MIT,Copyright (c) 2014 Brian Goff
orchestrion,github.com/dave/dst,MIT,Copyright (c) 2018 David Brophy | Copyright (c) 2009 The Go Authors. All rights reserved.
orchestrion,github.com/dave/jennifer/jen,MIT,Copyright (c) 2017 David Brophy
orchestrion,github.com/dlclark/regexp2,MIT,unknown
orchestrion,github.com/dustin/go-humanize,MIT,Copyright (c) 2005-2008 Dustin Sallings <dustin@spy.net>
orchestrion,github.com/eapache/queue/v2,MIT,Copyright (c) 2014 Evan Huus
orchestrion,github.com/ebitengine/purego,Apache-2.0,unknown
Expand Down
5 changes: 5 additions & 0 deletions _integration-tests/gls/access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ import (
"sync"
"testing"

"github.com/DataDog/orchestrion/runtime/built"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

//dd:orchestrion-enabled
const orchestrionEnabled = false

func TestBuiltWithOrchestrion(t *testing.T) {
require.Equal(t, built.WithOrchestrion, orchestrionEnabled)
}

func TestSimple(t *testing.T) {
expected := "Hello, World!"

Expand Down
6 changes: 2 additions & 4 deletions _integration-tests/tests/civisibility/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,15 @@ import (
"os"
"testing"

"github.com/DataDog/orchestrion/runtime/built"
"github.com/tinylib/msgp/msgp"
)

//dd:orchestrion-enabled
const isOrchestrionEnabled = false

var ciVisibilityPayloads mockPayloads

func TestMain(m *testing.M) {
// check if orchestrion is enabled
if !isOrchestrionEnabled {
if !built.WithOrchestrion {
panic("Orchestrion is not enabled, please run this test with orchestrion")
}

Expand Down
6 changes: 2 additions & 4 deletions _integration-tests/utils/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ import (

"datadoghq.dev/orchestrion/_integration-tests/utils/agent"
"datadoghq.dev/orchestrion/_integration-tests/validator/trace"
"github.com/DataDog/orchestrion/runtime/built"
"github.com/stretchr/testify/require"
)

//dd:orchestrion-enabled
const orchestrionEnabled = false

// TestCase describes the general contract for tests. Each package in this
// directory is expected to export a [TestCase] structure implementing this
// interface.
Expand Down Expand Up @@ -47,7 +45,7 @@ type TestCase interface {

func RunTest(t *testing.T, tc TestCase) {
t.Helper()
require.True(t, orchestrionEnabled, "this test suite must be run with orchestrion enabled")
require.True(t, built.WithOrchestrion, "this test suite must be run with orchestrion enabled")

mockAgent, err := agent.New(t)
require.NoError(t, err)
Expand Down
12 changes: 12 additions & 0 deletions docs/static/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@
"oneOf": [
{ "$ref": "#/$defs/join-point/all-of" },
{ "$ref": "#/$defs/join-point/configuration" },
{ "$ref": "#/$defs/join-point/declaration-of" },
{ "$ref": "#/$defs/join-point/directive" },
{ "$ref": "#/$defs/join-point/function-body" },
{ "$ref": "#/$defs/join-point/function" },
Expand Down Expand Up @@ -408,6 +409,17 @@
{ "configuration": { "httpmode": "wrap" } }
]
},
"declaration-of": {
"required": ["declaration-of"],
"unevaluatedProperties": false,
"properties": {
"declaration-of": {
"markdownDescription": "The `declaration-of` join point matches top-level declarations. It matches only `ValueSpec` and `FuncDecl` nodes.",
"type": "string",
"pattern": "^.+\\.[\\p{L}_][\\p{L}_\\p{Nd}]*$"
}
}
},
"directive": {
"required": ["directive"],
"unevaluatedProperties": false,
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ require (
github.com/charmbracelet/lipgloss v1.0.0
github.com/dave/dst v0.27.3
github.com/dave/jennifer v1.7.1
github.com/dlclark/regexp2 v1.11.4
github.com/fsnotify/fsnotify v1.8.0
github.com/gohugoio/hugo v0.136.5
github.com/google/go-licenses/v2 v2.0.0-alpha.1
Expand Down Expand Up @@ -129,6 +128,7 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/disintegration/gift v1.2.1 // indirect
github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/eapache/go-resiliency v1.7.0 // indirect
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
Expand Down
65 changes: 65 additions & 0 deletions internal/injector/aspect/join/declaration.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,60 @@
package join

import (
"fmt"
"regexp"

"github.com/DataDog/orchestrion/internal/injector/aspect/context"
"github.com/dave/dst"
"github.com/dave/jennifer/jen"
"gopkg.in/yaml.v3"
)

type declarationOf struct {
ImportPath string
Name string
}

// DeclarationOf matches the (top-level) declaration of the specified symbol.
func DeclarationOf(importPath string, name string) *declarationOf {
return &declarationOf{ImportPath: importPath, Name: name}
}

func (i *declarationOf) Matches(ctx context.AspectContext) bool {
if ctx.ImportPath() != i.ImportPath {
return false
}

switch node := ctx.Node().(type) {
case *dst.FuncDecl:
return node.Name != nil && node.Name.Name == i.Name
case *dst.ValueSpec:
if parent := ctx.Chain().Parent(); parent == nil {
// No parent, this is almost certainly a syntax error...
return false
} else if _, isGenDecl := parent.Node().(*dst.GenDecl); !isGenDecl {
// Parent isn't a GenDecl, so this is not a top-level declaration.
return false
}
for _, name := range node.Names {
if name.Name == i.Name {
return true
}
}
return false
default:
return false
}
}

func (i *declarationOf) ImpliesImported() []string {
return []string{i.ImportPath}
}

func (i *declarationOf) AsCode() jen.Code {
return jen.Qual(pkgPath, "DeclarationOf").Call(jen.Lit(i.ImportPath), jen.Lit(i.Name))
}

type valueDeclaration struct {
TypeName TypeName
}
Expand Down Expand Up @@ -49,7 +97,24 @@ func (i *valueDeclaration) AsCode() jen.Code {
return jen.Qual(pkgPath, "ValueDeclaration").Call(i.TypeName.AsCode())
}

// See: https://regex101.com/r/OXDfJ1/1
var symbolNamePattern = regexp.MustCompile(`\A(.+)\.([\p{L}_][\p{L}_\p{Nd}]*)\z`)

func init() {
unmarshalers["declaration-of"] = func(node *yaml.Node) (Point, error) {
var symbol string
if err := node.Decode(&symbol); err != nil {
return nil, err
}

matches := symbolNamePattern.FindStringSubmatch(symbol)
if matches == nil {
return nil, fmt.Errorf("invalid symbol name %q", symbol)
}

return DeclarationOf(matches[1], matches[2]), nil
}

unmarshalers["value-declaration"] = func(node *yaml.Node) (Point, error) {
var typeName string
if err := node.Decode(&typeName); err != nil {
Expand Down
26 changes: 14 additions & 12 deletions internal/injector/aspect/join/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,8 @@ type functionCall struct {
Name string
}

func FunctionCall(pattern string) *functionCall {
matches := funcNamePattern.FindStringSubmatch(pattern)
if matches == nil {
panic(fmt.Errorf("invalid function name pattern: %q", pattern))
}

return &functionCall{ImportPath: matches[1], Name: matches[2]}
func FunctionCall(importPath string, name string) *functionCall {
return &functionCall{ImportPath: importPath, Name: name}
}

func (i *functionCall) ImpliesImported() []string {
Expand Down Expand Up @@ -59,17 +54,24 @@ func (i *functionCall) Matches(ctx context.AspectContext) bool {
}

func (i *functionCall) AsCode() jen.Code {
return jen.Qual(pkgPath, "FunctionCall").Call(jen.Lit(i.ImportPath + "." + i.Name))
return jen.Qual(pkgPath, "FunctionCall").Call(jen.Lit(i.ImportPath), jen.Lit(i.Name))
}

var funcNamePattern = regexp.MustCompile(`\A(?:(.+)\.)?([^.]+)\z`)
// See: https://regex101.com/r/fjLo1l/1
var funcNamePattern = regexp.MustCompile(`\A(?:(.+)\.)?([\p{L}_][\p{L}_\p{Nd}]*)\z`)

func init() {
unmarshalers["function-call"] = func(node *yaml.Node) (Point, error) {
var pattern string
if err := node.Decode(&pattern); err != nil {
var symbol string
if err := node.Decode(&symbol); err != nil {
return nil, err
}
return FunctionCall(pattern), nil

matches := funcNamePattern.FindStringSubmatch(symbol)
if matches == nil {
return nil, fmt.Errorf("invalid function name %q", symbol)
}

return FunctionCall(matches[1], matches[2]), nil
}
}
Loading

0 comments on commit 3d60a25

Please sign in to comment.