or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-processing.mderrors.mdfiltering.mdindex.mdtheming.md

filtering.mddocs/

0

# Filtering

1

2

Advanced filtering capabilities for selective processing of Eliot tasks based on various criteria. Filters work on the original Eliot message dictionaries before task parsing, enabling efficient selection using JMESPath queries, UUID matching, timestamp ranges, and logical combinations.

3

4

## Imports

5

6

```python

7

from datetime import datetime

8

from iso8601 import parse_date

9

```

10

11

## Capabilities

12

13

### JMESPath Query Filtering

14

15

Create filter functions using JMESPath query expressions to select tasks based on any field or condition in the original Eliot message structure.

16

17

```python { .api }

18

def filter_by_jmespath(query):

19

"""

20

Produce a function for filtering a task by a JMESPath query expression.

21

22

Parameters:

23

- query: str - JMESPath query string used as a predicate

24

25

Returns:

26

Callable[[dict], bool] - Filter function that returns True if task matches query

27

"""

28

```

29

30

**Usage Examples:**

31

32

```python

33

from eliottree import filter_by_jmespath

34

35

# Filter tasks containing a 'uri' field

36

uri_filter = filter_by_jmespath('uri')

37

38

# Filter by specific action type

39

http_filter = filter_by_jmespath('action_type == `"http_client:request"`')

40

41

# Filter by HTTP status codes

42

error_filter = filter_by_jmespath('contains(`[401, 500]`, status)')

43

44

# Complex filtering with multiple conditions

45

critical_filter = filter_by_jmespath(

46

'http_status == `401` && uri && contains(uri, `"/criticalEndpoint"`)'

47

)

48

49

# Apply filter to messages

50

filtered_tasks = [task for task in tasks if uri_filter(task)]

51

```

52

53

### UUID-Based Filtering

54

55

Filter entire task trees by their unique identifier, useful for isolating specific request flows or debugging particular operations.

56

57

```python { .api }

58

def filter_by_uuid(task_uuid):

59

"""

60

Produce a function for filtering tasks by their UUID.

61

62

Implementation note: This is implemented as a JMESPath wrapper that creates

63

a query equivalent to: task_uuid == `<uuid_value>`

64

65

Parameters:

66

- task_uuid: str - UUID string to match against task_uuid field

67

68

Returns:

69

Callable[[dict], bool] - Filter function for UUID matching

70

"""

71

```

72

73

**Usage Example:**

74

75

```python

76

from eliottree import filter_by_uuid

77

78

# Filter by specific task UUID

79

uuid_filter = filter_by_uuid("f3a32bb3-ea6b-457c-aa99-08a3d0491ab4")

80

81

# Apply filter

82

specific_tasks = [task for task in tasks if uuid_filter(task)]

83

```

84

85

### Timestamp-Based Filtering

86

87

Filter tasks based on their occurrence time using start and end date boundaries, enabling time-range analysis of log data.

88

89

```python { .api }

90

def filter_by_start_date(start_date):

91

"""

92

Produce a function for filtering by task timestamps after (or on) a certain date and time.

93

94

Parameters:

95

- start_date: datetime - Tasks must occur at or after this datetime

96

97

Returns:

98

Callable[[dict], bool] - Filter function for start date filtering

99

"""

100

101

def filter_by_end_date(end_date):

102

"""

103

Produce a function for filtering by task timestamps before a certain date and time.

104

105

Parameters:

106

- end_date: datetime - Tasks must occur before this datetime

107

108

Returns:

109

Callable[[dict], bool] - Filter function for end date filtering

110

"""

111

```

112

113

**Usage Examples:**

114

115

```python

116

from datetime import datetime

117

from iso8601 import parse_date

118

from eliottree import filter_by_start_date, filter_by_end_date

119

120

# Filter tasks after a specific time

121

start_time = parse_date("2015-03-03T04:28:00Z")

122

after_filter = filter_by_start_date(start_time)

123

124

# Filter tasks before a specific time

125

end_time = parse_date("2015-03-03T04:30:00Z")

126

before_filter = filter_by_end_date(end_time)

127

128

# Apply filters

129

recent_tasks = [task for task in tasks if after_filter(task)]

130

time_range_tasks = [task for task in tasks

131

if after_filter(task) and before_filter(task)]

132

```

133

134

### Logical Filter Combination

135

136

Combine multiple filter functions using logical AND operations to create sophisticated filtering criteria.

