Skip to content

Commit 0ab14a0

Browse files
frankhcharlesviengithub-actions[bot]Copilot
authored
feat(logs): add live tailing functionality for logs (#42214)
Co-authored-by: Charles Vien <[email protected]> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <[email protected]>
1 parent 3ea0e7d commit 0ab14a0

File tree

16 files changed

+380
-16
lines changed

16 files changed

+380
-16
lines changed

bin/clickhouse-logs.sql

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ CREATE OR REPLACE TABLE logs31
3838
INDEX idx_attributes_str_values mapValues(attributes_map_str) TYPE bloom_filter(0.001) GRANULARITY 1,
3939
INDEX idx_mat_body_ipv4_matches mat_body_ipv4_matches TYPE bloom_filter(0.01) GRANULARITY 1,
4040
INDEX idx_body_ngram3 body TYPE ngrambf_v1(3, 25000, 2, 0) GRANULARITY 1,
41+
INDEX idx_observed_minmax observed_timestamp TYPE minmax GRANULARITY 1,
4142
PROJECTION projection_aggregate_counts
4243
(
4344
SELECT
@@ -180,6 +181,33 @@ mapSort(mapFilter((k, v) -> isNotNull(v), mapApply((k,v) -> (concat(k, '__float'
180181
mapSort(mapFilter((k, v) -> isNotNull(v), mapApply((k,v) -> (concat(k, '__datetime'), parseDateTimeBestEffortOrNull(JSONExtract(v, 'String'), 6)), attributes))) as attributes_map_datetime,
181182
mapSort(resource_attributes) as resource_attributes,
182183
toInt32OrZero(_headers.value[indexOf(_headers.name, 'team_id')]) as team_id
183-
FROM kafka_logs_avro;
184+
FROM kafka_logs_avro settings min_insert_block_size_rows=0, min_insert_block_size_bytes=0;
185+
186+
create or replace table logs_kafka_metrics
187+
(
188+
`_partition` UInt32,
189+
`_topic` String,
190+
`max_offset` SimpleAggregateFunction(max, UInt64),
191+
`max_observed_timestamp` SimpleAggregateFunction(max, DateTime64(9)),
192+
`max_timestamp` SimpleAggregateFunction(max, DateTime64(9)),
193+
`max_created_at` SimpleAggregateFunction(max, DateTime64(9)),
194+
`max_lag` SimpleAggregateFunction(max, UInt64)
195+
)
196+
ENGINE = MergeTree
197+
ORDER BY (_topic, _partition);
198+
199+
drop view if exists kafka_logs_avro_kafka_metrics_mv;
200+
CREATE MATERIALIZED VIEW kafka_logs_avro_kafka_metrics_mv TO logs_kafka_metrics
201+
AS
202+
SELECT
203+
_partition,
204+
_topic,
205+
maxSimpleState(_offset) as max_offset,
206+
maxSimpleState(observed_timestamp) as max_observed_timestamp,
207+
maxSimpleState(timestamp) as max_timestamp,
208+
maxSimpleState(now()) as max_created_at,
209+
maxSimpleState(now() - observed_timestamp) as max_lag
210+
FROM kafka_logs_avro
211+
group by _partition, _topic;
184212

185213
select 'clickhouse logs tables initialised successfully!';
462 Bytes
Loading
-6.89 KB
Loading

frontend/src/lib/lemon-ui/LemonTable/LemonTable.scss

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
@keyframes LemonTable__row__highlight__animation {
2+
0% {
3+
background-color: var(--color-accent-highlight-secondary);
4+
}
5+
6+
100% {
7+
background-color: transparent;
8+
}
9+
}
10+
111
.LemonTable {
212
--row-base-height: auto;
313
--row-horizontal-padding: 0.5rem;
@@ -163,6 +173,10 @@
163173
}
164174
}
165175

176+
&.LemonTable__row--status-highlight-new {
177+
animation: LemonTable__row__highlight__animation 1.5s ease-out;
178+
}
179+
166180
&:not(.LemonTable__expansion) {
167181
> td {
168182
// Make spacing of buttons tighter in tables by adding negative vertical margin

frontend/src/lib/lemon-ui/LemonTable/LemonTable.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ export interface LemonTableProps<T extends Record<string, any>> {
3232
/** Color to mark each row with. */
3333
rowRibbonColor?: string | ((record: T, rowIndex: number) => string | null | undefined)
3434
/** Status of each row. Defaults no status. */
35-
rowStatus?: 'highlighted' | ((record: T, rowIndex: number) => 'highlighted' | null)
35+
rowStatus?:
36+
| 'highlighted'
37+
| 'highlight-new'
38+
| ((record: T, rowIndex: number) => 'highlighted' | 'highlight-new' | null)
3639
/** Function that for each row determines what props should its `tr` element have based on the row's record. */
3740
onRow?: (record: T, index: number) => Omit<HTMLProps<HTMLTableRowElement>, 'key'>
3841
/** How tall should rows be. The default value is `"middle"`. */

frontend/src/lib/lemon-ui/LemonTable/TableRow.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export interface TableRowProps<T extends Record<string, any>> {
1414
rowKeyDetermined: string | number
1515
rowClassNameDetermined: string | null | undefined
1616
rowRibbonColorDetermined: string | null | undefined
17-
rowStatusDetermined: 'highlighted' | null | undefined
17+
rowStatusDetermined: 'highlighted' | 'highlight-new' | null | undefined
1818
columnGroups: LemonTableColumnGroup<T>[]
1919
onRow: ((record: T, index: number) => Omit<HTMLProps<HTMLTableRowElement>, 'key'>) | undefined
2020
expandable: ExpandableConfig<T> | undefined

frontend/src/lib/lemon-ui/icons/icons.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,19 @@ export function IconPlayCircle(props: LemonIconProps): JSX.Element {
11501150
)
11511151
}
11521152

1153+
export function IconPauseCircle(props: LemonIconProps): JSX.Element {
1154+
return (
1155+
<LemonIconBase {...props}>
1156+
<path
1157+
d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM12 20C7.59 20 4 16.41 4 12C4 7.59 7.59 4 12 4C16.41 4 20 7.59 20 12C20 16.41 16.41 20 12 20Z"
1158+
fill="currentColor"
1159+
/>
1160+
<rect x="9.5" y="8" width="2" height="8" rx="0.75" fill="currentColor" />
1161+
<rect x="12.5" y="8" width="2" height="8" rx="0.75" fill="currentColor" />
1162+
</LemonIconBase>
1163+
)
1164+
}
1165+
11531166
export function IconSkipBackward(props: LemonIconProps): JSX.Element {
11541167
return (
11551168
<LemonIconBase {...props}>

frontend/src/queries/schema.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17517,6 +17517,13 @@
1751717517
"level": {
1751817518
"$ref": "#/definitions/LogSeverityLevel"
1751917519
},
17520+
"live_logs_checkpoint": {
17521+
"format": "date-time",
17522+
"type": "string"
17523+
},
17524+
"new": {
17525+
"type": "boolean"
17526+
},
1752017527
"observed_timestamp": {
1752117528
"format": "date-time",
1752217529
"type": "string"
@@ -17602,6 +17609,9 @@
1760217609
"limit": {
1760317610
"$ref": "#/definitions/integer"
1760417611
},
17612+
"liveLogsCheckpoint": {
17613+
"type": "string"
17614+
},
1760517615
"modifiers": {
1760617616
"$ref": "#/definitions/HogQLQueryModifiers",
1760717617
"description": "Modifiers used when performing the query"

frontend/src/queries/schema/schema-general.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2574,6 +2574,9 @@ export interface LogMessage {
25742574
resource_attributes: any
25752575
instrumentation_scope: string
25762576
event_name: string
2577+
/** @format date-time */
2578+
live_logs_checkpoint?: string
2579+
new?: boolean
25772580
}
25782581

25792582
export interface LogsQuery extends DataNode<LogsQueryResponse> {
@@ -2586,6 +2589,7 @@ export interface LogsQuery extends DataNode<LogsQueryResponse> {
25862589
severityLevels: LogSeverityLevel[]
25872590
filterGroup: PropertyGroupFilter
25882591
serviceNames: string[]
2592+
liveLogsCheckpoint?: string
25892593
}
25902594

25912595
export interface LogsQueryResponse extends AnalyticsQueryResponseBase {

posthog/hogql/database/database.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
LogEntriesTable,
7272
ReplayConsoleLogsLogEntriesTable,
7373
)
74-
from posthog.hogql.database.schema.logs import LogsTable
74+
from posthog.hogql.database.schema.logs import LogsKafkaMetricsTable, LogsTable
7575
from posthog.hogql.database.schema.numbers import NumbersTable
7676
from posthog.hogql.database.schema.person_distinct_id_overrides import (
7777
PersonDistinctIdOverridesTable,
@@ -191,6 +191,7 @@ class Database(BaseModel):
191191
"document_embeddings": TableNode(name="document_embeddings", table=DocumentEmbeddingsTable()),
192192
"pg_embeddings": TableNode(name="pg_embeddings", table=PgEmbeddingsTable()),
193193
"logs": TableNode(name="logs", table=LogsTable()),
194+
"logs_kafka_metrics": TableNode(name="logs_kafka_metrics", table=LogsKafkaMetricsTable()),
194195
"numbers": TableNode(name="numbers", table=NumbersTable()),
195196
"system": SystemTables(), # This is a `TableNode` already, refer to implementation
196197
# Web analytics pre-aggregated tables (internal use only)

0 commit comments

Comments
 (0)