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

feat(api-logs): add the SeverityNumber enumeration #3443

Merged
merged 3 commits into from
Dec 21, 2022

Conversation

fuaiyi
Copy link
Contributor

@fuaiyi fuaiyi commented Nov 28, 2022

Background

Our company is also using OpenTelemetry standard for observability. I have been paying attention to the construction of OpenTelemetry, but I found that the Logs capability is not provided. so we developed the implementation of Logs by referring to the design standard. Recently, the community started developing Logs after the Metric stable release was completed. so I want to contribute the code that has been done with reference to the community's latest specifications and style, as well as the recent implementation of Logs in java, to build on and improve the capability of Logs. Accelerate the building of Logs capability so that developers like me can use the stable version of OpenTelemetry capability sooner rather than later. Welcome to participate in the CR and discussion.

We've done some capability development

  • api-logs
  • sdk-logs
  • exporter-logs-otlp-http

PR

Note: Because the amount of code submitted at one time is too large, I conducted PR several times. The PR content of this time is as follows (My colleague also submitted a full amount of code for your convenience: #3442)

api-logs

Module directory: experimental/packages/API - logs
Detail: in the process of development, it is found that the existing api-logs (v0.34.0) is inconsistent with the design standard and fails to meet part of the sdk capabilities, so a part of the code is reconstructed after referring to the design standard and java implementation. The main details are as follows:

  1. delete LogEvent
  2. Logger implements: emitLogRecord -> modification; getLogRecord; emitEvent -> getLogEvent
  3. LogRecord modification (I think the LogRecord in api should provide the corresponding method and configuration, rather than the specific data model, can refer to the implementation in Trace)
  4. implementation of NoopLogger
  5. add NoopLogRecord
  6. modify the unit test
  7. modify README

@fuaiyi fuaiyi requested a review from a team November 28, 2022 06:51
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Nov 28, 2022

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: fuaiyi / name: fuaiyi (7e8cc42)

@fuaiyi fuaiyi closed this Nov 28, 2022
@fuaiyi fuaiyi reopened this Nov 28, 2022
@fuaiyi fuaiyi changed the title refactor(api-logs): fefactor Logger api refactor(api-logs): refactor Logger api Nov 28, 2022
@fuaiyi fuaiyi closed this Nov 28, 2022
@fuaiyi fuaiyi reopened this Nov 28, 2022
@dyladan
Copy link
Member

dyladan commented Nov 29, 2022

/cc @martinkuba

@codecov
Copy link

codecov bot commented Nov 29, 2022

Codecov Report

Merging #3443 (64bc770) into main (faa0a33) will increase coverage by 0.02%.
The diff coverage is 100.00%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3443      +/-   ##
==========================================
+ Coverage   93.73%   93.75%   +0.02%     
==========================================
  Files         248      249       +1     
  Lines        7567     7593      +26     
  Branches     1581     1582       +1     
==========================================
+ Hits         7093     7119      +26     
  Misses        474      474              
Impacted Files Coverage Δ
...erimental/packages/api-logs/src/types/LogRecord.ts 100.00% <100.00%> (ø)

Copy link
Member

@dyladan dyladan left a comment

Choose a reason for hiding this comment

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

Took a quick pass here. In general it seems like there were some unnecessary architecture changes which weren't specified. Can you explain your motivation for these changes? Maybe i'm missing something that was decided in the log sig or spec.

*/
emitLogRecord(logRecord: LogRecord): void;
getLogRecord(options?: LogRecordOptions): LogRecord;
Copy link
Member

Choose a reason for hiding this comment

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

Why make this change? I don't see this specified anywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, there are a few main issues to consider here

  1. Consistency of style (major); Logger is used to create data in opentelemetry, such as: Meter.createCounter or Tracer.startSpan, both of which return a Span /Couter object, but the data is committed through span.end/couter.add. So Logger.getLogRecrd and LogRecord.emit are also assigned similar responsibilities
  2. User experience of developers; emit directly assembled data, can not provide developers with flexible Settings and modification capabilities, such as setAtributes and so on
  3. Of course, there is also a small reason to keep the same style with other languages. Here, I also refer to the implementation of opentelemtry-java (which has implemented the log api), and they also handle it in this way

image

Copy link
Contributor

Choose a reason for hiding this comment

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

I have originally proposed a similar shape of the API with createLogRecord() and createEvent() methods. But we decided to opt for a simpler API instead. This was discussed here.

I don't think we need to be consistent with the Tracer and Meter APIs, as those need to have two different calls while emitting logs does not. The only advantage would be to have methods like setAttribute() to build an instance of a LogRecord over time. But that's just a convenience, IMO. The counterargument is to have a simpler API, as most logging libraries do.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, thank you for your reply. I also considered it when I handled it before. I was struggling to decide whether to use a simpler api or keep the same trace/metric style. That is, consistency is a better priority, and now that we've discussed it here we'll use the solution that we've discussed, and I'm going to roll back that part of the code.

*/
emitEvent(event: LogEvent): void;
getLogEvent(eventName: string, options?: LogRecordOptions): LogEvent;
Copy link
Member

Choose a reason for hiding this comment

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

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Again, there's another reason for LogEvents:
LogEvent and LogRecord are a data structure. LogEvent only has two more attributes than LogRecord: event.name and event.domain. They return LogEvet and LogRecord objects, respectively, as shown in the standard design:
domain should be supported in LoggerProvider.getLogger instead of here. Here, only event.name is needed. https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/event-api.md (sorry, there is the recent changes, To separate the Event API from the previous one, commit: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/event-api.md), However, the design here is still consistent (I will pay attention to the changes here, and after this is combined with the design modification, I will submit a pr to split the event api, which has been consistent with the design).

import { LoggerProvider } from '../types/LoggerProvider';
import { _globalThis } from '../platform';
import type { LoggerProvider } from "../types/LoggerProvider";
import { _globalThis } from "../platform";
Copy link
Member

Choose a reason for hiding this comment

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

There are many places you decided to change just the quote for some reason. This strikes me as an autoformatter that you ran, but it really bloats the PR

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I took the time to do some formatting. If it is not needed, I will delete it here

Copy link
Member

Choose a reason for hiding this comment

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

Formatter enforcement has been enabled in #3444. Now the styles can be validated with GitHub Actions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, that's great. I'm just going to restore the format here

}

