0
# Core Context Management
1
2
Core context management provides the fundamental operations for creating, storing, and retrieving contextual information within applications. Context objects are immutable and form parent-child relationships when new values are added.
3
4
## Context Access
5
6
### Current Context
7
8
Retrieves the context associated with the current scope.
9
10
```java { .api }
11
static Context current();
12
```
13
14
Returns the context from the current thread's context storage. If no context has been attached, returns the root context.
15
16
**Usage Example:**
17
```java
18
// Get current context
19
Context currentCtx = Context.current();
20
21
// Check if a value exists
22
String userId = currentCtx.get(USER_ID_KEY);
23
if (userId != null) {
24
processUser(userId);
25
}
26
```
27
28
### Root Context
29
30
Returns the root context from which all other contexts derive.
31
32
```java { .api }
33
static Context root();
34
```
35
36
Generally you should use `Context.current()` instead. Only use root context when you need to explicitly disregard the current context.
37
38
**Usage Example:**
39
```java
40
// Start fresh with root context (rare usage)
41
Context rootCtx = Context.root();
42
Context newCtx = rootCtx.with(USER_ID_KEY, "admin");
43
```
44
45
## Value Storage and Retrieval
46
47
### Get Value
48
49
Retrieves a value stored in the context for the given key.
50
51
```java { .api }
52
<V> V get(ContextKey<V> key);
53
```
54
55
**Parameters:**
56
- `key` - The context key to look up
57
58
**Returns:** The value associated with the key, or `null` if not present
59
60
**Usage Example:**
61
```java
62
private static final ContextKey<String> REQUEST_ID_KEY = ContextKey.named("requestId");
63
64
Context context = Context.current();
65
String requestId = context.get(REQUEST_ID_KEY);
66
67
if (requestId != null) {
68
logger.info("Processing request: {}", requestId);
69
}
70
```
71
72
### Store Value
73
74
Creates a new context with the given key-value pair added.
75
76
```java { .api }
77
<V> Context with(ContextKey<V> key, V value);
78
```
79
80
**Parameters:**
81
- `key` - The context key to store the value under
82
- `value` - The value to store
83
84
**Returns:** A new Context containing the key-value pair
85
86
**Usage Example:**
87
```java
88
private static final ContextKey<User> USER_KEY = ContextKey.named("user");
89
90
// Create new context with user information
91
User currentUser = getCurrentUser();
92
Context contextWithUser = Context.current().with(USER_KEY, currentUser);
93
94
// Chain multiple values
95
Context enrichedContext = contextWithUser
96
.with(REQUEST_ID_KEY, "req-123")
97
.with(TENANT_KEY, "tenant-456");
98
```
99
100
### Store Implicit Context Values
101
102
Creates a new context with an implicit context keyed value.
103
104
```java { .api }
105
Context with(ImplicitContextKeyed value);
106
```
107
108
**Parameters:**
109
- `value` - An object implementing ImplicitContextKeyed
110
111
**Returns:** A new Context with the value stored
112
113
**Usage Example:**
114
```java
115
// Assuming TraceSpan implements ImplicitContextKeyed
116
TraceSpan span = tracer.spanBuilder("operation").startSpan();
117
Context contextWithSpan = Context.current().with(span);
118
```
119
120
## Context Activation
121
122
### Make Current
123
124
Makes this context the current context and returns a scope for cleanup.
125
126
```java { .api }
127
Scope makeCurrent();
128
```
129
130
**Returns:** A Scope that must be closed to restore the previous context
131
132
**Usage Example:**
133
```java
134
Context newContext = Context.current().with(USER_ID_KEY, "user123");
135
136
try (Scope scope = newContext.makeCurrent()) {
137
// Within this scope, Context.current() returns newContext
138
performOperation(); // This operation sees the new context
139
140
// Nested contexts work too
141
Context nestedContext = Context.current().with(OPERATION_KEY, "nested");
142
try (Scope nestedScope = nestedContext.makeCurrent()) {
143
performNestedOperation();
144
} // Nested context restored
145
146
} // Original context restored automatically
147
```
148
149
**Important Notes:**
150
- Always use try-with-resources to ensure proper cleanup
151
- Kotlin coroutine users should NOT use this method - use the opentelemetry-extension-kotlin library instead
152
- Breaking the scope closing rules may lead to memory leaks and incorrect scoping
153
154
## Context Chaining
155
156
Multiple context modifications can be chained together:
157
158
```java
159
// Chain multiple with() calls
160
Context enrichedContext = Context.current()
161
.with(USER_ID_KEY, "user123")
162
.with(REQUEST_ID_KEY, "req-456")
163
.with(TENANT_ID_KEY, "tenant789");
164
165
try (Scope scope = enrichedContext.makeCurrent()) {
166
// All three values are available
167
String userId = Context.current().get(USER_ID_KEY);
168
String requestId = Context.current().get(REQUEST_ID_KEY);
169
String tenantId = Context.current().get(TENANT_ID_KEY);
170
}
171
```
172
173
## Error Handling
174
175
Context operations are generally safe and do not throw exceptions:
176
177
- `get()` returns `null` for missing keys
178
- `with()` always returns a valid context
179
- `makeCurrent()` always returns a valid scope
180
181
```java
182
// Safe to call with any key
183
String value = Context.current().get(UNKNOWN_KEY); // Returns null
184
185
// Safe to store null values
186
Context ctxWithNull = Context.current().with(SOME_KEY, null);
187
```