or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

celery-extension.mdcontext.mdindex.mdlogging.mdmiddleware.mdsentry-extension.md

logging.mddocs/

0

# Logging Integration

1

2

Log filters that automatically attach correlation IDs to log records, enabling seamless log correlation without manual ID injection. These filters integrate with Python's standard logging framework to automatically include tracking identifiers in all log output.

3

4

## Capabilities

5

6

### Correlation ID Filter

7

8

Logging filter that automatically attaches the current correlation ID to log records, making it available for formatting and output.

9

10

```python { .api }

11

class CorrelationIdFilter(logging.Filter):

12

"""

13

Logging filter to attach correlation IDs to log records.

14

15

Parameters:

16

- name: Filter name (default: '')

17

- uuid_length: Optional length to trim UUID to (default: None)

18

- default_value: Default value when no correlation ID exists (default: None)

19

"""

20

def __init__(

21

self,

22

name: str = '',

23

uuid_length: Optional[int] = None,

24

default_value: Optional[str] = None

25

): ...

26

27

def filter(self, record: LogRecord) -> bool:

28

"""

29

Attach a correlation ID to the log record.

30

31

Adds 'correlation_id' attribute to the log record containing:

32

- Current correlation ID from context variable

33

- Trimmed to uuid_length if specified

34

- default_value if no correlation ID exists

35

36

Parameters:

37

- record: Log record to modify

38

39

Returns:

40

- bool: Always True (never filters out records)

41

"""

42

```

43

44

The filter adds a `correlation_id` attribute to every log record, which can be used in log formatters:

45

46

```python

47

# In log format string

48

'%(levelname)s [%(correlation_id)s] %(name)s %(message)s'

49

50

# Results in output like:

51

# INFO [a1b2c3d4] myapp.views Processing user request

52

# ERROR [a1b2c3d4] myapp.models Database connection failed

53

```

54

55

### Celery Tracing IDs Filter

56

57

Logging filter that attaches both parent and current Celery task IDs to log records, enabling hierarchical task tracing.

58

59

```python { .api }

60

class CeleryTracingIdsFilter(logging.Filter):

61

"""

62

Logging filter to attach Celery tracing IDs to log records.

63

64

Parameters:

65

- name: Filter name (default: '')

66

- uuid_length: Optional length to trim UUIDs to (default: None)

67

- default_value: Default value when no IDs exist (default: None)

68

"""

69

def __init__(

70

self,

71

name: str = '',

72

uuid_length: Optional[int] = None,

73

default_value: Optional[str] = None

74

): ...

75

76

def filter(self, record: LogRecord) -> bool:

77

"""

78

Append parent and current ID to the log record.

79

80

Adds two attributes to the log record:

81

- 'celery_parent_id': ID of the process that spawned current task

82

- 'celery_current_id': Unique ID for the current task process

83

84

Both IDs are trimmed to uuid_length if specified, and use

85

default_value when the respective context variable is None.

86

87

Parameters:

88

- record: Log record to modify

89

90

Returns:

91

- bool: Always True (never filters out records)

92

"""

93

```

94

95

This filter enables detailed task tracing in log output:

96

97

```python

98

# In log format string

99

'%(levelname)s [%(celery_current_id)s|%(celery_parent_id)s] %(name)s %(message)s'

100

101

# Results in output like:

102

# INFO [task-abc123|req-xyz789] tasks.email Sending notification email

103

# ERROR [task-def456|task-abc123] tasks.data Task failed processing batch

104

```

105

106

## Usage Examples

107

108

### Basic Logging Setup

109

110

```python

111

import logging

112

from asgi_correlation_id import CorrelationIdFilter

113

114

# Configure logging with correlation ID

115

logging.basicConfig(

116

level=logging.INFO,

117

format='%(asctime)s %(levelname)s [%(correlation_id)s] %(name)s %(message)s'

118

)

119

120

# Add filter to root logger

121

correlation_filter = CorrelationIdFilter()

122

logging.getLogger().addFilter(correlation_filter)

123

124

# Use logging normally - correlation ID is automatically included

125

logger = logging.getLogger(__name__)

126

logger.info("This will include the correlation ID")

127

```

128

129

### Advanced Logging Configuration

130

131

