mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[github] Add reporting for rates used during requests
GitOrigin-RevId: 70db6715002f37965663a6960f23315eb96fd168
This commit is contained in:
committed by
intellij-monorepo-bot
parent
406980ad74
commit
e4e1e56b64
@@ -0,0 +1,3 @@
|
||||
fragment rates on RateLimit {
|
||||
cost
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
query($repoOwner: String!, $repoName: String!, $baseBranch: String, $headBranch: String) {
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequests(states: [OPEN], baseRefName: $baseBranch, headRefName: $headBranch, first: 1) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
...pullRequestInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
query($organization: String!, $pageSize: Int = 100, $cursor: String) {
|
||||
organization(login: $organization) {
|
||||
teams(first: $pageSize, after: $cursor) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
...teamInfo
|
||||
}
|
||||
}
|
||||
organization(login: $organization) {
|
||||
teams(first: $pageSize, after: $cursor) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
...teamInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,15 @@
|
||||
query($pullRequestId: ID!) {
|
||||
node(id: $pullRequestId) {
|
||||
... on PullRequest {
|
||||
reviews(states: [PENDING], first: 1) {
|
||||
nodes {
|
||||
...pullRequestPendingReview
|
||||
}
|
||||
}
|
||||
node(id: $pullRequestId) {
|
||||
... on PullRequest {
|
||||
reviews(states: [PENDING], first: 1) {
|
||||
nodes {
|
||||
...pullRequestPendingReview
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,8 @@ query($repoOwner: String!, $repoName: String!, $number: Int!) {
|
||||
...pullRequestInfo
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,8 @@ query($repoOwner: String!, $repoName: String!, $number: Int!) {
|
||||
number
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
query($repoOwner: String!, $repoName: String!, $number: Int!) {
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequest(number: $number) {
|
||||
...pullRequestMergeability
|
||||
}
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequest(number: $number) {
|
||||
...pullRequestMergeability
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
query($repoOwner: String!, $repoName: String!) {
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
...repository
|
||||
}
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
...repository
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,8 @@ query($login: String!) {
|
||||
__typename
|
||||
...userInfo
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
query($repoOwner: String!, $repoName: String!, $pageSize: Int = 100, $cursor: String) {
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
branchProtectionRules(first: $pageSize, after: $cursor) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
...nodeInfo
|
||||
pattern
|
||||
}
|
||||
}
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
branchProtectionRules(first: $pageSize, after: $cursor) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
...nodeInfo
|
||||
pattern
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,8 @@ query($repoOwner: String!, $repoName: String!) {
|
||||
body
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -35,4 +35,8 @@ query($repoOwner: String!, $repoName: String!, $oid: GitObjectID!, $pageSize: In
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -8,4 +8,8 @@ query($repoOwner: String!, $repoName: String!, $oid: GitObjectID!) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,8 @@ query issueSearch($query: String!, $pageSize: Int = 100, $cursor: String) {
|
||||
...pullRequestInfoShort
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,22 @@
|
||||
query($repoOwner: String!, $repoName: String!, $number: Int!, $pageSize: Int = 100, $cursor: String) {
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequest(number: $number) {
|
||||
commits(first: $pageSize, after: $cursor) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
...nodeInfo
|
||||
commit {
|
||||
...commit
|
||||
}
|
||||
url
|
||||
}
|
||||
}
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequest(number: $number) {
|
||||
commits(first: $pageSize, after: $cursor) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
...nodeInfo
|
||||
commit {
|
||||
...commit
|
||||
}
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,19 @@
|
||||
query($repoOwner: String!, $repoName: String!, $number: Int!, $pageSize: Int = 100, $cursor: String) {
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequest(number: $number) {
|
||||
files(first: $pageSize, after: $cursor) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
path
|
||||
viewerViewedState
|
||||
}
|
||||
}
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequest(number: $number) {
|
||||
files(first: $pageSize, after: $cursor) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
path
|
||||
viewerViewedState
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,18 @@
|
||||
query($repoOwner: String!, $repoName: String!, $number: Int!, $pageSize: Int = 100, $cursor: String) {
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequest(number: $number) {
|
||||
reviewThreads(first: $pageSize, after: $cursor) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
...pullRequestReviewThread
|
||||
}
|
||||
}
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequest(number: $number) {
|
||||
reviewThreads(first: $pageSize, after: $cursor) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
...pullRequestReviewThread
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -1,283 +1,287 @@
|
||||
fragment issueCommentInfo on IssueComment {
|
||||
...comment
|
||||
viewerCanUpdate
|
||||
viewerCanDelete
|
||||
viewerCanReact
|
||||
...comment
|
||||
viewerCanUpdate
|
||||
viewerCanDelete
|
||||
viewerCanReact
|
||||
}
|
||||
|
||||
fragment prCommitInfo on PullRequestCommit {
|
||||
...nodeInfo
|
||||
commit {
|
||||
...commitShort
|
||||
}
|
||||
url
|
||||
...nodeInfo
|
||||
commit {
|
||||
...commitShort
|
||||
}
|
||||
url
|
||||
}
|
||||
|
||||
fragment reviewDismissedEvent on ReviewDismissedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
dismissalMessageHTML
|
||||
review {
|
||||
author {
|
||||
...actorInfo
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
dismissalMessageHTML
|
||||
review {
|
||||
author {
|
||||
...actorInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment readyForReviewEvent on ReadyForReviewEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
|
||||
fragment convertToDraftEvent on ConvertToDraftEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
|
||||
fragment renamedEvent on RenamedTitleEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
previousTitle
|
||||
currentTitle
|
||||
createdAt
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
previousTitle
|
||||
currentTitle
|
||||
createdAt
|
||||
}
|
||||
|
||||
fragment closedEvent on ClosedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
|
||||
fragment reopenedEvent on ReopenedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
|
||||
fragment mergedEvent on MergedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
commit {
|
||||
...commitShort
|
||||
}
|
||||
mergeRefName
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
commit {
|
||||
...commitShort
|
||||
}
|
||||
mergeRefName
|
||||
}
|
||||
|
||||
fragment assignedEvent on AssignedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
user {
|
||||
...userInfo
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
user {
|
||||
...userInfo
|
||||
}
|
||||
}
|
||||
|
||||
fragment unassignedEvent on UnassignedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
user {
|
||||
...userInfo
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
user {
|
||||
...userInfo
|
||||
}
|
||||
}
|
||||
|
||||
fragment labeledEvent on LabeledEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
label {
|
||||
...labelInfo
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
label {
|
||||
...labelInfo
|
||||
}
|
||||
}
|
||||
|
||||
fragment unlabeledEvent on UnlabeledEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
label {
|
||||
...labelInfo
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
label {
|
||||
...labelInfo
|
||||
}
|
||||
}
|
||||
|
||||
fragment reviewRequestedEvent on ReviewRequestedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
requestedReviewer {
|
||||
...pullRequestReviewerInfo
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
requestedReviewer {
|
||||
...pullRequestReviewerInfo
|
||||
}
|
||||
}
|
||||
|
||||
fragment reviewRequestRemovedEvent on ReviewRequestRemovedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
requestedReviewer {
|
||||
...pullRequestReviewerInfo
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
requestedReviewer {
|
||||
...pullRequestReviewerInfo
|
||||
}
|
||||
}
|
||||
|
||||
fragment gitRefName on Ref {
|
||||
name
|
||||
name
|
||||
}
|
||||
|
||||
fragment baseRefForcePushedEvent on BaseRefForcePushedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
ref {
|
||||
...gitRefName
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
ref {
|
||||
...gitRefName
|
||||
}
|
||||
}
|
||||
|
||||
fragment headRefForcePushedEvent on HeadRefForcePushedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
ref {
|
||||
...gitRefName
|
||||
}
|
||||
beforeCommit {
|
||||
...commitHash
|
||||
}
|
||||
afterCommit {
|
||||
...commitHash
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
ref {
|
||||
...gitRefName
|
||||
}
|
||||
beforeCommit {
|
||||
...commitHash
|
||||
}
|
||||
afterCommit {
|
||||
...commitHash
|
||||
}
|
||||
}
|
||||
|
||||
fragment headRefDeletedEvent on HeadRefDeletedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
headRefName
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
headRefName
|
||||
}
|
||||
|
||||
fragment headRefRestoredEvent on HeadRefRestoredEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
|
||||
fragment baseRefChangedEvent on BaseRefChangedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
|
||||
fragment referenceSubject on ReferencedSubject {
|
||||
__typename
|
||||
... on PullRequest {
|
||||
title
|
||||
number
|
||||
state
|
||||
isDraft
|
||||
url
|
||||
}
|
||||
... on Issue {
|
||||
title
|
||||
number
|
||||
state
|
||||
url
|
||||
}
|
||||
__typename
|
||||
... on PullRequest {
|
||||
title
|
||||
number
|
||||
state
|
||||
isDraft
|
||||
url
|
||||
}
|
||||
... on Issue {
|
||||
title
|
||||
number
|
||||
state
|
||||
url
|
||||
}
|
||||
}
|
||||
|
||||
fragment crossReferencedEvent on CrossReferencedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
source {
|
||||
...referenceSubject
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
source {
|
||||
...referenceSubject
|
||||
}
|
||||
}
|
||||
|
||||
fragment connectedEvent on ConnectedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
subject {
|
||||
...referenceSubject
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
subject {
|
||||
...referenceSubject
|
||||
}
|
||||
}
|
||||
|
||||
fragment disconnectedEvent on DisconnectedEvent {
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
subject {
|
||||
...referenceSubject
|
||||
}
|
||||
actor {
|
||||
...actorInfo
|
||||
}
|
||||
createdAt
|
||||
subject {
|
||||
...referenceSubject
|
||||
}
|
||||
}
|
||||
|
||||
query($repoOwner: String!, $repoName: String!, $number: Int!, $pageSize: Int = 100, $cursor: String, $since: DateTime) {
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequest(number: $number) {
|
||||
timelineItems(first: $pageSize, after: $cursor, since: $since) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
__typename
|
||||
...prCommitInfo
|
||||
...pullRequestReview
|
||||
...issueCommentInfo
|
||||
|
||||
...renamedEvent
|
||||
|
||||
...closedEvent
|
||||
...reopenedEvent
|
||||
...mergedEvent
|
||||
|
||||
...assignedEvent
|
||||
...unassignedEvent
|
||||
|
||||
...labeledEvent
|
||||
...unlabeledEvent
|
||||
|
||||
...reviewRequestedEvent
|
||||
...reviewRequestRemovedEvent
|
||||
|
||||
...reviewDismissedEvent
|
||||
|
||||
...readyForReviewEvent
|
||||
...convertToDraftEvent
|
||||
|
||||
...baseRefChangedEvent
|
||||
...baseRefForcePushedEvent
|
||||
|
||||
...headRefForcePushedEvent
|
||||
...headRefDeletedEvent
|
||||
...headRefRestoredEvent
|
||||
|
||||
...crossReferencedEvent
|
||||
...connectedEvent
|
||||
...disconnectedEvent
|
||||
}
|
||||
}
|
||||
repository(owner: $repoOwner, name: $repoName) {
|
||||
pullRequest(number: $number) {
|
||||
timelineItems(first: $pageSize, after: $cursor, since: $since) {
|
||||
pageInfo {
|
||||
...pageInfo
|
||||
}
|
||||
nodes {
|
||||
__typename
|
||||
...prCommitInfo
|
||||
...pullRequestReview
|
||||
...issueCommentInfo
|
||||
|
||||
...renamedEvent
|
||||
|
||||
...closedEvent
|
||||
...reopenedEvent
|
||||
...mergedEvent
|
||||
|
||||
...assignedEvent
|
||||
...unassignedEvent
|
||||
|
||||
...labeledEvent
|
||||
...unlabeledEvent
|
||||
|
||||
...reviewRequestedEvent
|
||||
...reviewRequestRemovedEvent
|
||||
|
||||
...reviewDismissedEvent
|
||||
|
||||
...readyForReviewEvent
|
||||
...convertToDraftEvent
|
||||
|
||||
...baseRefChangedEvent
|
||||
...baseRefForcePushedEvent
|
||||
|
||||
...headRefForcePushedEvent
|
||||
...headRefDeletedEvent
|
||||
...headRefRestoredEvent
|
||||
|
||||
...crossReferencedEvent
|
||||
...connectedEvent
|
||||
...disconnectedEvent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit {
|
||||
...rates
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ object GHGQLQueries {
|
||||
const val createPullRequest = "graphql/query/createPullRequest.graphql"
|
||||
const val findPullRequest = "graphql/query/findPullRequest.graphql"
|
||||
const val findPullRequestId = "graphql/query/findPullRequestId.graphql"
|
||||
const val findOpenPullRequestsByBranches = "graphql/query/findOpenPullRequestsByBranches.graphql"
|
||||
const val updatePullRequest = "graphql/query/updatePullRequest.graphql"
|
||||
const val markPullRequestReadyForReview = "graphql/query/markPullRequestReadyForReview.graphql"
|
||||
const val pullRequestTimeline = "graphql/query/pullRequestTimeline.graphql"
|
||||
|
||||
@@ -46,6 +46,9 @@ object GithubApiContentHelper {
|
||||
@Throws(GithubJsonException::class)
|
||||
inline fun <reified T> fromJson(string: String): T = fromJson(string, T::class.java)
|
||||
|
||||
@Throws(GithubJsonException::class)
|
||||
internal inline fun <reified T> fromJson(string: String, gqlNaming: Boolean = false): T = fromJson(string, T::class.java, gqlNaming)
|
||||
|
||||
@JvmStatic
|
||||
@Throws(GithubJsonException::class)
|
||||
fun <T> fromJson(string: String, clazz: Class<T>, gqlNaming: Boolean = false): T {
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.util.ThrowableConvertor
|
||||
import org.jetbrains.plugins.github.api.data.GithubResponsePage
|
||||
import org.jetbrains.plugins.github.api.data.GithubSearchResult
|
||||
import org.jetbrains.plugins.github.api.data.graphql.GHGQLError
|
||||
import org.jetbrains.plugins.github.api.data.graphql.GHGQLRateLimit
|
||||
import org.jetbrains.plugins.github.exceptions.GithubAuthenticationException
|
||||
import org.jetbrains.plugins.github.exceptions.GithubConfusingException
|
||||
import org.jetbrains.plugins.github.exceptions.GithubJsonException
|
||||
@@ -98,8 +99,7 @@ sealed class GithubApiRequest<out T>(val url: String) {
|
||||
url: String,
|
||||
private val clazz: Class<T>,
|
||||
acceptMimeType: String? = GithubApiContentHelper.V3_JSON_MIME_TYPE,
|
||||
)
|
||||
: Get<GithubResponsePage<T>>(url, acceptMimeType) {
|
||||
) : Get<GithubResponsePage<T>>(url, acceptMimeType) {
|
||||
|
||||
override fun extractResult(response: GithubApiResponse): GithubResponsePage<T> {
|
||||
val page = parseJsonSearchPage(response, clazz)
|
||||
@@ -161,20 +161,20 @@ sealed class GithubApiRequest<out T>(val url: String) {
|
||||
throw GithubConfusingException(errors.toString())
|
||||
}
|
||||
|
||||
abstract fun extractResultWithCost(response: GithubApiResponse): Pair<T, GHGQLRateLimit?>
|
||||
|
||||
override fun extractResult(response: GithubApiResponse): T =
|
||||
extractResultWithCost(response).first
|
||||
|
||||
class Parsed<out T>(
|
||||
url: String,
|
||||
requestFilePath: String,
|
||||
variablesObject: Any,
|
||||
private val clazz: Class<T>,
|
||||
) : GQLQuery<T>(url, requestFilePath, variablesObject) {
|
||||
override fun extractResult(response: GithubApiResponse): T {
|
||||
val result: GraphQLResponseDTO<out T, GHGQLError> = parseGQLResponse(response, clazz)
|
||||
val data = result.data
|
||||
if (data != null) return data
|
||||
|
||||
val errors = result.errors
|
||||
if (errors == null) error("Undefined request state - both result and errors are null")
|
||||
else throwException(errors)
|
||||
override fun extractResultWithCost(response: GithubApiResponse): Pair<T, GHGQLRateLimit?> {
|
||||
return parseResponse(response, clazz)
|
||||
?: throw GithubJsonException("Non-nullable entity is null or entity path is invalid")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,8 +185,7 @@ sealed class GithubApiRequest<out T>(val url: String) {
|
||||
private val clazz: Class<out T>,
|
||||
private vararg val pathFromData: String,
|
||||
) : GQLQuery<T>(url, requestFilePath, variablesObject) {
|
||||
|
||||
override fun extractResult(response: GithubApiResponse): T {
|
||||
override fun extractResultWithCost(response: GithubApiResponse): Pair<T, GHGQLRateLimit?> {
|
||||
return parseResponse(response, clazz, pathFromData)
|
||||
?: throw GithubJsonException("Non-nullable entity is null or entity path is invalid")
|
||||
}
|
||||
@@ -199,8 +198,8 @@ sealed class GithubApiRequest<out T>(val url: String) {
|
||||
private val clazz: Class<T>,
|
||||
private vararg val pathFromData: String,
|
||||
) : GQLQuery<T?>(url, requestFilePath, variablesObject) {
|
||||
override fun extractResult(response: GithubApiResponse): T? {
|
||||
return parseResponse(response, clazz, pathFromData)
|
||||
override fun extractResultWithCost(response: GithubApiResponse): Pair<T?, GHGQLRateLimit?> {
|
||||
return parseResponse(response, clazz, pathFromData) ?: (null to null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,17 +210,25 @@ sealed class GithubApiRequest<out T>(val url: String) {
|
||||
private val clazz: Class<T>,
|
||||
private vararg val pathFromData: String,
|
||||
) : GQLQuery<List<T>?>(url, requestFilePath, variablesObject) {
|
||||
override fun extractResult(response: GithubApiResponse): List<T>? =
|
||||
override fun extractResultWithCost(response: GithubApiResponse): Pair<List<T>?, GHGQLRateLimit?> =
|
||||
parseResponse(response, pathFromData) {
|
||||
GithubApiContentHelper.readJsonList(it.toString().reader(), clazz)
|
||||
}
|
||||
} ?: (null to null)
|
||||
}
|
||||
|
||||
protected fun <T> parseResponse(
|
||||
response: GithubApiResponse,
|
||||
clazz: Class<T>,
|
||||
): Pair<T, GHGQLRateLimit?>? =
|
||||
parseResponse(response, arrayOf()) {
|
||||
GithubApiContentHelper.fromJson(it.toString(), clazz, true)
|
||||
}
|
||||
|
||||
protected fun <T> parseResponse(
|
||||
response: GithubApiResponse,
|
||||
clazz: Class<T>,
|
||||
pathFromData: Array<out String>,
|
||||
): T? =
|
||||
): Pair<T, GHGQLRateLimit?>? =
|
||||
parseResponse(response, pathFromData) {
|
||||
GithubApiContentHelper.fromJson(it.toString(), clazz, true)
|
||||
}
|
||||
@@ -230,15 +237,21 @@ sealed class GithubApiRequest<out T>(val url: String) {
|
||||
response: GithubApiResponse,
|
||||
pathFromData: Array<out String>,
|
||||
deserialize: (JsonNode) -> T,
|
||||
): T? {
|
||||
val result: GraphQLResponseDTO<out JsonNode, GHGQLError> = parseGQLResponse(response, JsonNode::class.java)
|
||||
): Pair<T, GHGQLRateLimit?>? {
|
||||
val result = parseGQLResponse(response, JsonNode::class.java)
|
||||
val data = result.data
|
||||
if (data != null && !data.isNull) {
|
||||
var node: JsonNode = data
|
||||
for (path in pathFromData) {
|
||||
node = node[path] ?: break
|
||||
}
|
||||
if (!node.isNull) return deserialize(node)
|
||||
if (!node.isNull) {
|
||||
val result = deserialize(node)
|
||||
val rates = data["rateLimit"]
|
||||
?.takeIf { !it.isNull }
|
||||
?.let { GithubApiContentHelper.fromJson<GHGQLRateLimit?>(it.toString(), gqlNaming = true) }
|
||||
return result to rates
|
||||
}
|
||||
}
|
||||
val errors = result.errors
|
||||
if (errors == null) return null
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.github.api
|
||||
|
||||
import com.intellij.collaboration.api.dto.GraphQLRequestDTO
|
||||
import com.intellij.collaboration.api.httpclient.HttpClientUtil
|
||||
import com.intellij.collaboration.ui.SimpleEventListener
|
||||
import com.intellij.openapi.Disposable
|
||||
@@ -22,6 +23,7 @@ import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.plugins.github.api.data.GithubErrorMessage
|
||||
import org.jetbrains.plugins.github.exceptions.*
|
||||
import org.jetbrains.plugins.github.i18n.GithubBundle
|
||||
import org.jetbrains.plugins.github.pullrequest.GHPRStatisticsCollector
|
||||
import org.jetbrains.plugins.github.util.GithubSettings
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
@@ -95,6 +97,7 @@ sealed class GithubApiRequestExecutor {
|
||||
indicator.checkCanceled()
|
||||
try {
|
||||
LOG.debug("Request: ${request.url} ${request.operationName} : Connecting")
|
||||
val activity = GHPRStatisticsCollector.logApiRequestStart(request.operation)
|
||||
return connect {
|
||||
val connection = it.connection as HttpURLConnection
|
||||
if (request is GithubApiRequest.WithBody) {
|
||||
@@ -104,10 +107,28 @@ sealed class GithubApiRequestExecutor {
|
||||
else {
|
||||
LOG.debug("Request: ${connection.requestMethod} ${connection.url} : Connected")
|
||||
}
|
||||
|
||||
GHPRStatisticsCollector.logApiResponseReceived(
|
||||
activity = activity,
|
||||
remaining = connection.getHeaderFieldInt("x-ratelimit-remaining", -1),
|
||||
resourceName = connection.getHeaderField("x-ratelimit-resource"),
|
||||
statusCode = connection.responseCode,
|
||||
)
|
||||
|
||||
checkResponseCode(connection)
|
||||
checkServerVersion(connection)
|
||||
|
||||
indicator.checkCanceled()
|
||||
val result = request.extractResult(createResponse(it, indicator))
|
||||
|
||||
val (result, rates) = if (request is GithubApiRequest.Post.GQLQuery) {
|
||||
request.extractResultWithCost(createResponse(it, indicator))
|
||||
} else {
|
||||
request.extractResult(createResponse(it, indicator)) to null
|
||||
}
|
||||
val cost = rates?.cost
|
||||
|
||||
GHPRStatisticsCollector.logApiResponseRates(request.operation, cost ?: 1, isGuessed = cost == null)
|
||||
|
||||
LOG.debug("Request: ${connection.requestMethod} ${connection.url} : Result extracted")
|
||||
result
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.plugins.github.api.data.graphql
|
||||
|
||||
import com.intellij.collaboration.api.dto.GraphQLFragment
|
||||
|
||||
@GraphQLFragment("/graphql/fragment/rates.graphql")
|
||||
data class GHGQLRateLimit(val cost: Int)
|
||||
+110
-3
@@ -1,18 +1,21 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.plugins.github.pullrequest
|
||||
|
||||
import com.intellij.internal.statistic.StructuredIdeActivity
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
import com.intellij.internal.statistic.eventLog.events.EventFields
|
||||
import com.intellij.internal.statistic.eventLog.events.EventPair
|
||||
import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.ProjectActivity
|
||||
import com.intellij.platform.util.coroutines.childScope
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.plugins.github.api.GithubApiRequestOperation
|
||||
import org.jetbrains.plugins.github.api.GithubServerPath
|
||||
import org.jetbrains.plugins.github.api.data.GHEnterpriseServerMeta
|
||||
import org.jetbrains.plugins.github.api.data.GithubPullRequestMergeMethod
|
||||
@@ -22,8 +25,10 @@ import org.jetbrains.plugins.github.util.GHEnterpriseServerMetadataLoader
|
||||
import java.util.*
|
||||
|
||||
// TODO: Fix or replace a whole bunch of these statistics as they're no longer being collected since generalizing to Collab Tools
|
||||
internal object GHPRStatisticsCollector: CounterUsagesCollector() {
|
||||
private val COUNTERS_GROUP = EventLogGroup("vcs.github.pullrequest.counters", 7)
|
||||
internal object GHPRStatisticsCollector : CounterUsagesCollector() {
|
||||
private val COUNTERS_GROUP = EventLogGroup("vcs.github.pullrequest.counters", 8)
|
||||
|
||||
private val LOG = logger<GHPRStatisticsCollector>()
|
||||
|
||||
override fun getGroup() = COUNTERS_GROUP
|
||||
|
||||
@@ -159,6 +164,108 @@ internal object GHPRStatisticsCollector: CounterUsagesCollector() {
|
||||
SERVER_META_EVENT.log(project, server.toUrl(), meta.installedVersion)
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region: API
|
||||
private enum class RateLimitResource {
|
||||
Core, Search, CodeSearch, GraphQL,
|
||||
IntegrationManifest, DependencySnapshots, CodeScanningUpload, ActionsRunnerRegistration,
|
||||
SourceImport,
|
||||
Collaborators,
|
||||
Unknown;
|
||||
|
||||
companion object {
|
||||
fun fromString(name: String): RateLimitResource = when (name) {
|
||||
"core", "rate" -> Core
|
||||
"search" -> Search
|
||||
"code_search" -> CodeSearch
|
||||
"graphql" -> GraphQL
|
||||
"integration_manifest" -> IntegrationManifest
|
||||
"dependency_snapshots" -> DependencySnapshots
|
||||
"code_scanning_upload" -> CodeScanningUpload
|
||||
"actions_runner_registration" -> ActionsRunnerRegistration
|
||||
"collaborators" -> Collaborators
|
||||
"source_import" -> SourceImport
|
||||
else -> Unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val API_REQUEST_OPERATION_FIELD = EventFields.Enum<GithubApiRequestOperation>(
|
||||
"operation", description = "The type of operation executed."
|
||||
)
|
||||
|
||||
private val API_REQUEST_RATELIMIT_REMAINING_FIELD = EventFields.Int(
|
||||
"rates_remaining",
|
||||
description = "The rate limit remaining for the resource as returned by GitHub." +
|
||||
"This is not a good measure of rates-used-per-request, instead it's a measure of total usage for a session/user."
|
||||
)
|
||||
|
||||
private val API_REQUEST_RATELIMIT_USED_FIELD = EventFields.Int(
|
||||
"rates_used",
|
||||
description = "The rate limit used during the request. " +
|
||||
"In the case of GraphQL rates, this is taken directly from the request. " +
|
||||
"In the case of REST rates, this defaults to 1, but may be changed in the future if GitHub changes their rate limit policy."
|
||||
)
|
||||
|
||||
private val API_REQUEST_RATELIMIT_GUESSED_FIELD = EventFields.Boolean(
|
||||
"rates_used_guessed",
|
||||
description = "Whether the rates used during the request are guessed. " +
|
||||
"If `false`, the rates are pulled directly from the request."
|
||||
)
|
||||
|
||||
private val API_REQUEST_RATELIMIT_RESOURCE_FIELD = EventFields.Enum<RateLimitResource>(
|
||||
"rates_resource", description = "The resource from which rates are taken as returned by GitHub."
|
||||
)
|
||||
|
||||
private val API_REQUEST_STATUS_CODE_FIELD = EventFields.Int(
|
||||
"status", description = "The status code of the response (200 = OK, 404 = Not Found, etc.)."
|
||||
)
|
||||
|
||||
private val API_REQUEST_EVENT = COUNTERS_GROUP.registerIdeActivity(
|
||||
"api.request",
|
||||
startEventAdditionalFields = arrayOf(API_REQUEST_OPERATION_FIELD),
|
||||
finishEventAdditionalFields = arrayOf(API_REQUEST_RATELIMIT_REMAINING_FIELD, API_REQUEST_RATELIMIT_RESOURCE_FIELD, API_REQUEST_STATUS_CODE_FIELD)
|
||||
)
|
||||
|
||||
private val API_REQUEST_RATES_EVENT = COUNTERS_GROUP.registerEvent(
|
||||
"api.rates",
|
||||
API_REQUEST_OPERATION_FIELD,
|
||||
API_REQUEST_RATELIMIT_USED_FIELD,
|
||||
API_REQUEST_RATELIMIT_GUESSED_FIELD,
|
||||
description = "Event that happens internally after we have tried to determine the rates used for a request."
|
||||
)
|
||||
|
||||
fun logApiRequestStart(operation: GithubApiRequestOperation): StructuredIdeActivity =
|
||||
API_REQUEST_EVENT.started(null) {
|
||||
listOf(API_REQUEST_OPERATION_FIELD.with(operation))
|
||||
}
|
||||
|
||||
fun logApiResponseReceived(
|
||||
activity: StructuredIdeActivity,
|
||||
remaining: Int, resourceName: String,
|
||||
statusCode: Int,
|
||||
) {
|
||||
val resource = RateLimitResource.fromString(resourceName)
|
||||
|
||||
if (resource == RateLimitResource.Unknown) {
|
||||
LOG.warn("Unknown rate limit resource: ${resourceName}")
|
||||
}
|
||||
|
||||
activity.finished {
|
||||
listOf(
|
||||
API_REQUEST_RATELIMIT_REMAINING_FIELD.with(remaining),
|
||||
API_REQUEST_RATELIMIT_RESOURCE_FIELD.with(resource),
|
||||
API_REQUEST_STATUS_CODE_FIELD.with(statusCode)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun logApiResponseRates(operation: GithubApiRequestOperation, used: Int, isGuessed: Boolean) {
|
||||
LOG.debug("Rates { operation: $operation, used: $used, isGuessed: $isGuessed }")
|
||||
|
||||
API_REQUEST_RATES_EVENT.log(operation, used, isGuessed)
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
enum class GHPRAction {
|
||||
@@ -176,7 +283,7 @@ enum class GHPRAction {
|
||||
@Service(Service.Level.PROJECT)
|
||||
private class GHServerVersionsCollector(
|
||||
private val project: Project,
|
||||
parentCs: CoroutineScope
|
||||
parentCs: CoroutineScope,
|
||||
) {
|
||||
|
||||
private val scope = parentCs.childScope(javaClass.name)
|
||||
|
||||
Reference in New Issue
Block a user