fluency-v8-components 1.6.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fluency-v8-components.es.js +16 -15
- package/dist/fluency-v8-components.umd.js +119 -115
- package/dist/{index-CS1vHSYo.mjs → index-BAGLjhJi.mjs} +10752 -10552
- package/dist/{index.es-I_IDoGTc.mjs → index.es-DW6Ls8hH.mjs} +1 -1
- package/package.json +1 -1
- package/src/assets/main.css +10 -6
- package/src/components/charts/TimelinePlot.vue +219 -0
- package/src/components/index.js +1 -0
- package/src/components/page-structure/FacetPage.vue +1 -1
- package/src/constants/fpl2.js +1 -1
package/package.json
CHANGED
package/src/assets/main.css
CHANGED
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
@utility std-light {
|
|
147
|
-
@apply bg-blue-
|
|
147
|
+
@apply bg-blue-100;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
@utility std-dark {
|
|
@@ -325,6 +325,10 @@
|
|
|
325
325
|
@apply w-10 h-10;
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
+
@utility link {
|
|
329
|
+
@apply text-blue-400 hover:underline;
|
|
330
|
+
}
|
|
331
|
+
|
|
328
332
|
@font-face {
|
|
329
333
|
font-family: "Open Sans";
|
|
330
334
|
src: url("/OpenSans-VariableFont_wdth,wght.ttf");
|
|
@@ -510,22 +514,22 @@
|
|
|
510
514
|
}
|
|
511
515
|
|
|
512
516
|
.chip {
|
|
513
|
-
@apply
|
|
517
|
+
@apply inline-flex items-center rounded-md px-2 py-1 font-medium ring-1 ring-inset;
|
|
514
518
|
}
|
|
515
519
|
.select-chip {
|
|
516
520
|
@apply px-1 text-sm font-medium rounded-full bg-sky-200 dark:bg-sky-700;
|
|
517
521
|
}
|
|
518
522
|
.green-chip {
|
|
519
|
-
@apply bg-green-
|
|
523
|
+
@apply bg-green-400/10 ring-green-500/20 text-green-400;
|
|
520
524
|
}
|
|
521
525
|
.red-chip {
|
|
522
|
-
@apply bg-red-
|
|
526
|
+
@apply bg-red-400/10 ring-red-500/20 text-red-400;
|
|
523
527
|
}
|
|
524
528
|
.yellow-chip {
|
|
525
|
-
@apply bg-yellow-
|
|
529
|
+
@apply bg-yellow-400/10 ring-yellow-500/20 text-yellow-400;
|
|
526
530
|
}
|
|
527
531
|
.blue-chip {
|
|
528
|
-
@apply bg-blue-
|
|
532
|
+
@apply bg-blue-400/10 ring-blue-500/20 text-blue-400;
|
|
529
533
|
}
|
|
530
534
|
|
|
531
535
|
.image-position-box {
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="col items-center">
|
|
3
|
+
<div class="text-center">
|
|
4
|
+
<span>{{ title }} Timeline ({{ total }} Events)</span>
|
|
5
|
+
</div>
|
|
6
|
+
<div ref="myplot" :class="['px-4', { 'pb-4': !props.flow }]"></div>
|
|
7
|
+
<div class="flex justify-end w-full mr-2">
|
|
8
|
+
<div ref="myplotLegend"></div>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup>
|
|
14
|
+
import { ref, watch } from "vue";
|
|
15
|
+
import * as d3 from "d3";
|
|
16
|
+
import * as Plot from "@observablehq/plot";
|
|
17
|
+
import { dateLocalTime } from "@/utils/timeUtils";
|
|
18
|
+
|
|
19
|
+
// props
|
|
20
|
+
const props = defineProps({
|
|
21
|
+
title: String,
|
|
22
|
+
buckets: Array,
|
|
23
|
+
total: Number,
|
|
24
|
+
from: Number,
|
|
25
|
+
to: Number,
|
|
26
|
+
flow: {
|
|
27
|
+
type: Boolean,
|
|
28
|
+
default: false,
|
|
29
|
+
},
|
|
30
|
+
width: {
|
|
31
|
+
type: Number,
|
|
32
|
+
default: 1200,
|
|
33
|
+
},
|
|
34
|
+
height: {
|
|
35
|
+
type: Number,
|
|
36
|
+
default: 300,
|
|
37
|
+
},
|
|
38
|
+
theme: {
|
|
39
|
+
type: String,
|
|
40
|
+
default: "light",
|
|
41
|
+
},
|
|
42
|
+
/** Key on each bucket for the risk score value (y-axis). Default "risk_score". */
|
|
43
|
+
valueKey: {
|
|
44
|
+
type: String,
|
|
45
|
+
default: "risk_score",
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
// states
|
|
49
|
+
const myplot = ref(null);
|
|
50
|
+
const myplotLegend = ref(null);
|
|
51
|
+
// watch for changes in data
|
|
52
|
+
watch([() => props.buckets], () => {
|
|
53
|
+
plotGraph();
|
|
54
|
+
});
|
|
55
|
+
watch([() => props.theme], () => {
|
|
56
|
+
plotGraph();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// function defs
|
|
60
|
+
function plotGraph() {
|
|
61
|
+
if (!props.buckets) return;
|
|
62
|
+
const valueKey = props.valueKey;
|
|
63
|
+
let options = {
|
|
64
|
+
marginTop: 30,
|
|
65
|
+
marks: [
|
|
66
|
+
Plot.frame(),
|
|
67
|
+
Plot.text(["No data available!"], { frameAnchor: "middle" }),
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
let marginLeft = 80;
|
|
71
|
+
let marginRight = 80;
|
|
72
|
+
|
|
73
|
+
if (props.buckets.length > 0) {
|
|
74
|
+
if (props.flow) {
|
|
75
|
+
const b = props.buckets;
|
|
76
|
+
|
|
77
|
+
// Left axis (flow) domain = max of rx/tx
|
|
78
|
+
const leftMax = Math.max(
|
|
79
|
+
1,
|
|
80
|
+
d3.max(b, (d) => Math.max(d?.rxHistogram?.value ?? 0, d?.txHistogram?.value ?? 0)) ?? 0
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Right axis (risk score) domain
|
|
84
|
+
const rightMax = Math.max(
|
|
85
|
+
1,
|
|
86
|
+
d3.max(b, (d) => d?.[valueKey] ?? 0) ?? 0
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const k = leftMax / rightMax;
|
|
90
|
+
const rightTicks = d3.ticks(0, rightMax, 5);
|
|
91
|
+
const leftTicks = d3.ticks(0, leftMax, 5);
|
|
92
|
+
|
|
93
|
+
options = {
|
|
94
|
+
x: { type: "time", label: "Time", tickSpacing: 100 },
|
|
95
|
+
y: {
|
|
96
|
+
label: "Flow",
|
|
97
|
+
domain: [0, leftMax],
|
|
98
|
+
},
|
|
99
|
+
grid: true,
|
|
100
|
+
marks: [
|
|
101
|
+
Plot.lineY(b, {
|
|
102
|
+
x: "key",
|
|
103
|
+
y: (d) => d?.rxHistogram?.value ?? 0,
|
|
104
|
+
strokeWidth: 2.5,
|
|
105
|
+
curve: "catmull-rom",
|
|
106
|
+
stroke: "#22c55e",
|
|
107
|
+
}),
|
|
108
|
+
Plot.lineY(b, {
|
|
109
|
+
x: "key",
|
|
110
|
+
y: (d) => d?.txHistogram?.value ?? 0,
|
|
111
|
+
strokeWidth: 2.5,
|
|
112
|
+
curve: "catmull-rom",
|
|
113
|
+
stroke: "#eab308",
|
|
114
|
+
}),
|
|
115
|
+
Plot.dotY(b, {
|
|
116
|
+
x: "key",
|
|
117
|
+
y: (d) => (d?.[valueKey] ?? 0) * k,
|
|
118
|
+
stroke: "#71b6e0",
|
|
119
|
+
strokeWidth: 3,
|
|
120
|
+
}),
|
|
121
|
+
Plot.axisY({
|
|
122
|
+
anchor: "left",
|
|
123
|
+
ticks: leftTicks.map((t) => t),
|
|
124
|
+
tickFormat: (_, i) => d3.format("~s")(leftTicks[i]) + "B",
|
|
125
|
+
label: "Bytes",
|
|
126
|
+
}),
|
|
127
|
+
Plot.axisY({
|
|
128
|
+
anchor: "right",
|
|
129
|
+
ticks: rightTicks.map((t) => t * k),
|
|
130
|
+
tickFormat: (_, i) => d3.format("~s")(rightTicks[i]),
|
|
131
|
+
label: "Risk Score",
|
|
132
|
+
}),
|
|
133
|
+
Plot.tip(
|
|
134
|
+
b,
|
|
135
|
+
Plot.pointerX({
|
|
136
|
+
x: "key",
|
|
137
|
+
y: (d) => (d?.[valueKey] ?? 0) * k,
|
|
138
|
+
fill: props.theme === "light" ? "white" : "black",
|
|
139
|
+
title: (d) =>
|
|
140
|
+
`Time: ${dateLocalTime(d.key)}\n` +
|
|
141
|
+
`rx: ${d?.rxHistogram?.value ?? 0}B (~${d3.format(".0s")(d?.rxHistogram?.value)}B)\n` +
|
|
142
|
+
`tx: ${d?.txHistogram?.value ?? 0}B (~${d3.format(".0s")(d?.txHistogram?.value)}B)\n` +
|
|
143
|
+
`Risk Score: ${Math.round(d?.[valueKey] ?? 0)}`,
|
|
144
|
+
})
|
|
145
|
+
),
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
} else {
|
|
149
|
+
const dataMax = d3.max(props.buckets, (d) => d?.[valueKey] ?? 0) ?? 0;
|
|
150
|
+
const maxRisk = dataMax > 0 ? Math.max(1, dataMax) : 500;
|
|
151
|
+
const allZeros = dataMax === 0;
|
|
152
|
+
const tickFormat = d3.format("d");
|
|
153
|
+
const widestTickLabel = tickFormat(maxRisk).toString();
|
|
154
|
+
marginLeft = Math.max(marginLeft, 24 + widestTickLabel.length * 8);
|
|
155
|
+
|
|
156
|
+
options = {
|
|
157
|
+
x: {
|
|
158
|
+
type: "time",
|
|
159
|
+
label: "Time",
|
|
160
|
+
tickSpacing: 100,
|
|
161
|
+
},
|
|
162
|
+
y: {
|
|
163
|
+
label: "Risk Score",
|
|
164
|
+
domain: [0, maxRisk],
|
|
165
|
+
tickFormat,
|
|
166
|
+
...(allZeros && { ticks: [0, 100, 200, 300, 400, 500] }),
|
|
167
|
+
},
|
|
168
|
+
grid: true,
|
|
169
|
+
marks: [
|
|
170
|
+
Plot.dotY(props.buckets, {
|
|
171
|
+
x: "key",
|
|
172
|
+
y: (d) => d?.[valueKey] ?? 0,
|
|
173
|
+
stroke: "#71b6e0",
|
|
174
|
+
strokeWidth: 3,
|
|
175
|
+
}),
|
|
176
|
+
Plot.tip(
|
|
177
|
+
props.buckets,
|
|
178
|
+
Plot.pointerX({
|
|
179
|
+
x: "key",
|
|
180
|
+
y: (d) => d?.[valueKey] ?? 0,
|
|
181
|
+
fill: props.theme === "light" ? "white" : "black",
|
|
182
|
+
title: (d) =>
|
|
183
|
+
`Time: ${dateLocalTime(d.key)}\nRisk Score: ${Math.round(d?.[valueKey] ?? 0)}`,
|
|
184
|
+
})
|
|
185
|
+
),
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const plot = Plot.plot({
|
|
192
|
+
marginLeft,
|
|
193
|
+
marginRight,
|
|
194
|
+
width: props.width,
|
|
195
|
+
height: props.height,
|
|
196
|
+
marginBottom: 50,
|
|
197
|
+
inset: 20,
|
|
198
|
+
style: {
|
|
199
|
+
fontSize: "16px",
|
|
200
|
+
backgroundColor: props.theme === "light" ? "white" : "#1a202c",
|
|
201
|
+
},
|
|
202
|
+
...options,
|
|
203
|
+
});
|
|
204
|
+
myplot.value.innerHTML = "";
|
|
205
|
+
myplot.value.appendChild(plot);
|
|
206
|
+
if (props.flow) {
|
|
207
|
+
const legend = Plot.legend({
|
|
208
|
+
color: {
|
|
209
|
+
type: "categorical",
|
|
210
|
+
domain: ["Received", "Sent", "Risk Score"],
|
|
211
|
+
range: ["#22c55e", "#eab308", "#71b6e0"],
|
|
212
|
+
},
|
|
213
|
+
swatchSize: 8,
|
|
214
|
+
});
|
|
215
|
+
myplotLegend.value.innerHTML = "";
|
|
216
|
+
myplotLegend.value.appendChild(legend);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
</script>
|
package/src/components/index.js
CHANGED
|
@@ -119,6 +119,7 @@ export { default as StackedChartClustered } from "./charts/StackedChartClustered
|
|
|
119
119
|
export { default as PieChart } from "./charts/PieChart.vue";
|
|
120
120
|
export { default as ProgressChart } from "./charts/ProgressChart.vue";
|
|
121
121
|
export { default as TimelineChart } from "./charts/TimelineChart.vue";
|
|
122
|
+
export { default as TimelinePlot } from "./charts/TimelinePlot.vue";
|
|
122
123
|
export { default as RangeSlider } from "./charts/RangeSlider.vue"
|
|
123
124
|
export { default as EmptyChart } from "./charts/EmptyChart.vue";
|
|
124
125
|
export { default as WorkflowChart } from "./charts/WorkflowChart.vue";
|
package/src/constants/fpl2.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Prism from "prismjs";
|
|
2
2
|
|
|
3
3
|
const builtinfunction =
|
|
4
|
-
/#?(?!\s)\b(?:Add|After|Aggregate|alert|anomaly|append|Append|AWS_AccountRegionLambda|AWS_AccountLambda|AWS_GetCostUsage|AWS_GetMetric|AWS_GetPrice|AWS_LoadAsset|base64Encode|base64Decode|Before|Clone|coalesce|ColumnAggregate|concat|contains|content|Cylance_AddGlobalList|Cylance_GetDevice|Cylance_GetThreatDevices|Cylance_GetThreatDownload|Cylance_GetThreatInfo|Cylance_LoadDevice|Cylance_LoadThreat|decoder_CEF|decoder_CSV|decoder_MixedKeyValue|decoder_QuotedKeyValue|DimensionTable|Each|Emit|endsWith|Error|Find|Filter|Fluency_BehaviorSearch|Fluency_Device_Add|Fluency_Device_Delete|Fluency_DeviceSearch|Fluency_Device_Lookup|Fluency_Device_LookupName|Fluency_Device_Update|Fluency_EntityinfoLookup|Fluency_FusionEvent|fluencyLavadbFpl|Fluency_LavadbQuery|Fluency_LavaLakeFpl|Fluency_ResourceLoad|Fluency_SummarySearch|Fluency_Tenant_Device_Add|Fluency_Tenant_Device_Delete|Fluency_Tenant_Device_Lookup|Fluency_Tenant_Device_LookupName|Fluency_Tenant_Device_Update|Format|geoip|GetColumnValues|GetEnv|GetKeys|GetRow|gzipCompress|gzipDecompress|htmlTemplate|indexOf|isEmpty|IsEmpty|isIPv4|isIPv6|ipNormalize|isNull|isNumber|isString|isUndef|isValidIP|Join|JoinStream|jsonClone|jsonTable|len|Limit|main|Map|match|mergeTable|NewColumns|NewColumnLambda|parseBool|parseFloat|parseInt|parseJson|Platform_Action|Platform_Action_Endpoint|Platform_Asset_Lookup|Platform_Asset_Refresh|Platform_Asset_Register|Platform_Cache_Check|Platform_Cache_Delete|Platform_Cache_DeRegister|Platform_Cache_Get|Platform_Cache_Register|Platform_Cache_Replace|Platform_Cache_Set|Platform_Cache_SetMultiple|Platform_Channel|Platform_DataObject_Delete|Platform_DataObject_Get|Platform_DataObject_Save|Platform_DataObject_Search|Platform_EntityinfoCheck|Platform_EntityinfoLookup|Platform_EntityProvider_Lookup|Platform_EntityProvider_Refresh|Platform_Grok_Add_Pattern|Platform_Grok_Check|Platform_Grok_Parse|Platform_Grok_Register|Platform_LoadComponent|Platform_Metric_Alert_Counter_Stop|Platform_Metric_Counter|Platform_Metric_Query|Platform_Metric_QueryBuild|Platform_Metric_QueryRange|Platform_Metric_Sort|Platform_Metric_Sort_Histogram|Platform_Notification_Email|Platform_Notification_PagerDuty|Platform_Notification_Slack|Platform_Notification_ServiceNow|Platform_PluginLambda|Platform_REST_Call|Platform_Sink|Platform_Site_GetInfo|Platform_Site_GetTenants|Platform_Site_LoadTenantComponent|pluginLambda|Plugin_Bitdefender_LoadEndpoint|Plugin_Falcon_GetHost|Plugin_Falcon_GetIncident|Plugin_Falcon_LoadHost|Plugin_Falcon_LoadIncident|Plugin_InControl_LoadClient|Plugin_InControl_LoadDevice|printf|Prom_Push_Counter|Prom_Push_Gauge|regexp|replace|replaceAll|ReplaceKey|RenameColumn|RemoveColumn|Round|run|RxFPL_GetMetric|setEnv|split|Some|Sort|sprintf|startsWith|SetColumnUnit|SetDimensions|SetTags|SetUnit|sleep|SummaryTable|subString|template|TimeTable|toLower|timezoneOffset|toUpper|transform|trim|trimPrefix|trimSuffix|typeof|Unix|UnixMilli|window)\b(?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/g;
|
|
4
|
+
/#?(?!\s)\b(?:Add|After|Aggregate|alert|anomaly|append|Append|AWS_AccountRegionLambda|AWS_AccountLambda|AWS_GetCostUsage|AWS_GetMetric|AWS_GetPrice|AWS_LoadAsset|base64Encode|base64Decode|Before|Clone|coalesce|ColumnAggregate|concat|contains|content|Cylance_AddGlobalList|Cylance_GetDevice|Cylance_GetThreatDevices|Cylance_GetThreatDownload|Cylance_GetThreatInfo|Cylance_LoadDevice|Cylance_LoadThreat|decoder_CEF|decoder_CSV|decoder_MixedKeyValue|decoder_QuotedKeyValue|DimensionTable|Each|Emit|endsWith|Error|Find|Filter|Fluency_BehaviorSearch|Fluency_Device_Add|Fluency_Device_Delete|Fluency_DeviceSearch|Fluency_Device_Lookup|Fluency_Device_LookupName|Fluency_Device_Update|Fluency_EntityinfoLookup|Fluency_FusionEvent|fluencyLavadbFpl|Fluency_LavadbQuery|fluencyLavaLakeFpl|Fluency_LavaLakeFpl|Fluency_ResourceLoad|Fluency_SummarySearch|Fluency_Tenant_Device_Add|Fluency_Tenant_Device_Delete|Fluency_Tenant_Device_Lookup|Fluency_Tenant_Device_LookupName|Fluency_Tenant_Device_Update|Format|geoip|GetColumnValues|GetEnv|GetKeys|GetRow|gzipCompress|gzipDecompress|htmlTemplate|indexOf|isEmpty|IsEmpty|isIPv4|isIPv6|ipNormalize|isNull|isNumber|isString|isUndef|isValidIP|Join|JoinStream|jsonClone|jsonTable|len|Limit|main|Map|match|mergeTable|NewColumns|NewColumnLambda|parseBool|parseFloat|parseInt|parseJson|Platform_Action|Platform_Action_Endpoint|Platform_Asset_Lookup|Platform_Asset_Refresh|Platform_Asset_Register|Platform_Cache_Check|Platform_Cache_Delete|Platform_Cache_DeRegister|Platform_Cache_Get|Platform_Cache_Register|Platform_Cache_Replace|Platform_Cache_Set|Platform_Cache_SetMultiple|Platform_Channel|Platform_DataObject_Delete|Platform_DataObject_Get|Platform_DataObject_Save|Platform_DataObject_Search|Platform_EntityinfoCheck|Platform_EntityinfoLookup|Platform_EntityProvider_Lookup|Platform_EntityProvider_Refresh|Platform_Grok_Add_Pattern|Platform_Grok_Check|Platform_Grok_Parse|Platform_Grok_Register|Platform_LoadComponent|Platform_Metric_Alert_Counter_Stop|Platform_Metric_Counter|Platform_Metric_Query|Platform_Metric_QueryBuild|Platform_Metric_QueryRange|Platform_Metric_Sort|Platform_Metric_Sort_Histogram|Platform_Notification_Email|Platform_Notification_PagerDuty|Platform_Notification_Slack|Platform_Notification_ServiceNow|Platform_PluginLambda|Platform_REST_Call|Platform_Sink|Platform_Site_GetInfo|Platform_Site_GetTenants|Platform_Site_LoadTenantComponent|pluginLambda|Plugin_Bitdefender_LoadEndpoint|Plugin_Falcon_GetHost|Plugin_Falcon_GetIncident|Plugin_Falcon_LoadHost|Plugin_Falcon_LoadIncident|Plugin_InControl_LoadClient|Plugin_InControl_LoadDevice|printf|Prom_Push_Counter|Prom_Push_Gauge|regexp|replace|replaceAll|ReplaceKey|RenameColumn|RemoveColumn|Round|run|RxFPL_GetMetric|setEnv|split|Some|Sort|sprintf|startsWith|SetColumnUnit|SetDimensions|SetTags|SetUnit|sleep|SummaryTable|subString|template|TimeTable|toLower|timezoneOffset|toUpper|transform|trim|trimPrefix|trimSuffix|typeof|Unix|UnixMilli|window)\b(?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/g;
|
|
5
5
|
|
|
6
6
|
const fpl2 = {
|
|
7
7
|
regex: Prism.languages.javascript.regex,
|