export type LogEvent = LogRecord;
Copy link
Member

Choose a reason for hiding this comment

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

Why

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As mentioned above, LogEvent and LogRecord are the same data model. LogEvent has two more attributes than LogRecod: name and domain, so LogEvent is LogRecord. This is mainly for readability, so that developers can distinguish between these two types. getLogRecord and getLogEvent in the Logger

@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 2, 2022

@dyladan @martinkuba
Please help to check whether this pr is ok, and if anything is inappropriate or needs to be changed, can add comments, I can change it in time , because the sdk and exporter's code is also in the back

@dyladan
Copy link
Member

dyladan commented Dec 7, 2022

I am going to try to discuss this in the SIG meeting today

@dyladan
Copy link
Member

dyladan commented Dec 7, 2022

I talked today with @martinkuba about this and I think we're in agreement that it doesn't really make sense to change the API to return a builder for a log record. For traces it makes sense because the span start and end are not expected to happen at the same time, but a log record or event is meant to represent a point in time. If you need to mutate a log record you can do so with a simple object and emit it when you are done building it. Languages like Java make this harder so they use builder patterns to get around that.

@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 8, 2022

Thanks for @dyladan and @martinkuba reply and discussion. I have removed part of the code about logger api, but there are still two parts of the code you can review

  1. Enumeration definition for SeverityNumber. I think the enumeration value should be defined in the api, just like Attributes, and the specification also explicitly defines the enumeration value:
  2. Regarding event.name and event.domain, these two attributes should not be defined in LogEvent, domain should be set in the options of getLogger method, not in emitEvent. And it's actually already defined in LoggerOptions. One parameter of emitEvent method should be eventName and the second parameter should be logRecord. LogRecord and LogEvent are the same data model. This part is also mentioned in the specification (sorry, there is the recent changes, separate the Event API from the previous one, the pr: Split out Event API from Log API opentelemetry-specification#2941, I will pay attention to the changes here, and after this is combined with the design modification, I will submit a pr to split the event api, which has been consistent with the design).

