Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution] JSON diff view PoC #171750

Closed

Conversation

nikitaindik
Copy link
Contributor

@nikitaindik nikitaindik commented Nov 22, 2023

Ticket: #169160

Summary

Scherm­afbeelding 2023-11-27 om 14 23 04

Comparing different libraries for showing text diffs.

About the libs

react-diff-viewer-continued

GitHub stars: 65
Weekly downloads: 55,000
Bundle size: 46kB (min), 16kb (min + gzip)

It's fork of a popular lib that was abandoned by its maintainer. The original version doesn't work in our project because it relies on old versions of emotion packages. The fork has more up-to-date dependencies and works with our version of emotion.

Pros:

  • Does what we want (out of the box)
  • Very easy to use API (diffs are passed as 2 strings, diffing algorithm is passed a prop)
  • Comes with batteries included (expandable diff sections, diffing algorithms)
  • Customisable (can use custom components and styles)

Cons: The original project is abandoned. Right now the fork doesn't seem to have a lot of dev activity going on and I couldn't find any info about future plans.

react-diff-view

GitHub stars: 743
Weekly downloads: 18,000
Bundle size: 71kB (min), 22kb (min + gzip)

Very customisable, but requires DIY work to be useful. You can't pass your diff as two strings - you have to do a number of conversions first. You can check my comments in code to understand what's going on more quickly. Development is not very active, but the author seems to be preparing a new major version.

