Skip to content

Commit dea53cb

Browse files
committed
Merge branch 'main' into zgu/refactor-vmstructs
2 parents 95f92fd + 6e11f7d commit dea53cb

12 files changed

Lines changed: 2042 additions & 321 deletions

File tree

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
description: Analyze divergences from upstream async-profiler, propose grouped PRs, and open draft PRs.
3+
---
4+
5+
# Contribute Upstream Workflow
6+
7+
You are orchestrating the contribution of java-profiler divergences back to the upstream async-profiler project. These are all changes in our repo relative to upstream — not just uncommitted local modifications. Follow these steps precisely.
8+
9+
## Configuration
10+
11+
- **Fork repo**: `git@github.com:DataDog/async-profiler.git`
12+
- **Upstream repo**: `async-profiler/async-profiler` (for PR target)
13+
- **Upstream branch**: `master`
14+
- **Analysis script**: `utils/check_contribution_candidates.sh`
15+
- **Report dir**: `build/contribution-reports/`
16+
17+
## Step 1: Run Analysis
18+
19+
Execute the analysis script to generate reports:
20+
21+
```bash
22+
./utils/check_contribution_candidates.sh
23+
```
24+
25+
If it fails, diagnose and report the error to the user. Do not proceed.
26+
27+
## Step 2: Parse Results
28+
29+
Find the most recent JSON report in `build/contribution-reports/` (highest timestamp). Read it to get the list of files with contributable hunks.
30+
31+
Also read the corresponding markdown report to understand the actual diff hunks for each file.
32+
33+
If there are zero candidates, tell the user and stop.
34+
35+
## Step 3: Filter Out Existing PRs
36+
37+
Before proposing new PRs, check what's already open from the DataDog fork against upstream. Note: `--author DataDog` does not work because fork PRs are authored by the pushing user, not the org. Instead, query the API and filter by head repo:
38+
39+
```bash
40+
gh api 'repos/async-profiler/async-profiler/pulls?state=open&per_page=100' \
41+
--jq '.[] | select(.head.repo.full_name == "DataDog/async-profiler") | {number, title}'
42+
```
43+
44+
Then for each matching PR, fetch the files it touches:
45+
46+
```bash
47+
gh api 'repos/async-profiler/async-profiler/pulls/<number>/files' --jq '.[].filename'
48+
```
49+
50+
For each open PR, extract the list of files it touches. Then cross-reference with the candidate files from Step 2:
51+
52+
- If a candidate file is already fully covered by an open PR (i.e., the PR touches that file and addresses the same type of change), **exclude it** from proposals
53+
- If a candidate file is only partially covered (the open PR addresses some hunks but not others), keep the uncovered hunks as candidates
54+
- When presenting proposals in Step 4, mention any skipped files and the existing PR that covers them, so the user has full visibility
55+
56+
Analyze the remaining contributable hunks across candidate files and group them into logical PR proposals. Guidelines:
57+
58+
- **Related changes go together**: e.g., a bug fix touching `stackWalker.cpp` and `vmStructs.cpp` for the same issue = one PR
59+
- **Independent changes are separate**: unrelated fixes in different files = separate PRs
60+
- **Each PR should be self-contained**: it should make sense on its own, compile on its own, and have a clear rationale
61+
- **Keep PRs small**: prefer multiple small PRs over one large one
62+
63+
For each proposed PR, prepare:
64+
- A descriptive title (e.g., "Fix null pointer check in stackWalker", "Add bounds validation in VMStruct")
65+
- The list of files and hunks it covers
66+
- A brief rationale explaining why this change benefits upstream
67+
68+
## Step 5: Present Proposals to User
69+
70+
Show the user a numbered list of proposed PRs with:
71+
- Title
72+
- Files involved
73+
- Brief description of the change
74+
- Number of hunks
75+
76+
Use `AskUserQuestion` with `multiSelect: true` to let the user pick which PRs to create. Offer all proposals as options.
77+
78+
If the user selects none, stop.
79+
80+
## Step 6: Create Selected PRs
81+
82+
For each selected PR, perform the following:
83+
84+
### 6a. Clone the Fork (once)
85+
86+
Clone `git@github.com:DataDog/async-profiler.git` to a temp directory. Reuse this clone for all PRs.
87+
88+
```bash
89+
FORK_DIR=$(mktemp -d "${TMPDIR:-/tmp}/async-profiler-fork.XXXXXX")
90+
git clone git@github.com:DataDog/async-profiler.git "$FORK_DIR"
91+
cd "$FORK_DIR"
92+
git remote add upstream https://github.com/async-profiler/async-profiler.git
93+
git fetch upstream
94+
git checkout -b temp upstream/master
95+
git branch -D master 2>/dev/null || true
96+
git checkout -b master
97+
git branch -D temp
98+
```
99+
100+
### 6b. Create Feature Branch
101+
102+
For each PR, create a branch from upstream master:
103+
104+
```bash
105+
cd "$FORK_DIR"
106+
git checkout master
107+
BRANCH_NAME="contribute/<slug>-$(date +%Y%m%d)"
108+
git checkout -b "$BRANCH_NAME"
109+
```
110+
111+
Where `<slug>` is a short kebab-case description derived from the PR title.
112+
113+
### 6c. Port Changes
114+
115+
Apply only the relevant contributable hunks for this PR to the upstream files:
116+
117+
1. For each file in the PR, find the corresponding upstream file in `src/` of the fork
118+
2. Apply the contributable hunks using careful manual editing (use the Edit tool)
119+
3. **Critical**: Ensure NO Datadog-specific references leak through (DD_, ddprof, Datadog, datadog, DDPROF, context.h, counters.h, tagger, QueueItem)
120+
4. If a hunk cannot be cleanly applied because the upstream file diverged, skip it and note it for the user
121+
122+
### 6d. Verify Build
123+
124+
Attempt a basic build check:
125+
126+
```bash
127+
cd "$FORK_DIR"
128+
make
129+
```
130+
131+
If the build fails, analyze the error. If it's a simple fix (e.g., missing include), fix it. If it's complex, note it for the user and proceed anyway (the PR is draft).
132+
133+
### 6e. Commit and Push
134+
135+
```bash
136+
cd "$FORK_DIR"
137+
git add -A
138+
git commit -m "<concise description of the change>"
139+
git push origin "$BRANCH_NAME"
140+
```
141+
142+
### 6f. Open Draft PR
143+
144+
Use `gh` to create a draft PR against upstream. **Important**: Before creating the first PR, fetch the target project's PR template from the upstream repo (`gh api repos/async-profiler/async-profiler/contents/.github/PULL_REQUEST_TEMPLATE.md` and decode the base64 content). The PR body **must** follow that template exactly — use all its sections, checkboxes, and footer verbatim. Fill in each section with the relevant content for this change.
145+
146+
```bash
147+
gh pr create \
148+
--repo async-profiler/async-profiler \
149+
--base master \
150+
--head "DataDog:$BRANCH_NAME" \
151+
--draft \
152+
--title "<PR title>" \
153+
--body "<body following the upstream PR template>"
154+
```
155+
156+
## Step 7: Report
157+
158+
After all selected PRs are created, show the user:
159+
- A summary table of created PRs with their URLs
160+
- Any hunks that could not be applied
161+
- Any build issues encountered
162+
- The temp directory path in case manual follow-up is needed
163+
164+
## Error Handling
165+
166+
- If `gh` is not authenticated, tell the user to run `gh auth login` and stop
167+
- If the fork clone fails, check SSH key setup and report
168+
- If a branch already exists on the fork, append a counter suffix (e.g., `-2`)
169+
- Always clean up on fatal errors (remove temp directory)

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,20 @@ For detailed documentation, see [doc/RemoteSymbolication.md](doc/plans/RemoteSym
433433
4. Run tests: `./gradlew test`
434434
5. Submit a pull request
435435

436+
## Utility Scripts
437+
438+
The [`utils/`](utils/) directory contains helper scripts for common workflows. See [`utils/README.md`](utils/README.md) for full documentation.
439+
440+
| Script | Description |
441+
|--------|-------------|
442+
| `release.sh` | Trigger a validated release (major/minor/patch) via GitHub Actions |
443+
| `backport-pr.sh` | Cherry-pick a merged PR onto a release branch and open a backport PR |
444+
| `patch-dd-java-agent.sh` | Patch `dd-java-agent.jar` with a local ddprof build for quick testing |
445+
| `run-docker-tests.sh` | Run tests in Docker containers (musl/glibc, multiple JDKs) |
446+
| `check_upstream_changes.sh` | Check for upstream async-profiler changes locally |
447+
| `track_upstream_changes.sh` | Track upstream changes and generate reports |
448+
| `generate_tracked_files.sh` | Generate the list of files tracked from upstream |
449+
436450
## License
437451
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
438452

ddprof-lib/src/main/cpp/javaApi.cpp

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -440,9 +440,6 @@ Java_com_datadoghq_profiler_JVMAccess_healthCheck0(JNIEnv *env,
440440
return true;
441441
}
442442

443-
// Static variable to track the current published context
444-
static otel_process_ctx_result* current_published_context = nullptr;
445-
446443
extern "C" DLLEXPORT void JNICALL
447444
Java_com_datadoghq_profiler_OTelContext_setProcessCtx0(JNIEnv *env,
448445
jclass unused,
@@ -460,16 +457,19 @@ Java_com_datadoghq_profiler_OTelContext_setProcessCtx0(JNIEnv *env,
460457
JniString version_str(env, version);
461458
JniString tracer_version_str(env, tracer_version);
462459

460+
const char *host_name_attrs[] = {"host.name", hostname_str.c_str(), NULL};
461+
463462
otel_process_ctx_data data = {
464-
.deployment_environment_name = const_cast<char*>(env_str.c_str()),
465-
.host_name = const_cast<char*>(hostname_str.c_str()),
466-
.service_instance_id = const_cast<char*>(runtime_id_str.c_str()),
467-
.service_name = const_cast<char*>(service_str.c_str()),
468-
.service_version = const_cast<char*>(version_str.c_str()),
469-
.telemetry_sdk_language = const_cast<char*>("java"),
470-
.telemetry_sdk_version = const_cast<char*>(tracer_version_str.c_str()),
471-
.telemetry_sdk_name = const_cast<char*>("dd-trace-java"),
472-
.resources = NULL // TODO: Arbitrary tags not supported yet for Java
463+
.deployment_environment_name = env_str.c_str(),
464+
.service_instance_id = runtime_id_str.c_str(),
465+
.service_name = service_str.c_str(),
466+
.service_version = version_str.c_str(),
467+
.telemetry_sdk_language = "java",
468+
.telemetry_sdk_version = tracer_version_str.c_str(),
469+
.telemetry_sdk_name = "dd-trace-java",
470+
.resource_attributes = host_name_attrs,
471+
.extra_attributes = NULL,
472+
.thread_ctx_config = NULL
473473
};
474474

475475
otel_process_ctx_result result = otel_process_ctx_publish(&data);
@@ -491,8 +491,6 @@ Java_com_datadoghq_profiler_OTelContext_readProcessCtx0(JNIEnv *env, jclass unus
491491
// Convert C strings to Java strings
492492
jstring jDeploymentEnvironmentName = result.data.deployment_environment_name ?
493493
env->NewStringUTF(result.data.deployment_environment_name) : nullptr;
494-
jstring jHostName = result.data.host_name ?
495-
env->NewStringUTF(result.data.host_name) : nullptr;
496494
jstring jServiceInstanceId = result.data.service_instance_id ?
497495
env->NewStringUTF(result.data.service_instance_id) : nullptr;
498496
jstring jServiceName = result.data.service_name ?
@@ -505,7 +503,17 @@ Java_com_datadoghq_profiler_OTelContext_readProcessCtx0(JNIEnv *env, jclass unus
505503
env->NewStringUTF(result.data.telemetry_sdk_version) : nullptr;
506504
jstring jTelemetrySdkName = result.data.telemetry_sdk_name ?
507505
env->NewStringUTF(result.data.telemetry_sdk_name) : nullptr;
508-
// TODO: result.data.resources not supported yet for Java
506+
507+
// Extract host.name from resource_attributes
508+
jstring jHostName = nullptr;
509+
if (result.data.resource_attributes != NULL) {
510+
for (int i = 0; result.data.resource_attributes[i] != NULL; i += 2) {
511+
if (strcmp(result.data.resource_attributes[i], "host.name") == 0 && result.data.resource_attributes[i + 1] != NULL) {
512+
jHostName = env->NewStringUTF(result.data.resource_attributes[i + 1]);
513+
break;
514+
}
515+
}
516+
}
509517

510518
otel_process_ctx_read_drop(&result);
511519

0 commit comments

Comments
 (0)