Skip to content

Commit 75cc19f

Browse files
pellaredCopilotlmolkova
authored
Update exception recording guidelines to not use span events (#3256)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Liudmila Molkova <neskazu@gmail.com>
1 parent 2e8f547 commit 75cc19f

6 files changed

Lines changed: 42 additions & 18 deletions

File tree

.chloggen/3256.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
change_type: deprecation
2+
component: exceptions
3+
note: Update exception recording guidelines to not use span events.
4+
issues: [3256]

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ these requirements:
9696

9797
- **Spans**: Set status to Error, populate `error.type`, set description when helpful
9898
- **Metrics**: Include `error.type` attribute for filtering and analysis
99-
- **Exceptions**: Record as span events or log records using SDK APIs
99+
- **Exceptions**: Record as log records
100100
- **Consistency**: Same `error.type` across spans and metrics for same operation
101101

102102
## Common Issues to Flag

AREAS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ their owners, related project (and project board) as well as its current status.
3939
| Semantic Conventions: Database | [semconv-db-approvers](https://github.com/orgs/open-telemetry/teams/semconv-db-approvers) | https://github.com/open-telemetry/community/blob/main/projects/completed-projects/database-client-semconv.md | https://github.com/orgs/open-telemetry/projects/73 | `area:db` | `inactive` | The SIG is inactive. Bugs and bugfixes are welcome. For substantial changes, follow the [new project process](https://github.com/open-telemetry/community/blob/main/project-management.md) |
4040
| Semantic Conventions: FaaS | [specs-semconv-maintainers](https://github.com/orgs/open-telemetry/teams/specs-semconv-maintainers) | https://github.com/open-telemetry/community/blob/main/projects/completed-projects/faas.md | N/A | `area:faas` | `inactive` | The SIG is inactive. Bugs and bugfixes are welcome. For substantial changes, follow the [new project process](https://github.com/open-telemetry/community/blob/main/project-management.md) |
4141
| Semantic Conventions: JVM | [semconv-jvm-approvers](https://github.com/orgs/open-telemetry/teams/semconv-jvm-approvers) | N/A | https://github.com/orgs/open-telemetry/projects/49 | `area:jvm` | `inactive` | The SIG is inactive. Bugs and bugfixes are welcome. For substantial changes, follow the [new project process](https://github.com/open-telemetry/community/blob/main/project-management.md) |
42-
| Semantic Conventions: Logs | [semconv-log-approvers](https://github.com/orgs/open-telemetry/teams/semconv-log-approvers) | N/A | N/A | `area:log`, `area:event`, `area:exception` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
42+
| Semantic Conventions: Logs | [semconv-log-approvers](https://github.com/orgs/open-telemetry/teams/semconv-log-approvers) | N/A | https://github.com/orgs/open-telemetry/projects/65 | `area:log`, `area:event`, `area:exception` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
4343
| Semantic Conventions: Mainframe | [sig-mainframe-approvers](https://github.com/orgs/open-telemetry/teams/sig-mainframe-approvers) | https://github.com/open-telemetry/community/blob/main/projects/mainframe.md | N/A | `area:mainframe`, `area:zos` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
4444
| Semantic Conventions: Profiling | [profiling-approvers](https://github.com/orgs/open-telemetry/teams/profiling-approvers) | N/A | N/A | `area:profile`, `area:pprof` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
4545
| Semantic Conventions: .NET | [semconv-dotnet-approver](https://github.com/orgs/open-telemetry/teams/semconv-dotnet-approver) | N/A | N/A | `area:dotnet`, `area:aspnetcore`, `area:signalr`, `area:kestrel` | `accepting_contributions`, `active` | SIG is driven by members of the .NET runtime team. Contributions are welcomed but must be aligned with the .NET runtime features/roadmap |

areas.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ areas:
191191
- name: "semconv-log-approvers"
192192
github: semconv-log-approvers
193193
project: "N/A"
194-
board: "N/A"
194+
board: "https://github.com/orgs/open-telemetry/projects/65"
195195
labels:
196196
- area:log
197197
- area:event

docs/exceptions/exceptions-spans.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ linkTitle: Spans
44

55
# Semantic conventions for exceptions on spans
66

7-
**Status**: [Stable][DocumentStatus]
7+
**Status**: [Deprecated][DocumentStatus]<br>
8+
Use [Semantic conventions for exceptions in logs](exceptions-logs.md) instead.
89

910
This document defines semantic conventions for recording application
1011
exceptions associated with spans.

docs/general/recording-errors.md

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ Individual semantic conventions are encouraged to provide additional guidance.
2020

2121
An operation SHOULD be considered as failed if any of the following is true:
2222

23-
- an exception is thrown by the instrumented method (API, block of code, or another instrumented unit)
24-
- the instrumented method returns an error in another way, for example, via an error code
23+
- an exception is thrown by the instrumented operation (API, block of code, or another instrumented unit)
24+
- the instrumented operation returns an error in another way, for example, via an error code
2525

2626
Semantic conventions that define domain-specific status codes SHOULD specify
2727
which status codes should be reported as errors by a general-purpose instrumentation.
@@ -83,12 +83,12 @@ include it if the operation succeeded.
8383

8484
## Recording exceptions
8585

86-
When an instrumented operation fails with an exception, instrumentation SHOULD record
87-
this exception as a [span event](/docs/exceptions/exceptions-spans.md) or a [log record](/docs/exceptions/exceptions-logs.md).
86+
When the instrumented operation failed due to an exception:
8887

89-
It's RECOMMENDED to use the `Span.recordException` API or logging library API that takes exception instance
90-
instead of providing individual attributes. This enables the OpenTelemetry SDK to
91-
control what information is recorded based on application configuration.
88+
- instrumentation SHOULD record this exception as a [log record](/docs/exceptions/exceptions-logs.md),
89+
- instrumentation SHOULD follow [recording errors on spans](#recording-errors-on-spans)
90+
and [recording errors on metrics](#recording-errors-on-metrics)
91+
on capturing exception details on these signals.
9292

9393
It's NOT RECOMMENDED to record the same exception more than once.
9494
It's NOT RECOMMENDED to record exceptions that are handled by the instrumented library.
@@ -100,22 +100,41 @@ to the caller should be recorded (or logged) once.
100100
```java
101101
public boolean createIfNotExists(String resourceId) throws IOException {
102102
Span span = startSpan();
103+
long startTime = System.nanoTime();
103104
try {
104105
create(resourceId);
106+
107+
recordMetric("acme.resource.create.duration", System.nanoTime() - startTime);
108+
105109
return true;
106110
} catch (ResourceAlreadyExistsException e) {
107-
// not recording exception and not setting span status to error - exception is handled
108-
// but we can set attributes that capture additional details
111+
// we do not set span status to error and the "error.type" attribute
112+
// as the exception is not an error,
113+
// but we still log and set attributes that capture additional details
114+
logger.withEventName("acme.resource.create.error")
115+
.withAttribute("acme.resource.create.status", "already_exists")
116+
.withException(e)
117+
.debug();
118+
109119
span.setAttribute(AttributeKey.stringKey("acme.resource.create.status"), "already_exists");
120+
121+
recordMetric("acme.resource.create.duration", System.nanoTime() - startTime);
122+
110123
return false;
111124
} catch (IOException e) {
112-
// recording exception here (assuming it was not recorded inside `create` method)
113-
span.recordException(e);
114-
// or
115-
// logger.warn(e);
125+
// this exception is expected to be handled by the caller
126+
// and could be a transient error
127+
logger.withEventName("acme.resource.create.error")
128+
.withException(e)
129+
.warn();
130+
131+
String errorType = e.getClass().getCanonicalName();
116132

117-
span.setAttribute(AttributeKey.stringKey("error.type"), e.getClass().getCanonicalName())
133+
span.setAttribute(AttributeKey.stringKey("error.type"), errorType);
118134
span.setStatus(StatusCode.ERROR, e.getMessage());
135+
136+
recordMetric("acme.resource.create.duration", System.nanoTime() - startTime,
137+
AttributeKey.stringKey("error.type"), errorType);
119138
throw e;
120139
}
121140
}

0 commit comments

Comments
 (0)