@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 12, 2022

@dyladan @martinkuba all the questions have been modified, please have time to check whether they can merge

@martinkuba
Copy link
Contributor

@fuaiyi My apologies for the delayed response. There have been a lot of discussions around the Logs/Events API, and my understanding is that there is a good chance the Events API might change again in the specification. Before we make more changes, I want to check with the Logs SIG about a couple of things...

I think you are correct that as written in the specification, the event domain can be specified only on the EventLogger, not individual events. Although I think originally it was allowed on individual events. I want to clarify whether overriding it on individual events is strictly forbidden.

I will also check how likely it is for the API specification to change again in the near future. I will follow up here with more guidance.

@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 15, 2022

@martinkuba Thanks for your reply, I think you are right, because the current logs specification is still in the experimental stage, it is unstable, and it will probably be modified in the future. My pr modification this time is mainly because I found this place difficult to deal with in the implementation of sdk, and it is not quite consistent with the current specification, so I made the modification. In addition, I have been very careful to refer to the implementation of other languages when revising, and I made the modification after confirming the consistency

But, I think it is normal that the future will be modified, but we need to have a complete implementation at present, and then if the specification is modified, we will do the iteration. We can't give up the support for the existing specification just because the future will be modified. Hope to reach a conclusion as soon as possible, thank you very much.

Finally, I am also very interested in logs. At present, my company is using otlp as the standard of observability, and I am also responsible for the construction of this section in my company. Hope to be able to participate in the construction of Logs. In the future, I will continue to pay attention to the construction and maintenance here, and make my own contribution to the community. @dyladan @martinkuba

@legendecas legendecas added the api:logs Issues and PRs related to the Logs API label Dec 15, 2022
*/
emitEvent(event: LogEvent): void;
emitEvent(eventName: string, logRecord: LogRecord): void;
Copy link
Member

Choose a reason for hiding this comment

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

Is it intended that this is LogRecord and not a different event type?

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 mentioned here in the specification. domain should be defined by Logger. It is recommended to use different loggers to manage different domian, and the eventName should be determined when submitting an event. its data model is LogRecrod too. So the entries here should be name and logrecord.
image
source: https://opentelemetry.io/docs/reference/specification/logs/event-api/

Copy link
Member

@legendecas legendecas Dec 20, 2022

Choose a reason for hiding this comment

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

With this change, I find that the domain is missing from the API, which should be necessary as part of the event API.

We don't have an EventLogger interface right now, which should provide a static method to create an EventLogger instance with a domain name. I believe we should address this as a whole so that we won't miss anything from the API.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, it seems like the domain is present in the LoggerOptions. It makes sense now.

Copy link
Member

@dyladan dyladan left a comment

Choose a reason for hiding this comment

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

Seems generally fine. This is now a much smaller change than when it was originally proposed

@dyladan
Copy link
Member

dyladan commented Dec 16, 2022

@martinkuba this has been pared down significantly and seems to just be handling some things like the log level enum. Want to take another look?

@fuaiyi fuaiyi changed the title refactor(api-logs): refactor Logger api feat(api-logs): add the SeverityNumber enumeration and refactor emitEvent api Dec 17, 2022
@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 20, 2022

@martinkuba take another look and see if it's OK? It's been a long time

Copy link
Member

@legendecas legendecas left a comment

Choose a reason for hiding this comment

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

The SeverityNumber part is LGTM and I believe it can land apart from the EventLogger modifications.

*/
emitEvent(event: LogEvent): void;
emitEvent(eventName: string, logRecord: LogRecord): void;
Copy link
Member

@legendecas legendecas Dec 20, 2022

Choose a reason for hiding this comment

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

With this change, I find that the domain is missing from the API, which should be necessary as part of the event API.

We don't have an EventLogger interface right now, which should provide a static method to create an EventLogger instance with a domain name. I believe we should address this as a whole so that we won't miss anything from the API.