Pros:

  • Does what we want (but I had to add a custom plugin for word-level diffing)
  • Very customisable (can use custom components and styles + some other stuff like widgets and custom events which we probably won't need)

Cons:

  • Requires custom code to be useful
  • Requires a separate library called "unidiff". It's a small library that converts "before" and "after" strings to a single "unified diff" formatted string.
  • Documentation is limited. There's a usage example, but it's not very easy to understand.

@kbn/monaco

GitHub stars: 36,400
Weekly downloads: 842,794
Bundle size (main package): 110kB (min), 18kb (min + gzip)
Bundle size (react-monaco-editor): 5kB (min), 1kb (min + gzip)

Code editor developed by Microsoft that powers VSCode. It has a diff mode, the same as you see in VSCode. You can even merge sections of diff using arrow buttons (not our use case, of course).

Pros:

  • Very robust, very well maintained, not going away anytime soon
  • We use it in Kibana already (@kbn/monaco)

Cons:

  • It's a big, full-fledged text-editor, definitely an overkill for our use case
  • Diffing functionality is there but customisation is limited (even styling is limited)
  • Couldn't find a way to do diffing by word

diff2html

Not customisable. Not very reacty - generates an HTML string that you insert via dangerouslySetInnerHTML:

<div dangerouslySetInnerHTML={{ __html: diffHtml }} />

Cons:

  • Very basic, not customisable, doesn't do what we want

Application Experience Team PoC

Davis from the Application Experience Team made a very nice-looking PoC for a feature that didn't end up on their roadmap. No plans to prioritise it for now, so the PR is still in draft. You can check this video to see it in action.

demo_json.mp4

It's simple and good-looking but very barebones for our use case: no split view and expandable / hidden code sections, for example.

@nikitaindik nikitaindik force-pushed the json-diffs-prebuilt-rules branch from 90a09e3 to e4761fb Compare November 27, 2023 16:12
@nikitaindik nikitaindik force-pushed the json-diffs-prebuilt-rules branch from 95ccaf4 to be5cad2 Compare November 27, 2023 18:04
import type { RuleFieldsDiff } from '../../../../../common/api/detection_engine/prebuilt_rules/model/diff/rule_diff/rule_diff';
import type { RuleResponse } from '../../../../../common/api/detection_engine/model/rule_schema/rule_schemas.gen';

const HIDDEN_FIELDS = ['meta', 'rule_schedule', 'version'];
Copy link
Contributor

Choose a reason for hiding this comment

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

I know it's not relevant for the POC, but curious why rule_schedule is hidden here? The rule schedule can be updated by the TRADE team (and later on customzied by the user)

const mergedVersion: string = get(fields, [fieldName, 'merged_version'], '');

const oldSource =
compareMethod === DiffMethod.JSON && typeof currentVersion === 'object'
Copy link
Contributor

Choose a reason for hiding this comment

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

currentVersion will always be a string so this always evaulates to JSON.stringify(currentVersion, null, 2). Same in the calculation of newSource

import { isDelete, isInsert, isNormal, pickRanges } from 'react-diff-view';
import type { ChangeData, HunkData, RangeTokenNode, TokenizeEnhancer } from 'react-diff-view';

interface JsDiff {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could be refactored like:

type StringDiffFn = (oldStr: string, newStr: string) => Change[];

type JsonDiffFn = (
  oldObject: Record<string, unknown>,
  newObject: Record<string, unknown>
) => Change[];

interface JsDiff {
  diffChars: StringDiffFn;
  diffWords: StringDiffFn;
  diffWordsWithSpace: StringDiffFn;
  diffLines: StringDiffFn;
  diffTrimmedLines: StringDiffFn;
  diffSentences: StringDiffFn;
  diffCss: StringDiffFn;
  diffJson: JsonDiffFn;
}

Comment on lines +241 to +217
isInsert: true,
lineNumber: 14,
type: "insert"
Copy link
Contributor

@jpdjere jpdjere Nov 28, 2023

Choose a reason for hiding this comment

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

I think these 3 properties live within the changes object, which is a sibling of content?

Comment on lines 138 to 146
<Unfold
direction="down"
start={collapsedStart}
end={collapsedStart + 10}
onExpand={onExpand}
/>
<Unfold direction="none" start={collapsedStart} end={collapsedEnd} onExpand={onExpand} />
<Unfold direction="up" start={collapsedEnd - 10} end={collapsedEnd} onExpand={onExpand} />
</>
Copy link
Contributor

@jpdjere jpdjere Nov 28, 2023

Choose a reason for hiding this comment

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

Not sure here if this is the best UX. While I think it's helpful to be able to expand 10 lines down, 10 lines up or all collapsed lines, my first reaction when I saw how it looks was a little confused:
image
Wondering if displaying only the "Expand hidden 38 lines" is clearer when there are no other changes in the hidden lines. But would like to know what the team thinks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree. I also found it a bit confusing, but I decided to leave it there for the PoC to show that a possibility to show a bit more exists in case someone might find it useful. But yeah, I also vote for having only "Expand 38 lines".

Copy link
Contributor

@jpdjere jpdjere left a comment

Choose a reason for hiding this comment

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

@nikitaindik Thanks for this great effort! The diffing component looks great and covers everything we need for this phase and pretty sure for all requirements we will have on Phase 3 as well.

From my review of the alternatives, and the discussion we had synchronously, my conclusions are:

  • app-experience-team and diff2html: discarded since they don't satisfy all our requirements.
  • react-diff-viewer-continued: since with react-diff-view we can achieve all the same results (albeit with more manual work, less out of the box features) I'd discard this option in favour of react-diff-view.

So for me, it boils down to react-diff-view vs monaco:

  • one of the main reasons we were doubting to use monaco was its potential bundle size, but the PR's description shows that for react-diff-view it's 22kb zipped, while the combined size for the two bundles needed for monaco is 19kb, zipped.
  • monaco is used already in a number of parts of the Kibana application, so it's a proved solution (although not used for diffing functionality, yet)
  • react-diff-view indeed seems to be more flexible and we can achieve results that monaco can't. The most notable for me:
    • styling: monaco seems very unflexible with this (not sure if changing styles is possible though) and the POC shows that react-diff-view allows basically any styling choices that we want. If we decide to go with monaco I think we should communicate this to Product/Design and get them to compromise - I think the styles monaco uses are acceptable.
    • tokenizing: in the POC we couldn't get monaco to tokenize by word, and some diffs might look a little off this way. For example, comparing tags, there's no point in knowing that "Defense Evasion" shares the "D" with "Data Source: Elastic Endgame".
      image react-diff-view even allows us to select the diffing algorithm and switch between them. Having said that, I consider the choosing of the diff algorithm a nice-to-have and don't consider the way that monaco displays diffs a deal-breaker at all. Especially considering that the react-diff-view's diffing algorithms had to be coded manually.
    • unchanged lines collapse/expansion: here both libs seems to follow quite a distinct philosophy. With react-diff-view we collapse sections of the rule with no changes and have the "Expand N lines" clickable buttons to expand it. monaco shows all content by default, which could not be the best UX for particularly long files. I think, however, that this "painpoint" is greatly reduced through the filemap at the right (beside the scrollbar) which allows the user to see where the changes are, and to quickly scroll to them to review them (in way a dev can be used to do when checking for changes/reviewing PRs in VSCode)
    • alignment of properties: I feel Monaco does a better job here keeping the properties aligned side by side, and prefer the way it fills empty space with the crossed-gray lines. For example, compare how the diff for description and false_positives are handled in monaco vs react-diff-view:
      image image Also, Monaco keeps the name and note props better aligned when meta is removed:
      image
      image
    • use as editable field: thinking ahead here, but for Phase 3 we have to think about giving the users the ability to edit rule fields. Unsure here how much effort it would take to adapt react-diff-view if we wanted to make it editable (we can always fallback to a normal editable EUI component), but monaco will do that out of the box, and could potentially be less design breaking to have all columns in the three way diff component done with the same library.

All in all, I'm favouring the use of monaco here, especially considering the effort required to use react-diff-view and the pretty tight deadline we have for FF 8.12 (I think if we went for the react-diff-view option, it should be created as a package that we import).

Looking forward to the teams opinion though.

@nikitaindik
Copy link
Contributor Author

Thanks for checking this out @jpdjere! Here's what I know about Monaco styling and word diffing.

Monaco diffs styling is limited. You can only change background and border colors for added / removed sections and chars. Here's an example. And a full list of stylable properties. So no way to add the crossed-out effect, like we have in the designs.

Also Monaco doesn't support having different color stylings for different instances of monaco-editor. Once you apply it to one instance, it also applies to others. I wonder if it may cause unwanted styling of other monacos in Kibana. Also it seems that in many scenarios monaco doesn't handle multiple instances correctly. There are many related issues on GitHub, like 1, 2, 3.

Theoretically there is a possibility to add word-diffing to Monaco. There's a way to write a diffing plugin, but there are no docs for this and you'll have to work with monaco / VSCode specific objects, not plain strings. I couldn't find any ready npm package that does this or any example of someone actually doing this successfully.

Copy link
Contributor

@banderror banderror left a comment

Choose a reason for hiding this comment

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

Visualizing changes in the MITRE ATT&CK (threat) rule field

Hey @nikitaindik, I did some local testing and would like to share something.

I installed the Linux Restricted Shell Breakout via Linux Binary(s) prebuilt rule. Its rule_id is 52376a86-ee86-4967-97ae-1a05f55816f0.

I called the rule patch endpoint against it with the following request body:

{
	"id": "716c682f-287a-45af-b6b7-2556655847f4",
	"name": "Linux Restricted Shell Breakout via Linux Binary(s) (UPDATED)",
	"version": 109,
	
	"tags": [
		"Domain: Endpoint",
		"OS: Linux",
		"Use Case: Threat Detection",
		"Tactic: Execution",
		"Data Source: Elastic Defend (RENAMED)",
		"Some: New Tag"
	],
	
	"severity": "high",
	"risk_score": 77,
	
	"query": "process where host.os.type == \"linux\" and event.type == \"start\"",
	
	"threat": [
		{
			"framework": "MITRE ATT&CK",
			"tactic": {
				"id": "TA0002",
				"name": "Execution",
				"reference": "https://attack.mitre.org/tactics/TA0002/"
			},
			"technique": [
				{
					"id": "T1059",
					"name": "Command and Scripting Interpreter",
					"reference": "https://attack.mitre.org/techniques/T1059/"
				}
			]
		}
	]
}

This request removes a MITRE subtechnique from the threat structure.

The only implementation that could visualize the diff properly was the react-diff-viewer-continued with the JSON diff algorithm:

Screenshot 2023-11-29 at 00 05 21 Screenshot 2023-11-29 at 00 05 48

All the other implementations show the threat field as an array having a single empty object inside. @nikitaindik do you have an idea why it works like that? Can other implementations show nested arrays and objects correctly?

react-diff-viewer-continued:
Screenshot 2023-11-29 at 00 07 53

react-diff-view:
Screenshot 2023-11-29 at 00 08 13

monaco:
Screenshot 2023-11-29 at 00 08 51

@banderror
Copy link
Contributor

As soon as I open the app-experience-team-poc tab, it breaks the styles of the timeline component in the footer:

Screenshot 2023-11-29 at 00 49 34

@nikitaindik nikitaindik force-pushed the json-diffs-prebuilt-rules branch from 5e9b29e to a450270 Compare November 29, 2023 01:11
@nikitaindik
Copy link
Contributor Author

Visualizing changes in the MITRE ATT&CK (threat) rule field

Hey @nikitaindik, I did some local testing and would like to share something.

I installed the Linux Restricted Shell Breakout via Linux Binary(s) prebuilt rule. Its rule_id is 52376a86-ee86-4967-97ae-1a05f55816f0.

I called the rule patch endpoint against it with the following request body:

{
	"id": "716c682f-287a-45af-b6b7-2556655847f4",
	"name": "Linux Restricted Shell Breakout via Linux Binary(s) (UPDATED)",
	"version": 109,
	
	"tags": [
		"Domain: Endpoint",
		"OS: Linux",
		"Use Case: Threat Detection",
		"Tactic: Execution",
		"Data Source: Elastic Defend (RENAMED)",
		"Some: New Tag"
	],
	
	"severity": "high",
	"risk_score": 77,
	
	"query": "process where host.os.type == \"linux\" and event.type == \"start\"",
	
	"threat": [
		{
			"framework": "MITRE ATT&CK",
			"tactic": {
				"id": "TA0002",
				"name": "Execution",
				"reference": "https://attack.mitre.org/tactics/TA0002/"
			},
			"technique": [
				{
					"id": "T1059",
					"name": "Command and Scripting Interpreter",
					"reference": "https://attack.mitre.org/techniques/T1059/"
				}
			]
		}
	]
}

This request removes a MITRE subtechnique from the threat structure.

The only implementation that could visualize the diff properly was the react-diff-viewer-continued with the JSON diff algorithm:

Screenshot 2023-11-29 at 00 05 21 Screenshot 2023-11-29 at 00 05 48
All the other implementations show the threat field as an array having a single empty object inside. @nikitaindik do you have an idea why it works like that? Can other implementations show nested arrays and objects correctly?

react-diff-viewer-continued: Screenshot 2023-11-29 at 00 07 53

react-diff-view: Screenshot 2023-11-29 at 00 08 13

monaco: Screenshot 2023-11-29 at 00 08 51

@banderror Good catch! Apparently my simplistic approach to JSON sorting didn't handle nested arrays properly. That's what I used

JSON.stringify(jsObject, Object.keys(jsObject).sort(), 2);

Should be fixed now.

JSON sorting algorithm from "react-diff-viewer-continued" worked because unlike other algorithms it accepts objects (not strings) and sorts them under the hood.

@kibana-ci
Copy link
Collaborator

kibana-ci commented Nov 29, 2023

💔 Build Failed

Failed CI Steps

Test Failures

  • [job] [logs] Investigations - Security Solution Cypress Tests #3 / Ransomware Detection Alerts Ransomware in Timelines Renders ransomware entries in timelines table Renders ransomware entries in timelines table
  • [job] [logs] Serverless Security Cypress Tests #4 / Use Value list in exception entry Should use value list in exception entry, and validate deleting value list prompt Should use value list in exception entry, and validate deleting value list prompt

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
securitySolution 4669 4711 +42

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
cloudSecurityPosture 402.7KB 402.8KB +118.0B
discover 587.1KB 587.2KB +122.0B
kibanaReact 214.5KB 214.7KB +122.0B
securitySolution 13.0MB 13.3MB ⚠️ +252.4KB
securitySolutionServerless 330.5KB 336.8KB +6.3KB
total +259.1KB

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
securitySolutionServerless 41.7KB 41.7KB -1.0B

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @nikitaindik

Comment on lines +12 to +13
import type { Change } from 'diff';
import { diffLines } from 'diff';
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that the diff library is specified in dev dependencies in package.json. We should only use it in code if we move it to normal dependencies.

Screenshot 2023-11-29 at 00 32 08

original={sortAndStringifyJson(oldRule)}
value={sortAndStringifyJson(newRule)}
fullWidth={true}
height="500px"
Copy link
Contributor

Choose a reason for hiding this comment

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

Can it grow to the full available height in the flyout? Or consume as much height as needed?

Setting height="100%" doesn't work, and fixed 500px height doesn't look like something we could ship in production:

Screenshot 2023-11-29 at 01 28 59

Comment on lines +8 to +26
export const sortObject = (jsObject) => {
if (typeof jsObject !== 'object' || jsObject === null) {
return jsObject;
}

if (Array.isArray(jsObject)) {
return jsObject.map((item) => sortObject(item));
}

return Object.keys(jsObject)
.sort()
.reduce((sorted, key) => {
sorted[key] = sortObject(jsObject[key]);
return sorted;
}, {});
};

export const sortAndStringifyJson = (jsObject: Record<string, unknown>): string =>
JSON.stringify(sortObject(jsObject), null, 2);
Copy link
Contributor

Choose a reason for hiding this comment

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

@nikitaindik Thanks for fixing #171750 (comment) using this code.

I think we can remove this complexity by using https://www.npmjs.com/package/json-stable-stringify. It's a popular library and it's already used in Kibana.

This code works (just tested it with all the libraries in your branch):

import stringify from 'json-stable-stringify';

export const sortAndStringifyJson = (jsObject: Record<string, unknown>): string =>
  stringify(jsObject, { space: 2 });

@banderror
Copy link
Contributor

I created individual PRs - one PR per each library - to be able to compare:

  • The minimum amount of code that needs to be written and maintained (git diff size).
  • Loading performance of a diff (first render), subsequent re-renders.
  • Scrolling performance.
  • Changes in the bundle size (this can be calculated by CI and posted in a comment in the PR).

Here are the PRs:

@banderror
Copy link
Contributor

banderror commented Nov 29, 2023

Some pros and cons

react-diff-viewer-continued

#172122

Pros:

  • Simplicity. This is probably the most simple implementation out of all of them. The diff is small and could be reduced even more.
  • DX. It feels like everything we need is supported out of the box and packed in a very nice and simple interface.
  • Customizable styling.

Cons:

  • Probably not the most flexible option.
  • It's noticeably slower than any other implementation. Its rendering takes a percievable amount of time (more than 1 second on my laptop). How much time would it take, using it, to render diffs for all individual text-based rule fields, when we start working on Milestone 3?
  • It doesn't seem to be well maintained. Only 1 contributor + a few micro-contributors. If it gets abandoned, we'll need to migrate to another library.
  • It has just a couple of naive tests. Proper test coverage is missing.

react-diff-view

#172124

Pros:

  • Flexibility. Can do (almost?) the same diff algorithms/tokenization as react-diff-viewer-continued. Can be integrated with diff-match-patch. Can be extended with custom functionality.
  • Customizable styling.
  • Rendering performance feels good. I'd say on my laptop it feels like the fastest implementation out of all of them.

Cons:

  • Requires a lot of new dependencies in package.json.
  • Requires a lot of boilerplate code to be written. This code doesn't look simple and easily digestible by anyone.
  • It doesn't seem to be very actively maintained. Although there are 3 core contributors, updates are infrequent. Maybe it's just a mature library though, so frequent updates are not needed. However, if it gets abandoned, we'll need to migrate to another library.
  • Test coverage is completely missing.

Monaco editor

#172125

Pros:

  • Simplicity. The diff is really small.
  • The only industry-grade library out of all options. Well maintained, has a big tech company behind it. It's very unlikely that it will be abandoned any time soon.
  • Rendering performance is surprisingly not so bad as I'd have expected. However, scrolling the diff feels laggy a little bit.

Cons:

  • I still have concerns about rendering N monaco editors simultaneusly in the same view - one editor in diff mode for each text-based rule field. Such fields are: rule name, description, setup guide, investigation guide, etc. It would be an overkiil, would likely look wierd in terms of styles, and would likely be not great in terms of performance.
  • Styling is very limited.
  • Customization and flexibility are limited.
  • The packages/shared-ux/code_editor/code_editor.tsx component doesn't look to be designed and coded for showing read-only diffs. It was designed for editing in mind. Introducing such a dependency might lead to bugs in the future caused by owners of packages/shared-ux + would bring unnecessary code to be executed.

@dplumlee
Copy link
Contributor

dplumlee commented Nov 29, 2023

react-diff-view even allows us to select the diffing algorithm and switch between them. Having said that, I consider the choosing of the diff algorithm a nice-to-have and don't consider the way that monaco displays diffs a deal-breaker at all. Especially considering that the react-diff-view's diffing algorithms had to be coded manually.

I feel like choosing the diff algorithm might be more than just a nice-to-have. The char tokenizing for things that are just a string or regular text is pretty straight forward to see and deal with but when we have super long query strings, it definitely doesn't help the readability especially compared to the word tokenizers in react-diff-viewer and react-diff-viewer-continued.

Here's some basic examples with a KQL query:

monaco
Screenshot 2023-11-28 at 10 13 12 PM
Screenshot 2023-11-28 at 10 13 22 PM

react-diff-viewer
Screenshot 2023-11-28 at 10 15 13 PM

I'll admit neither works perfectly in some of these scenarios (the dashes and slashes seem to confuse all the tokenizers) but in my opinion the words all being together helps with some cohesion in an already hard to read, long query string diff. How the react-query-diff design handles the look of a super long query string is also kind of wonky.

That being said, I agree with most of the pros for monaco @jpdjere and @banderror mentioned. I think we'd have to refine it a bit more out of the box (perhaps a bit easier said than done) and I would like to explore the possibility of adding a word and line tokenizer logic, but since our phase 1 is just JSON based, maybe that's something we can feasibly kick down the road to phase 2 when it's more needed

I also do like react-diff-view for it's customization features. Being able to align with our own designs and tokenizer of our choosing for different fields would be super nice. I do agree with what @banderror said about a lot of the boilerplate code in order to do that being pretty complicated and hard to digest. I wonder if we ended up trying to do the same with monaco, would we run into a similar issue.

For me the slowest library was react-diff-viewer-continued although I did like its out of the box features.

Overall, I probably agree with the decision being between monaco and react-diff-viewer. Something I think is important, especially considering the limited customization options of monaco, would be to get non-dev opinions on some of the options. I like the design of monaco and find it easy to read/understand for JSON and code but I also look at it almost every day in VS code.

Also thanks for putting this together @nikitaindik, this is an awesome hands on visualization!

@banderror
Copy link
Contributor

I feel like choosing the diff algorithm might be more than just a nice-to-have.

++ Agree with Davis, being able to show meaningful diffs for individual text-based fields will be very important from the UX perspective. Thank you for providing these screenshot examples @dplumlee!

@mbudge
Copy link

mbudge commented Dec 2, 2023

If this is for the pre-built rule upgrade workflow, wouldn’t it be easier to let users enter a list of fields which don’t get overwritten when they upgrade the enabled pre-built rules?

All customers need is a way to exclude fields like timestamp override, index pattern, data view and rule exceptions. Or when you do the upgrade you only update fields like the query (alerting logic), description, investigation guide etc.

If customers need to add filtering logic to the rule to reduce the number of alerts before the exception stage, add a new filtering section which can be copied between json objects.

Then it’s a simple case of copying the field from the previous json object to the new json object, or elastic only updating fields required to update alerting logic.

We just want elastic to manage the pre-built rules with as little work on our side as possible. In my view json diff is too complicated and something which could be works on as a long term objective.

Due to the complexity in the current method I could see it being hit by bugs when it’s released.

@mbudge
Copy link

mbudge commented Dec 4, 2023

I don't think you need a diff library for this.

Another option is take the key from the current rule and key from new rule, if key1 != key2 value ask the user if they want to update the value. It should be possible to iterate object keys in nodejs, even if they are child keys. Cache the keys from the current rule, and add any new keys from the new rule to the current rule json object.

@banderror
Copy link
Contributor

Hey @mbudge, thanks for your suggestions. The JSON diff we're working on is going to be readonly, and it will show what updates from Elastic will the user receive if they click "upgrade this prebuilt rule". This is a short-term feature to slightly improve the current rule upgrade UX.

Long-term, when we allow users to customize prebuilt rules, the UX for rule upgrades will be developed further and will not be based on interactive JSON diffs, so no complexity should be introduced for our users in that regard.

All customers need is a way to exclude fields like timestamp override, index pattern, data view and rule exceptions. Or when you do the upgrade you only update fields like the query (alerting logic), description, investigation guide etc.

This is an interesting suggestion, thank you for it. We will discuss it with our team members.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants