-
Notifications
You must be signed in to change notification settings - Fork 734
Description
Problem
The current Java source code integration (find_java.go) hardcodes the .java file extension when resolving function names to source file paths:
const ExtJava = ".java"The convertJavaFunctionNameToPath function always appends .java:
com/example/MyClass.method→com/example/MyClass.java
This means Kotlin applications get 404 errors for every source code lookup, since Kotlin source files use the .kt extension.
Context
Kotlin is a JVM language officially supported by Google for Android and widely used in server-side applications (Spring Boot, Ktor, etc.). Kotlin compiles to JVM bytecode, so the async-profiler / JFR profiling agent captures Kotlin classes the same way as Java classes. However, when Pyroscope tries to fetch the source code from GitHub, it looks for MyClass.java instead of MyClass.kt, resulting in a 404.
Reproduction
- Set up a Kotlin project with
.pyroscope.yaml:version: v1 source_code: mappings: - function_name: - prefix: com/example/myapp language: java source: github: owner: my-org repo: my-kotlin-app ref: main path: src/main/kotlin
- Profile the application and click on any function in the flame graph
- Pyroscope requests
src/main/kotlin/com/example/myapp/MyClass.javafrom GitHub - GitHub returns 404 because the actual file is
MyClass.kt
Proposed Solution
When language: java, try multiple JVM file extensions before returning "not found":
- Try
.javafirst (current behavior) - If 404, try
.kt(Kotlin) - Optionally try
.scala,.groovyfor other JVM languages
Alternatively, add a new language: kotlin option that uses .kt as the primary extension.
Suggested change in find_java.go:
var jvmExtensions = []string{".java", ".kt"}
func (ff *FileFinder) findJavaFile(ctx context.Context, mapping []MappingConfig) (*connect.Response[vcsv1.GetFileResponse], error) {
span, ctx := opentracing.StartSpanFromContext(ctx, "findJavaFile")
defer span.Finish()
path := convertJavaFunctionNameToPath(ff.file)
// path has .java extension, try .kt as fallback
basePath := strings.TrimSuffix(path, ExtJava)
for _, ext := range jvmExtensions {
candidate := basePath + ext
for _, m := range mapping {
resp, err := ff.fetchMappingFile(ctx, candidate, m)
if err == nil {
return resp, nil
}
// continue on 404, return on other errors
}
}
return nil, CodeNotFound
}Impact
This affects all JVM projects using non-Java languages:
- Kotlin — widely used in Android and server-side (Spring Boot)
- Scala — used in data engineering (Spark, Akka)
- Groovy — used in Gradle build scripts and some web apps
Environment
- Grafana Cloud with Pyroscope
- Kotlin 1.9.x + Spring Boot 3.x application
- Profiled via Grafana Alloy with
pyroscope.javacomponent .pyroscope.yamlwith 33 mappings, all returning 404 due to.javaextension