```python

132

LOGGING = {

133

'version': 1,

134

'disable_existing_loggers': False,

135

'formatters': {

136

'detailed': {

137

'format': '%(asctime)s %(levelname)s [%(correlation_id)s] %(name)s:%(lineno)d %(message)s',

138

'datefmt': '%Y-%m-%d %H:%M:%S'

139

},

140

'simple': {

141

'format': '%(levelname)s [%(correlation_id)s] %(message)s'

142

},

143

},

144

'filters': {

145

'correlation_id': {

146

'()': 'asgi_correlation_id.CorrelationIdFilter',

147

'uuid_length': 8, # Trim to 8 characters

148

'default_value': 'no-id'

149

},

150

},

151

'handlers': {

152

'console': {

153

'class': 'logging.StreamHandler',

154

'formatter': 'detailed',

155

'filters': ['correlation_id'],

156

},

157

'file': {

158

'class': 'logging.FileHandler',

159

'filename': 'app.log',

160

'formatter': 'simple',

161

'filters': ['correlation_id'],

162

},

163

},

164

'loggers': {

165

'myapp': {

166

'handlers': ['console', 'file'],

167

'level': 'INFO',

168

'propagate': False,

169

},

170

},

171

}

172

173

import logging.config

174

logging.config.dictConfig(LOGGING)

175

```

176

177

### Celery Logging Setup

178

179

```python

180

import logging

181

from asgi_correlation_id import CeleryTracingIdsFilter

182

183

# Configure Celery task logging

184

celery_filter = CeleryTracingIdsFilter(uuid_length=8, default_value='none')

185

186

# Add to Celery logger

187

celery_logger = logging.getLogger('celery')

188

celery_logger.addFilter(celery_filter)

189

190

# Configure format to include both IDs

191

logging.basicConfig(

192

format='%(asctime)s [%(celery_current_id)s|%(celery_parent_id)s] %(name)s %(message)s'

193

)

194

```

195

196

### Combined HTTP and Celery Logging

197

198

```python

199

import logging

200

from asgi_correlation_id import CorrelationIdFilter, CeleryTracingIdsFilter

201

202

# Create filters

203

http_filter = CorrelationIdFilter(uuid_length=8, default_value='no-req')

204

celery_filter = CeleryTracingIdsFilter(uuid_length=8, default_value='no-task')

205

206

# Configure different loggers for different contexts

207

http_logger = logging.getLogger('webapp')

208

http_logger.addFilter(http_filter)

209

210

celery_logger = logging.getLogger('tasks')

211

celery_logger.addFilter(celery_filter)

212

213

# Set up formatters for each context

214

logging.basicConfig(

215

format='%(asctime)s %(name)s %(message)s'

216

)

217

218

# HTTP logs will show: 2023-01-01 12:00:00 webapp [a1b2c3d4] Processing request

219

# Celery logs will show: 2023-01-01 12:00:00 tasks [task-123|req-456] Running background job

220

```

221

222

## Filter Behavior

223

224

### UUID Length Trimming

225

226

When `uuid_length` is specified:

227

- UUIDs longer than the specified length are truncated

228

- UUIDs shorter than the specified length remain unchanged

229

- `None` values are handled gracefully

230

231

```python

232

# With uuid_length=8

233

filter = CorrelationIdFilter(uuid_length=8)

234

235

# "a1b2c3d4-e5f6-7890-abcd-ef1234567890" becomes "a1b2c3d4"

236

# "short" remains "short"

237

# None remains None (or uses default_value)

238

```

239

240

### Default Values

241

242

The `default_value` parameter provides fallback text when no correlation ID is available:

243

244

```python

245

filter = CorrelationIdFilter(default_value='no-correlation-id')

246

247

# When correlation_id.get() returns None:

248

# Log shows: INFO [no-correlation-id] myapp Processing request

249

```

250

251

## Types

252

253

```python { .api }

254

from logging import Filter, LogRecord

255

from typing import TYPE_CHECKING, Optional

256

257

if TYPE_CHECKING:

258

from logging import LogRecord

259

260

# Internal utility function

261

def _trim_string(string: Optional[str], string_length: Optional[int]) -> Optional[str]:

262

"""Trim string to specified length if provided."""

263

```