137

138

```python { .api }

139

def combine_filters_and(*filters):

140

"""

141

Combine several filters together in a logical-AND fashion.

142

143

Parameters:

144

- *filters: Variable number of filter functions

145

146

Returns:

147

Callable[[Any], bool] - Combined filter function that returns True only

148

if all input filters return True

149

"""

150

```

151

152

**Usage Examples:**

153

154

```python

155

from eliottree import (

156

filter_by_jmespath, filter_by_start_date, filter_by_end_date,

157

combine_filters_and

158

)

159

160

# Combine multiple filters

161

error_filter = filter_by_jmespath('http_status == `401`')

162

uri_filter = filter_by_jmespath('uri && contains(uri, `"/api"`)')

163

time_filter = filter_by_start_date(parse_date("2015-03-03T04:00:00Z"))

164

165

# Create combined filter

166

combined_filter = combine_filters_and(error_filter, uri_filter, time_filter)

167

168

# Apply combined filter

169

filtered_tasks = [task for task in tasks if combined_filter(task)]

170

```

171

172

## Complete Filtering Pipeline

173

174

```python

175

import json

176

from datetime import datetime

177

from iso8601 import parse_date

178

from eliottree import (

179

tasks_from_iterable, render_tasks, get_theme,

180

filter_by_jmespath, filter_by_start_date, combine_filters_and

181

)

182

183

def process_filtered_logs(log_file, start_time_str, action_type):

184

"""Process logs with multiple filtering criteria."""

185

186

# Load messages

187

with open(log_file, 'r') as f:

188

messages = [json.loads(line) for line in f]

189

190

# Create filters

191

time_filter = filter_by_start_date(parse_date(start_time_str))

192

action_filter = filter_by_jmespath(f'action_type == `"{action_type}"`')

193

194

# Combine filters

195

combined_filter = combine_filters_and(time_filter, action_filter)

196

197

# Apply filtering

198

filtered_messages = [msg for msg in messages if combined_filter(msg)]

199

200

# Process and render

201

tasks = tasks_from_iterable(filtered_messages)

202

theme = get_theme(dark_background=True)

203

render_tasks(sys.stdout.write, tasks, theme=theme)

204

205

# Usage

206

process_filtered_logs(

207

'eliot.log',

208

'2015-03-03T04:28:00Z',

209

'http_client:request'

210

)

211

```

212

213

## Filter Function Composition

214

215

Filters can be composed and reused for different analysis scenarios:

216

217

```python

218

# Define reusable filters

219

def create_error_filters():

220

return {

221

'http_errors': filter_by_jmespath('status >= `400`'),

222

'timeout_errors': filter_by_jmespath('contains(error_type || `""`, `"timeout"`)'),

223

'auth_errors': filter_by_jmespath('status == `401` || status == `403`'),

224

}

225

226

def create_time_range_filter(start_str, end_str):

227

start_filter = filter_by_start_date(parse_date(start_str))

228

end_filter = filter_by_end_date(parse_date(end_str))

229

return combine_filters_and(start_filter, end_filter)

230

231

# Usage

232

error_filters = create_error_filters()

233

time_range = create_time_range_filter('2015-03-03T04:00:00Z', '2015-03-03T05:00:00Z')

234

235

# Combine for specific analysis

236

auth_errors_in_range = combine_filters_and(

237

error_filters['auth_errors'],

238

time_range

239

)

240

```

241

242

## JMESPath Query Patterns

243

244

Common query patterns for Eliot log analysis:

245

246

```python

247

# Existence checks

248

filter_by_jmespath('uri') # Has URI field

249

filter_by_jmespath('error_message') # Has error message

250

251

# Exact matches

252

filter_by_jmespath('action_type == `"http_request"`')

253

filter_by_jmespath('status == `200`')

254

255

# Numeric comparisons

256

filter_by_jmespath('status >= `400`') # HTTP errors

257

filter_by_jmespath('duration > `5.0`') # Slow operations

258

259

# String operations

260

filter_by_jmespath('contains(uri, `"/api/"`)')

261

filter_by_jmespath('starts_with(action_type, `"db:"`)')

262

263

# Array operations

264

filter_by_jmespath('contains(`[401, 403, 500]`, status)')

265

filter_by_jmespath('length(task_level) > `2`')

266

267

# Complex conditions

268

filter_by_jmespath('status >= `400` && contains(uri, `"/critical"`)')

269

```