Skip to content

Commit e9dde47

Browse files
authored
Merge pull request #2731 from digma-ai/error-hotsopt-lens-click
error-hotsopt-lens-click Closes #2699
2 parents 1abc846 + e5034ff commit e9dde47

File tree

10 files changed

+121
-71
lines changed

10 files changed

+121
-71
lines changed

ide-common/src/main/java/org/digma/intellij/plugin/analytics/AnalyticsService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ public String register(@NotNull Map<String, Object> queryParams) throws Analytic
523523
}
524524

525525
@NotNull
526-
public InsightsStatsResult getInsightsStats(String spanCodeObjectId, String insightTypes, String services) {
526+
public InsightsStatsResult getInsightsStats(@Nullable String spanCodeObjectId, String insightTypes, String services) {
527527
try {
528528
var envId = getCurrentEnvironmentId();
529529
var params = new HashMap<String, Object>();
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package org.digma.intellij.plugin.codelens
2+
3+
import com.intellij.openapi.diagnostic.Logger
4+
import com.intellij.openapi.fileEditor.FileEditorManager
5+
import com.intellij.openapi.project.Project
6+
import com.intellij.pom.Navigatable
7+
import com.intellij.psi.PsiElement
8+
import com.intellij.psi.SmartPsiElementPointer
9+
import org.digma.intellij.plugin.common.Backgroundable
10+
import org.digma.intellij.plugin.common.EDT
11+
import org.digma.intellij.plugin.common.objectToJsonNode
12+
import org.digma.intellij.plugin.errorreporting.ErrorReporter
13+
import org.digma.intellij.plugin.log.Log
14+
import org.digma.intellij.plugin.model.lens.CodeLens
15+
import org.digma.intellij.plugin.notifications.NotificationUtil
16+
import org.digma.intellij.plugin.posthog.ActivityMonitor
17+
import org.digma.intellij.plugin.scope.ScopeContext
18+
import org.digma.intellij.plugin.scope.ScopeManager
19+
import org.digma.intellij.plugin.scope.SpanScope
20+
21+
internal class CodeLensClickHandler(
22+
private val project: Project,
23+
private val lens: CodeLens,
24+
private val elementPointer: SmartPsiElementPointer<PsiElement>
25+
) {
26+
27+
private val logger: Logger = Logger.getInstance(this::class.java)
28+
29+
fun handle() {
30+
31+
try {
32+
ActivityMonitor.getInstance(project).registerLensClicked(lens.id)
33+
elementPointer.element?.let {
34+
if (it is Navigatable && it.canNavigateToSource()) {
35+
it.navigate(true)
36+
} else {
37+
//it's a fallback. sometimes the psiMethod.canNavigateToSource is false and really the
38+
//navigation doesn't work. I can't say why. usually it happens when indexing is not ready yet,
39+
// and the user opens files, selects tabs or moves the caret. then when indexing is finished,
40+
// we have the list of methods but then psiMethod.navigate doesn't work.
41+
// navigation to source using the editor does work in these circumstances.
42+
val selectedEditor = FileEditorManager.getInstance(project).selectedTextEditor
43+
selectedEditor?.caretModel?.moveToOffset(it.textOffset)
44+
}
45+
}
46+
47+
Backgroundable.ensurePooledThreadWithoutReadAccess {
48+
val isErrorHotspot = lens.lensTitle.lowercase().contains("error")
49+
val scopeCodeObjectId = lens.scopeCodeObjectId
50+
val contextPayload = objectToJsonNode(ChangeScopeMessagePayload(lens))
51+
val scopeContext = ScopeContext("IDE/CODE_LENS_CLICKED", contextPayload)
52+
if (isErrorHotspot) {
53+
ScopeManager.getInstance(project)
54+
.changeToHome(true, scopeContext, null)
55+
}else{
56+
if (scopeCodeObjectId == null) {
57+
EDT.ensureEDT {
58+
NotificationUtil.notifyFadingInfo(project, "No asset found for method: ${lens.codeMethod}")
59+
}
60+
}else{
61+
ScopeManager.getInstance(project)
62+
.changeScope(SpanScope(spanCodeObjectId = scopeCodeObjectId, methodId = lens.codeMethod), scopeContext, null)
63+
}
64+
}
65+
}
66+
} catch (e: Exception) {
67+
Log.warnWithException(logger, project, e, "error in CodeLensClickHandler {}", e)
68+
ErrorReporter.getInstance().reportError(project, "CodeLensClickHandler.handle", e)
69+
}
70+
}
71+
}

ide-common/src/main/kotlin/org/digma/intellij/plugin/codelens/CodeLensService.kt

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -205,39 +205,9 @@ class CodeLensService(private val project: Project) : Disposable {
205205
private val lens: CodeLens,
206206
private val project: Project,
207207
) : (MouseEvent?, Editor) -> Unit {
208-
private val logger: Logger = Logger.getInstance(this::class.java)
209-
private val elementPointer = SmartPointerManager.createPointer(element)
208+
private val codelensClickHandler = CodeLensClickHandler(project,lens,SmartPointerManager.createPointer(element))
210209
override fun invoke(event: MouseEvent?, editor: Editor) {
211-
try {
212-
ActivityMonitor.getInstance(project).registerLensClicked(lens.id)
213-
elementPointer.element?.let {
214-
if (it is Navigatable && it.canNavigateToSource()) {
215-
it.navigate(true)
216-
} else {
217-
//it's a fallback. sometimes the psiMethod.canNavigateToSource is false and really the
218-
//navigation doesn't work. I can't say why. usually it happens when indexing is not ready yet,
219-
// and the user opens files, selects tabs or moves the caret. then when indexing is finished
220-
// we have the list of methods but then psiMethod.navigate doesn't work.
221-
// navigation to source using the editor does work in these circumstances.
222-
val selectedEditor = FileEditorManager.getInstance(project).selectedTextEditor
223-
selectedEditor?.caretModel?.moveToOffset(it.textOffset)
224-
}
225-
}
226-
227-
val scopeCodeObjectId = lens.scopeCodeObjectId
228-
if (scopeCodeObjectId == null){
229-
NotificationUtil.notifyFadingInfo(project,"No asset found for method: ${lens.codeMethod}")
230-
}else{
231-
Backgroundable.ensurePooledThreadWithoutReadAccess {
232-
val contextPayload = objectToJsonNode(ChangeScopeMessagePayload(lens))
233-
val scopeContext = ScopeContext("IDE/CODE_LENS_CLICKED", contextPayload)
234-
ScopeManager.getInstance(project).changeScope(SpanScope(scopeCodeObjectId), scopeContext, null)
235-
}
236-
}
237-
} catch (e: Exception) {
238-
Log.warnWithException(logger, project, e, "error in ClickHandler {}", e)
239-
ErrorReporter.getInstance().reportError(project, "${this::class.simpleName}.ClickHandler.invoke", e)
240-
}
210+
codelensClickHandler.handle()
241211
}
242212
}
243213

ide-common/src/main/kotlin/org/digma/intellij/plugin/scope/ScopeManager.kt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ class ScopeManager(private val project: Project) {
3636
EDT.assertNonDispatchThread()
3737

3838
//must happen before firing the event
39-
if (!environmentId.isNullOrBlank()){
40-
setCurrentEnvironmentById(project,environmentId)
39+
if (!environmentId.isNullOrBlank()) {
40+
setCurrentEnvironmentById(project, environmentId)
4141
}
4242

43-
fireScopeChangedEvent(null, CodeLocation(listOf(), listOf()), false, scopeContext,environmentId)
43+
fireScopeChangedEvent(null, CodeLocation(listOf(), listOf()), false, scopeContext, environmentId)
4444

4545
EDT.ensureEDT {
4646
//don't do that on first wizard launch to let user complete the installation wizard.
@@ -65,7 +65,6 @@ class ScopeManager(private val project: Project) {
6565

6666
EDT.assertNonDispatchThread()
6767

68-
6968
try {
7069
when (scope) {
7170
is SpanScope -> changeToSpanScope(scope, scopeContext, environmentId)
@@ -91,8 +90,8 @@ class ScopeManager(private val project: Project) {
9190
) {
9291

9392
//must happen before anything else
94-
if (!environmentId.isNullOrBlank()){
95-
setCurrentEnvironmentById(project,environmentId)
93+
if (!environmentId.isNullOrBlank()) {
94+
setCurrentEnvironmentById(project, environmentId)
9695
}
9796

9897
val spanScopeInfo = try {
@@ -102,10 +101,10 @@ class ScopeManager(private val project: Project) {
102101
null
103102
}
104103

105-
val methodId = spanScopeInfo?.methodCodeObjectId ?: tryGetMethodIdForSpan(scope.spanCodeObjectId)
106-
methodId?.let {
107-
scope.methodId = CodeObjectsUtil.addMethodTypeToId(it)
108-
}
104+
//maybe the scope has methodId already, if not try to find it.
105+
//in any case add a method type to scope.methodId.
106+
val methodId = scope.methodId ?: spanScopeInfo?.methodCodeObjectId ?: tryGetMethodIdForSpan(scope.spanCodeObjectId)
107+
scope.methodId = methodId?.let { CodeObjectsUtil.addMethodTypeToId(it) }
109108
scope.displayName = spanScopeInfo?.displayName ?: ""
110109
scope.role = spanScopeInfo?.role
111110

@@ -153,7 +152,8 @@ class ScopeManager(private val project: Project) {
153152
scope: SpanScope?, codeLocation: CodeLocation, hasErrors: Boolean, scopeContext: ScopeContext?, environmentId: String?,
154153
) {
155154
project.messageBus.syncPublisher(ScopeChangedEvent.SCOPE_CHANGED_TOPIC)
156-
.scopeChanged(scope, codeLocation, hasErrors, scopeContext,environmentId)
155+
.scopeChanged(scope, codeLocation, hasErrors, scopeContext, environmentId)
157156
}
158157

158+
159159
}

src/main/kotlin/org/digma/intellij/plugin/ui/jcef/JCefComponent.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,11 @@ private constructor(
299299
project.messageBus.connect(parentDisposable).subscribe(
300300
ScopeChangedEvent.SCOPE_CHANGED_TOPIC, object : ScopeChangedEvent {
301301
override fun scopeChanged(
302-
scope: SpanScope?, codeLocation: CodeLocation, hasErrors: Boolean, scopeContext: ScopeContext?, environmentId: String?
302+
scope: SpanScope?,
303+
codeLocation: CodeLocation,
304+
hasErrors: Boolean,
305+
scopeContext: ScopeContext?,
306+
environmentId: String?
303307
) {
304308
try {
305309
val insightsStats = AnalyticsService.getInstance(project).getInsightsStats(scope?.spanCodeObjectId, null, null)
@@ -528,7 +532,8 @@ private constructor(
528532
}
529533

530534

531-
class LifeSpanHandle(private val schemeHandlerFactory: BaseSchemeHandlerFactory, private val url: String, private val appName: String) : CefLifeSpanHandlerAdapter() {
535+
class LifeSpanHandle(private val schemeHandlerFactory: BaseSchemeHandlerFactory, private val url: String, private val appName: String) :
536+
CefLifeSpanHandlerAdapter() {
532537

533538
override fun onAfterCreated(browser: CefBrowser) {
534539

@@ -538,7 +543,7 @@ class LifeSpanHandle(private val schemeHandlerFactory: BaseSchemeHandlerFactory,
538543
schemeHandlerFactory.getSchema(), schemeHandlerFactory.getDomain(), schemeHandlerFactory
539544
)
540545

541-
if(MAIN_APP_APP_NAME == appName) {
546+
if (MAIN_APP_APP_NAME == appName) {
542547
val mailtoSchemaHandlerFactory = MailtoSchemaHandlerFactory()
543548
CefApp.getInstance().registerSchemeHandlerFactory(
544549
mailtoSchemaHandlerFactory.getSchema(), mailtoSchemaHandlerFactory.getDomain(), mailtoSchemaHandlerFactory

src/main/kotlin/org/digma/intellij/plugin/ui/jcef/JCefMessagesUtils.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -261,16 +261,16 @@ fun sendRunConfigurationAttributes(
261261
}
262262

263263

264-
fun sendGenericPluginEventStringPayload(project: Project, cefBrowser: CefBrowser, name: String, payload: String? = null) {
265-
val jsonNode: JsonNode? = payload?.let {
266-
try {
267-
CommonObjectMapper.objectMapper.readTree(payload)
268-
} catch (e: Throwable) {
269-
null
270-
}
271-
}
272-
sendGenericPluginEvent(project, cefBrowser, name, jsonNode)
273-
}
264+
//fun sendGenericPluginEventStringPayload(project: Project, cefBrowser: CefBrowser, name: String, payload: String? = null) {
265+
// val jsonNode: JsonNode? = payload?.let {
266+
// try {
267+
// CommonObjectMapper.objectMapper.readTree(payload)
268+
// } catch (e: Throwable) {
269+
// null
270+
// }
271+
// }
272+
// sendGenericPluginEvent(project, cefBrowser, name, jsonNode)
273+
//}
274274

275275

276276
fun sendGenericPluginEvent(project: Project, cefBrowser: CefBrowser, name: String, payload: JsonNode? = null) {

src/main/kotlin/org/digma/intellij/plugin/ui/jcef/model/Persistence.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import org.digma.intellij.plugin.ui.jcef.JCEFGlobalConstants
77
import java.beans.ConstructorProperties
88

99

10-
enum class Scope {
10+
enum class JCefPersistenceScope {
1111
application, project
1212
}
1313

@@ -24,7 +24,7 @@ constructor(
2424
class SaveToPersistencePayload
2525
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
2626
@ConstructorProperties("key", "value", "scope")
27-
constructor(val key: String, val value: JsonNode, val scope: Scope)
27+
constructor(val key: String, val value: JsonNode, val scope: JCefPersistenceScope)
2828

2929

3030
@JsonIgnoreProperties(ignoreUnknown = true)
@@ -40,12 +40,12 @@ constructor(
4040
class GetFromPersistencePayload
4141
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
4242
@ConstructorProperties("key", "scope")
43-
constructor(val key: String, val scope: Scope)
43+
constructor(val key: String, val scope: JCefPersistenceScope)
4444

4545

4646
class SetFromPersistenceMessage(val payload: SetFromPersistenceMessagePayload) {
4747
val type = JCEFGlobalConstants.REQUEST_MESSAGE_TYPE
4848
val action = JCEFGlobalConstants.GLOBAL_SET_FROM_PERSISTENCE
4949
}
5050

51-
class SetFromPersistenceMessagePayload(val key: String, val value: JsonNode?, val scope: Scope, val error: ErrorPayload? = null)
51+
class SetFromPersistenceMessagePayload(val key: String, val value: JsonNode?, val scope: JCefPersistenceScope, val error: ErrorPayload? = null)

src/main/kotlin/org/digma/intellij/plugin/ui/jcef/persistence/JCEFPersistenceService.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import org.digma.intellij.plugin.errorreporting.ErrorReporter
1616
import org.digma.intellij.plugin.ui.jcef.model.ErrorPayload
1717
import org.digma.intellij.plugin.ui.jcef.model.GetFromPersistenceRequest
1818
import org.digma.intellij.plugin.ui.jcef.model.SaveToPersistenceRequest
19-
import org.digma.intellij.plugin.ui.jcef.model.Scope
19+
import org.digma.intellij.plugin.ui.jcef.model.JCefPersistenceScope
2020
import org.digma.intellij.plugin.ui.jcef.model.SetFromPersistenceMessage
2121
import org.digma.intellij.plugin.ui.jcef.model.SetFromPersistenceMessagePayload
2222
import org.digma.intellij.plugin.ui.jcef.serializeAndExecuteWindowPostMessageJavaScript
@@ -34,8 +34,8 @@ class JCEFPersistenceService(private val project: Project) {
3434

3535
fun getFromPersistence(browser: CefBrowser, getFromPersistenceRequest: GetFromPersistenceRequest) {
3636
when (getFromPersistenceRequest.payload.scope) {
37-
Scope.application -> getFromApplicationPersistence(browser, getFromPersistenceRequest)
38-
Scope.project -> getFromProjectPersistence(browser, getFromPersistenceRequest)
37+
JCefPersistenceScope.application -> getFromApplicationPersistence(browser, getFromPersistenceRequest)
38+
JCefPersistenceScope.project -> getFromProjectPersistence(browser, getFromPersistenceRequest)
3939
}
4040
}
4141

@@ -78,7 +78,7 @@ class JCEFPersistenceService(private val project: Project) {
7878
}
7979

8080

81-
private fun sendError(key: String, scope: Scope, e: Throwable, browser: CefBrowser) {
81+
private fun sendError(key: String, scope: JCefPersistenceScope, e: Throwable, browser: CefBrowser) {
8282
val message = SetFromPersistenceMessage(
8383
SetFromPersistenceMessagePayload(
8484
key,
@@ -94,14 +94,14 @@ class JCEFPersistenceService(private val project: Project) {
9494

9595
try {
9696
when (saveToPersistenceRequest.payload.scope) {
97-
Scope.application -> {
97+
JCefPersistenceScope.application -> {
9898
JCEFApplicationPersistence.getInstance().set(
9999
saveToPersistenceRequest.payload.key,
100100
saveToPersistenceRequest.payload.value
101101
)
102102
}
103103

104-
Scope.project -> {
104+
JCefPersistenceScope.project -> {
105105
JCEFProjectPersistence.getInstance(project).set(
106106
saveToPersistenceRequest.payload.key,
107107
saveToPersistenceRequest.payload.value

src/main/kotlin/org/digma/intellij/plugin/ui/tests/TestsUpdater.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,14 @@ class TestsUpdater(private val project: Project) : Disposable {
7171
}
7272

7373
try {
74-
var spanCodeObjectIds: Set<String> = setOf()
75-
if (scope.spanCodeObjectId.isNotEmpty())
76-
spanCodeObjectIds = setOf(scope.spanCodeObjectId)
7774

75+
val spanCodeObjectId = scope.spanCodeObjectId
76+
if (spanCodeObjectId.isEmpty()) {
77+
Log.log(logger::warn, "updateTestsData was called but scope.spanCodeObjectId is null or empty")
78+
return
79+
}
80+
81+
val spanCodeObjectIds = setOf(spanCodeObjectId)
7882
val testsOfSpanJson = project.service<TestsService>()
7983
.getLatestTestsOfSpan(TestsScopeRequest(spanCodeObjectIds, scope.methodId, null), lastKnownFilterForLatestTests)
8084
Log.log(logger::trace, project, "got tests of span {}", testsOfSpanJson)

ui-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
13.0.0
1+
14.2.4

0 commit comments

Comments
 (0)