*/
emitEvent(event: LogEvent): void;
emitEvent(eventName: string, logRecord: LogRecord): void;
Copy link
Member

Choose a reason for hiding this comment

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

Sorry, it seems like the domain is present in the LoggerOptions. It makes sense now.

@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 20, 2022

The SeverityNumber part is LGTM and I believe it can land apart from the EventLogger modifications.

@legendecas Thank you very much, but it seems that the approve running workflows needs to be started here. Can help start it?

@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 20, 2022

@dyladan @legendecas The approve workflow is ready , take another look, see if can merge ?

@martinkuba
Copy link
Contributor

The topic of the Events API was discussed in the last Log SIG. The recommendation is to separate it from the Logs API entirely, so that the Logs API can be stabilized independently. This was also the main driver for the current version of the Events API in the spec, where it really is just a syntactic sugar on top of the Logs API. We do not have to follow it strictly at this point. In fact, the recommendation from the SIG is to prototype an API that makes sense to us, and then bring it back to the group with a proposal.

As a result I propose the following:

  • separate the Events API into its own package
  • use the current form of the Events API as written now, and we can discuss changes to it in subsequent PRs (but my inclination is to not use the API as currently defined in the spec, for reasons I can explain later)
  • since the Events API will be separated, we can work on stabilizing the Logs API and implementing Logs SDK and exporters
  • work on the Events API can happen in parallel

As a result, I would reduce this PR just to the SeverityNumber addition. I can open a separate PR to separate the Events API, and then we can work from there. Does that sound reasonable?

@legendecas
Copy link
Member

  • separate the Events API into its own package

Regarding the packages, I'm inclined to have a single experimental package for each signal and merge them into the stable @opentelemetry/api package once they are stable. New experimental packages don't help here -- as the @opentelemetry/api-logs is already experimental anyways.

@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 21, 2022

The topic of the Events API was discussed in the last Log SIG. The recommendation is to separate it from the Logs API entirely, so that the Logs API can be stabilized independently. This was also the main driver for the current version of the Events API in the spec, where it really is just a syntactic sugar on top of the Logs API. We do not have to follow it strictly at this point. In fact, the recommendation from the SIG is to prototype an API that makes sense to us, and then bring it back to the group with a proposal.

As a result I propose the following:

  • separate the Events API into its own package
  • use the current form of the Events API as written now, and we can discuss changes to it in subsequent PRs (but my inclination is to not use the API as currently defined in the spec, for reasons I can explain later)
  • since the Events API will be separated, we can work on stabilizing the Logs API and implementing Logs SDK and exporters
  • work on the Events API can happen in parallel

As a result, I would reduce this PR just to the SeverityNumber addition. I can open a separate PR to separate the Events API, and then we can work from there. Does that sound reasonable?

The topic of the Events API was discussed in the last Log SIG. The recommendation is to separate it from the Logs API entirely, so that the Logs API can be stabilized independently. This was also the main driver for the current version of the Events API in the spec, where it really is just a syntactic sugar on top of the Logs API. We do not have to follow it strictly at this point. In fact, the recommendation from the SIG is to prototype an API that makes sense to us, and then bring it back to the group with a proposal.

As a result I propose the following:

  • separate the Events API into its own package
  • use the current form of the Events API as written now, and we can discuss changes to it in subsequent PRs (but my inclination is to not use the API as currently defined in the spec, for reasons I can explain later)
  • since the Events API will be separated, we can work on stabilizing the Logs API and implementing Logs SDK and exporters
  • work on the Events API can happen in parallel

As a result, I would reduce this PR just to the SeverityNumber addition. I can open a separate PR to separate the Events API, and then we can work from there. Does that sound reasonable?

Okay, so let's just include this enumeration.

I actually went to see the video from last week's SIG meeting, and there was a lot of discussion about the event api, but there were a few things that I thought were important:

  1. The form of event api still needs to be discussed and may be modified in the future. It is not recommended to provide it to the client directly for use
  2. Experimental things should not affect the progress of existing implementations, specifically mentioning that javascript is currently affected

