Skip to content

feat(rule): add wrap_struct_literal join-point for struct literal instrumentation#459

Open
gyanranjanpanda wants to merge 2 commits into
open-telemetry:mainfrom
gyanranjanpanda:feat/struct-literal-join-point
Open

feat(rule): add wrap_struct_literal join-point for struct literal instrumentation#459
gyanranjanpanda wants to merge 2 commits into
open-telemetry:mainfrom
gyanranjanpanda:feat/struct-literal-join-point

Conversation

@gyanranjanpanda
Copy link
Copy Markdown
Contributor

Summary

Implements #202 — adds a new wrap_struct_literal join-point that enables template-based wrapping of struct instantiations at compile time.

Motivation

The current instrumentation framework supports wrapping function calls (wrap_call) and injecting hooks into function bodies (func), but has no mechanism to intercept struct literal creation. This is needed for instrumenting patterns like &http.Server{} or &http.Transport{} where the instrumentation point is the instantiation itself, not a function call.

Design

Rule Schema

wrap_struct_literal:
  target: "main"
  struct_literal: "net/http.Server"
  match: "pointer-only"  # value-only | pointer-only | any
  template: |
    func(s *http.Server) *http.Server {
        s.Handler = otelhttp.NewHandler(s.Handler)
        return s
    }({{ . }})

Match Modes

Mode Matches &http.Server{} Matches http.Server{}
pointer-only
value-only
any (default)

Architecture

The implementation follows the established rule engine pattern:

  1. Rule definition (InstStructLiteralRule) — mirrors InstCallRule with struct-specific fields
  2. Rule matching — collected during the setup phase using glob-based target patterns
  3. AST transformation — walks dst.CompositeLit nodes, resolves import aliases, and applies the template wrap

Changes

New files

File Purpose
tool/internal/rule/struct_literal_rule.go Rule type definition with validation
tool/internal/rule/struct_literal_rule_test.go Rule creation and validation tests
tool/internal/instrument/apply_struct_literal.go AST transformation logic
tool/internal/instrument/apply_struct_literal_test.go 5 test cases: pointer, value, mismatch, any, aliased imports

Modified files

File Change
tool/internal/rule/base.go Added StructLiteralRules to InstRuleSet, Excludes to InstBaseRule
tool/internal/instrument/instrument.go Dispatch InstStructLiteralRule to applyStructLiteralRule
tool/internal/setup/match.go Parse wrap_struct_literal rule type, glob-based target matching
tool/internal/setup/match_test.go Updated tests for refactored runMatch signature

Testing

  • All existing unit tests pass
  • All integration tests pass
  • All e2e tests pass
  • make all completes successfully (build → format → lint → test)

Checklist

  • Tests added for new functionality
  • make all passes
  • No new dependencies introduced
  • Apache 2.0 license headers present on all new files
  • Follows existing code patterns (InstCallRule, applyCallRule)

…trumentation

Implements issue open-telemetry#202 by adding a new wrap_struct_literal rule type that
enables template-based wrapping of struct instantiations at compile time.

Changes:
- Define InstStructLiteralRule with struct_literal, match, and template fields
- Integrate struct literal rules into the rule engine (parsing, matching)
- Implement AST transformation via applyStructLiteralRule using dst walker
- Support value-only, pointer-only, and any match modes
- Handle aliased imports for accurate struct type resolution
- Add glob-based target matching with exclude patterns for all rule types
- Add comprehensive unit tests for rule creation and AST transformation

Assisted-by: Claude Opus 4.6
@gyanranjanpanda gyanranjanpanda requested a review from a team as a code owner May 4, 2026 04:21
@github-actions github-actions Bot added the scope:feat A new feature being added label May 4, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3d5e96a28

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tool/internal/setup/match.go Outdated
// Filter rules by target using pattern matching
relevantRules := make([]rule.InstRule, 0)
for _, r := range allRules {
matched, err := path.Match(r.GetTarget(), dep.ImportPath)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use prefix-aware matching for target/excludes globs

runMatch now uses path.Match to evaluate both target and excludes, but path.Match treats / as a separator and * does not cross it. That means common glob intents like target: "*", target: "github.com/myorg/*", or similar excludes will not match multi-segment import paths (for example, github.com/myorg/lib/subpkg), so rules are silently skipped in real projects. Since this commit introduces glob-based targeting, this behavior makes the feature effectively unusable for most package paths unless every / level is explicitly encoded.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@amazingakai amazingakai left a comment

Choose a reason for hiding this comment

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

Thank you for looking into this. For context, my comment was meant to start a discussion rather than serve as a ready proposal. I think it might be too soon to implement this without some maintainer input on the design first.

Comment thread tool/internal/setup/match.go Outdated
Comment on lines +149 to +177
relevantRules := make([]rule.InstRule, 0)
for _, r := range allRules {
matched, err := path.Match(r.GetTarget(), dep.ImportPath)
if err != nil {
sp.Error("Invalid target pattern", "target", r.GetTarget(), "err", err)
continue
}
if !matched {
continue
}

// Check excludes
excluded := false
for _, excl := range r.GetExcludes() {
exclMatch, exclErr := path.Match(excl, dep.ImportPath)
if exclErr != nil {
sp.Warn("Invalid exclude pattern", "pattern", excl, "error", exclErr)
continue
}
if exclMatch {
excluded = true
break
}
}

if !excluded {
relevantRules = append(relevantRules, r)
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this should be a separate PR. Also this is already being implemented in form of not combinator (#386) + import path glob filter (#382).

InstBaseRule `yaml:",inline"`

StructLiteral string `json:"struct_literal" yaml:"struct_literal"` // The type name of the struct literal to be matched
Match string `json:"match" yaml:"match"` // "value-only", "pointer-only", or "any"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Orchestrion also supported field level advising, mutually exclusive with match. Might be worth adding but it should be discussed first.
See: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/struct-literal/

@amazingakai
Copy link
Copy Markdown
Contributor

This PR is also missing golden tests and documentation.

…en tests, and revert premature glob match logic
@gyanranjanpanda
Copy link
Copy Markdown
Contributor Author

could @amazingakai check this if there any other isuue pls let me know

@y1yang0
Copy link
Copy Markdown
Contributor

y1yang0 commented May 7, 2026

Too early to review now, we should first discuss the necessity and design.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope:feat A new feature being added

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants