Skip to content

Commit 9fa48a7

Browse files
committed
gradle convention for generating weaver docs
1 parent 62172d7 commit 9fa48a7

File tree

11 files changed

+481
-306
lines changed

11 files changed

+481
-306
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ plugins {
99

1010
id("io.github.gradle-nexus.publish-plugin")
1111
id("otel.spotless-conventions")
12+
id("otel.weaver-docs")
1213
/* workaround for
1314
What went wrong:
1415
Could not determine the dependencies of task ':smoke-tests-otel-starter:spring-boot-3.2:bootJar'.
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import java.io.File
2+
3+
// Weaver documentation generation convention plugin
4+
// Recursively finds all instrumentation modules with models/ directories
5+
// and creates Gradle tasks to generate documentation using the OpenTelemetry Weaver tool
6+
7+
/**
8+
* Creates a Gradle task for generating weaver documentation from a models directory.
9+
*
10+
* @param instrumentationName The name to use in the task (derived from relative path)
11+
* @param modelsDir The directory containing weaver model files
12+
* @param docsDir The output directory for generated documentation
13+
*/
14+
fun createWeaverDocTask(instrumentationName: String, modelsDir: File, docsDir: File): TaskProvider<Exec> {
15+
return tasks.register<Exec>("generateWeaverDocs-${instrumentationName}") {
16+
group = "documentation"
17+
description = "Generate weaver documentation for $instrumentationName instrumentation"
18+
19+
inputs.dir(modelsDir)
20+
outputs.dir(docsDir)
21+
22+
standardOutput = System.out
23+
executable = "docker"
24+
25+
// Run as root in container to avoid permission issues with cache directory
26+
val dockerArgs = listOf<String>()
27+
28+
val cacheDir = File(project.layout.buildDirectory.get().asFile, ".weaver-cache")
29+
30+
// Template hierarchy (in order of precedence):
31+
// 1. Module-specific templates: models/templates/ (highest priority)
32+
// 2. Global shared templates: weaver-templates/ (medium priority)
33+
// 3. Default semantic-conventions templates (fallback)
34+
val moduleTemplatesDir = File(modelsDir, "templates")
35+
val globalTemplatesDir = File(project.rootDir, "weaver-templates")
36+
37+
val templatesSource = when {
38+
moduleTemplatesDir.exists() && moduleTemplatesDir.isDirectory -> {
39+
// Use module-specific templates (no mount needed, already in /source/templates)
40+
"/source/templates"
41+
}
42+
globalTemplatesDir.exists() && globalTemplatesDir.isDirectory -> {
43+
// Use global shared templates (needs separate mount)
44+
"/shared-templates"
45+
}
46+
else -> {
47+
// Fall back to default semantic-conventions templates
48+
"https://github.com/open-telemetry/semantic-conventions/archive/refs/tags/v1.34.0.zip[templates]"
49+
}
50+
}
51+
52+
// Build mount arguments - add global templates mount if using them
53+
val mountArgs = mutableListOf(
54+
"--mount", "type=bind,source=${modelsDir.absolutePath},target=/source,readonly",
55+
"--mount", "type=bind,source=${docsDir.absolutePath},target=/target",
56+
"--mount", "type=bind,source=${cacheDir.absolutePath},target=/home/weaver/.weaver"
57+
)
58+
59+
if (templatesSource == "/shared-templates") {
60+
mountArgs.addAll(listOf(
61+
"--mount", "type=bind,source=${globalTemplatesDir.absolutePath},target=/shared-templates,readonly"
62+
))
63+
}
64+
65+
val weaverArgs = listOf(
66+
"otel/weaver:v0.18.0@sha256:5425ade81dc22ddd840902b0638b4b6a9186fb654c5b50c1d1ccd31299437390",
67+
"registry", "generate",
68+
"--registry=/source",
69+
"--templates=${templatesSource}",
70+
"markdown", "/target"
71+
)
72+
73+
args = listOf("run", "--rm", "--platform=linux/x86_64") + dockerArgs + mountArgs + weaverArgs
74+
75+
doFirst {
76+
if (!modelsDir.exists()) {
77+
throw GradleException("Models directory does not exist: ${modelsDir.absolutePath}")
78+
}
79+
docsDir.mkdirs()
80+
cacheDir.mkdirs()
81+
}
82+
}
83+
}
84+
85+
/**
86+
* Recursively searches for all models/ directories under a given directory.
87+
*
88+
* @param dir The directory to search
89+
* @param baseDir The base directory for calculating relative paths
90+
* @return List of pairs containing (task-suffix, module-directory)
91+
*/
92+
fun findModelsDirectories(dir: File, baseDir: File = dir): List<Pair<String, File>> {
93+
val results = mutableListOf<Pair<String, File>>()
94+
95+
dir.listFiles()?.forEach { file ->
96+
if (file.isDirectory) {
97+
val modelsDir = File(file, "models")
98+
if (modelsDir.exists() && modelsDir.isDirectory) {
99+
val relativePath = file.relativeTo(baseDir).path.replace(File.separatorChar, '-')
100+
results.add(Pair(relativePath, file))
101+
}
102+
// Recursively search subdirectories
103+
results.addAll(findModelsDirectories(file, baseDir))
104+
}
105+
}
106+
107+
return results
108+
}
109+
110+
// Find all instrumentation modules with models directories and register tasks
111+
val weaverDocTasks = mutableListOf<TaskProvider<Exec>>()
112+
val instrumentationDir = file("instrumentation")
113+
if (instrumentationDir.exists() && instrumentationDir.isDirectory) {
114+
findModelsDirectories(instrumentationDir).forEach { (taskSuffix, moduleDir) ->
115+
val modelsDir = File(moduleDir, "models")
116+
val docsDir = File(moduleDir, "docs")
117+
val taskProvider = createWeaverDocTask(taskSuffix, modelsDir, docsDir)
118+
weaverDocTasks.add(taskProvider)
119+
}
120+
}
121+
122+
// Create an aggregate task to generate all weaver docs
123+
tasks.register("generateAllWeaverDocs") {
124+
group = "documentation"
125+
description = "Generate weaver documentation for all instrumentation modules"
126+
dependsOn(weaverDocTasks)
127+
}

docs/contributing/weaver.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Weaver Documentation Generation Guide
2+
3+
This project now includes Gradle tasks for generating documentation from weaver model files using
4+
the OpenTelemetry Weaver tool. The model files are currently generated by the gradle task
5+
`./gradlew :instrumentation-docs:runAnalysis`.
6+
7+
The build system automatically finds all instrumentation modules with a `models/` directory and
8+
creates Gradle tasks to generate documentation into a corresponding `docs/` directory.
9+
10+
## Model Directory Structure
11+
12+
Each instrumentation with weaver support will have:
13+
14+
```
15+
instrumentation/<module-name>/
16+
├── models/ # Scaffolded / Generated by the DocGenerater task
17+
│ ├── registry_manifest.yaml # Registry metadata and dependencies
18+
│ ├── signals.yaml # Metrics and spans definitions
19+
│ └── attributes.yaml # (Optional) Attribute group definitions
20+
└── docs/ # Generated documentation goes here
21+
└── README.md # Auto-generated
22+
```
23+
24+
## Usage
25+
26+
### Generate Documentation for a Specific Module
27+
28+
```bash
29+
./gradlew generateWeaverDocs-<module-name>
30+
31+
# Example:
32+
./gradlew generateWeaverDocs-activej-http-6.0
33+
```
34+
35+
### Generate Documentation for All Modules
36+
37+
```bash
38+
./gradlew generateAllWeaverDocs
39+
```
40+
41+
### List Available Documentation Tasks
42+
43+
```bash
44+
./gradlew tasks --group=documentation
45+
```
46+
47+
## Requirements
48+
49+
- Docker must be installed and running
50+
- The otel/weaver docker image will be pulled automatically
51+
52+
## Output
53+
54+
Generated documentation will appear in:
55+
- `instrumentation/<module-name>/docs/README.md`
56+
57+
## Manually Adding Weaver Support to a New Module
58+
59+
1. Create a `models/` directory in your instrumentation module
60+
2. Add `registry_manifest.yaml` with metadata and dependencies
61+
3. Add `signals.yaml` to define metrics/spans
62+
4. Add `attributes.yaml` for attributes
63+
5. Run `./gradlew generateWeaverDocs-<your-module-name>`
64+
65+
The build system will automatically detect the new models directory and create the task.
66+
67+
## Further Reading
68+
69+
- [Weaver Documentation](https://github.com/open-telemetry/weaver/tree/main/docs)
70+
- [Weaver Example Project](https://github.com/jerbly/weaver-example)

0 commit comments

Comments
 (0)