Given the two things above, I think
We should implement basic logs capability as soon as possible. we can forget about the experimental stuff, or do an implementation based on an experimental version. Don't consider experimental changes until the implementation is complete. Because if we had stuck with the experimental changes, we might never have finished development because it was still talking about validation. (In fact, the Specification hadn't split the event api when I contributed the code.) This is also what Specification SIGs doesn't want, you think? @legendecas @dyladan @martinkuba

@fuaiyi fuaiyi reopened this Dec 21, 2022
@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 21, 2022

I have removed the part of the event api, leaving only the SeverityNumber enumeration. @legendecas @dyladan @martinkuba Take a look at it again, Hope to merge soon. This pr is easy, but it's been almost a month

@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 21, 2022

  • separate the Events API into its own package

Regarding the packages, I'm inclined to have a single experimental package for each signal and merge them into the stable @opentelemetry/api package once they are stable. New experimental packages don't help here -- as the @opentelemetry/api-logs is already experimental anyways.

  • separate the Events API into its own package

Regarding the packages, I'm inclined to have a single experimental package for each signal and merge them into the stable @opentelemetry/api package once they are stable. New experimental packages don't help here -- as the @opentelemetry/api-logs is already experimental anyways.

Yes, I think so. The entire Logs are experimental in the specification. There is no need to separate a package to deal exclusively with the event api. The event api itself is also part of Logs

@martinkuba
Copy link
Contributor

  • separate the Events API into its own package

Regarding the packages, I'm inclined to have a single experimental package for each signal and merge them into the stable @opentelemetry/api package once they are stable. New experimental packages don't help here -- as the @opentelemetry/api-logs is already experimental anyways.

It is true that the Logs API is also experimental at this point. But separating the Events API would allow us to stabilize the Logs API independently of any discussions about events. This is also why it was split in the specification. We do not want folks to start implementing instrumentations that use the Events API that is not finalized yet. The Logs API is ok to use though.

I also think that it would be better to have the Events API not explicitly tied to LogRecord's, like it is now. The internal implementation can use the Logs SDK, but instrumentations should not have to know about that. This is obviously something that needs to be discussed more, but again splitting it into a separate package would allow us that flexibility.

@fuaiyi fuaiyi changed the title feat(api-logs): add the SeverityNumber enumeration and refactor emitEvent api feat(api-logs): add the SeverityNumber enumeration Dec 21, 2022
@fuaiyi fuaiyi mentioned this pull request Dec 21, 2022
4 tasks
@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 21, 2022

The topic of the Events API was discussed in the last Log SIG. The recommendation is to separate it from the Logs API entirely, so that the Logs API can be stabilized independently. This was also the main driver for the current version of the Events API in the spec, where it really is just a syntactic sugar on top of the Logs API. We do not have to follow it strictly at this point. In fact, the recommendation from the SIG is to prototype an API that makes sense to us, and then bring it back to the group with a proposal.

As a result I propose the following:

  • separate the Events API into its own package
  • use the current form of the Events API as written now, and we can discuss changes to it in subsequent PRs (but my inclination is to not use the API as currently defined in the spec, for reasons I can explain later)
  • since the Events API will be separated, we can work on stabilizing the Logs API and implementing Logs SDK and exporters
  • work on the Events API can happen in parallel

As a result, I would reduce this PR just to the SeverityNumber addition. I can open a separate PR to separate the Events API, and then we can work from there. Does that sound reasonable?

@legendecas @dyladan @martinkuba I have submitted a pr that has implemented the separation of the event api. Take a look and discuss the issues left over from this pr #3501. and can this pr be merged in first?

@dyladan
Copy link
Member

dyladan commented Dec 21, 2022

Yes. I just approved the tests to run and will merge this when it is complete

@fuaiyi
Copy link
Contributor Author

fuaiyi commented Dec 21, 2022

Yes. I just approved the tests to run and will merge this when it is complete

Yes, thank you very much, there was an error in markdown lint, I've already fixed it.

@dyladan dyladan merged commit 1c3af6c into open-telemetry:main Dec 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api:logs Issues and PRs related to the Logs API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants