Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tracing] Structured logging based on Span events #8583

Merged
merged 15 commits into from
Aug 18, 2020

Conversation

pujagani
Copy link
Contributor

@pujagani pujagani commented Jul 29, 2020

Description

The changes are related to issue #6694. Current implementation has structured logging in place, the changes provide additional context to the logs by encapsulating the information from span and events to logs by primarily logging events. This is the first iteration to make changes beginning with logging HTTP calls and database calls.

Changes below include:

  1. Add logging for events at INFO level as JSON in LoggingOptions.
  2. Update in event attribute datatypes to add arrays for String, Long, Double and Boolean.
  3. Standardise error events to match OpenTelemetry specification https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/exceptions.md.
  4. Instrument SpanWrappedHTTPHandler and TracedHTTPClient with events for logging.
  5. Instrument HandleSession, ReverseProxyHandler, JDBCBackedSessionMap and RedisBackedSessionMap with events for logging.
  6. Instrument DockerSessionFactory and DriverServiceSessionFactory with events for logging.
  7. Instrument LocalNode, LocalSessionMap, LocalDistributor. ProtocolConverter and GridStatusHandler with events for logging.

Motivation and Context

Span events can have attributes which can store all possible information for a particular operation. Leveraging the events, this information can be added to logs to provide rich contextual information in logs. This makes the debugging process easier. Rather than having multiple log statements for a single operation, event can be used to capture all possible context (including high-cardinality values) and used in logging.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • I have read the contributing document.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@pujagani pujagani marked this pull request as draft July 29, 2020 05:53
…ackedSession map and RedisBackedSessionMap.

Additional changes include:
- Disabling pretty printng in LoggingOptions for event JSON.
@pujagani pujagani marked this pull request as ready for review July 30, 2020 11:15
@pujagani pujagani changed the title [tracing] WIP - Structured logging based on Span events [tracing] Structured logging based on Span events Jul 30, 2020
SESSION_CAPABILITIES("session.capabilities"),
SESSION_URI("session.uri"),

DATABASE_STATEMENT ("db.statement"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These seems specific to the JDBC classes, and probably shouldn't be in the common keys.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are based on OpenTelemetry specification for databases and it is applicable to all SQL and NoSQL client calls.


package org.openqa.selenium.remote.tracing;

public enum AttributeKey {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's likely that we can't know all the possible keys in advance. An enum is a poor choice given this constraint, so it may be better to use an interface

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 , it is not possible to know keys in advance. AttributeKey enum is to store keys which are used repeatedly and which are part of OpenTelemetry specification, all attribute key do not need to be part of the enum. Do you still suggest to use an interface instead?

return new EventAttributeValue(value);
}

public static EventAttributeValue setValue(Long[] value) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer primitive types.

Copy link
Contributor Author

@pujagani pujagani Aug 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OpenTelemetry APIs for array attributes accepts boxes types so stuck to that.

attributeValue = value.getDoubleArrayValue();
break;
case BOOLEAN_ARRAY:
attributeValue = value.getBooleanArrayValue();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case statement makes me twitch. It's long, and it looks like a prime candidate to accidentally forget to extend if we add a new value type. At the least, I'd suggest making Attributes be aware of how to serialise itself to JSON, so you can do a map.put("attributes", event.getAttributes)

Copy link
Contributor Author

@pujagani pujagani Aug 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the concern expressed. However, the OpenTelemetry Attributes class stores a String key and AttributeValue value and in order to get the actual value from AttributeValue, it offers series of methods of based on the AttributeValue.Type. So this is the only way I am seeing to creating the attributeMap from Events, unless we extend Event. I will try and see how this can be made better.

Copy link
Contributor Author

@pujagani pujagani Aug 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially I considered extending either the Event or Attributes to add a method for Json serialisation of the attributes. After looking into the OTel classes, the Attributes implementation AutoValue_Attributes_ArrayBackedAttributes is final and cannot be extended. Same is applicable for Events implementation AutoValue_TimedEvent_RawTimedEvent. So we might be stuck with the switch case. Any suggestions on this front?

Map<String, Object> attributeMap = new HashMap<>();
attributes.forEach((key, value) -> {
Object attributeValue = null;
switch (value.getType()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed a default case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the exhaustive list of all the datatypes for event attributes, so any value that is passed will match one of the cases, hence no default case.

StringBuilder text = new StringBuilder();
try (JsonOutput json = JSON.newOutput(text).setPrettyPrint(false)) {
json.write(map);
text.append('\n');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀 Uhhh... Why? The logger will output everything on one line for us.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I passed the Json String as it is, it was pretty printing the Json, so this was added to disable the pretty printing and have the event log in one line.

Copy link
Member

@AutomatedTester AutomatedTester left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me but will wait for @shs96c to have a look

pujagani and others added 6 commits August 4, 2020 14:34
…tory with event logs.

- Alphabetize  EventAttributeValue Type enum
- Alphabetize  switch case in openTelemetrySpan
- Breakdown TracerTest into multiple test methods for Span event testing
- Add vargs to EventAttributeValue for array value types
…StatusHandler, LocalSessionMap and ProtocolConverter.
@AutomatedTester
Copy link
Member

I believe all comments have been addressed and will be merging on Tuesday morning if there are no further review comments.

@shs96c @diemol

@diemol
Copy link
Member

diemol commented Aug 17, 2020

Just a heads up, this PR touches some files that this #8513 one is also changing. I'd recommend merging the other one first and then solving the conflicts here afterwards.

@pujagani
Copy link
Contributor Author

Verified that the changes in #8513 have not impacted the changes here. It is working as intended. @AutomatedTester

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants