{"action":"created","comment":{"url":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/comments/207072446","pull_request_review_id":142610998,"id":207072446,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwNzA3MjQ0Ng==","diff_hunk":"@@ -0,0 +1,183 @@\n+// Copyright (c) 2017 The Jaeger Authors.\n+//\n+// Licensed under the Apache License, Version 2.0 (the \"License\");\n+// you may not use this file except in compliance with the License.\n+// You may obtain a copy of the License at\n+//\n+// http://www.apache.org/licenses/LICENSE-2.0\n+//\n+// Unless required by applicable law or agreed to in writing, software\n+// distributed under the License is distributed on an \"AS IS\" BASIS,\n+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+// See the License for the specific language governing permissions and\n+// limitations under the License.\n+\n+import _uniq from 'lodash/uniq';\n+import { getConfigValue } from '../utils/config/get-config';\n+\n+const parameterRegExp = /\\$\\{([^{}]*)\\}/;\n+\n+export function processTemplate(template, encodeFn) {\n+  if (typeof template !== 'string') {\n+    if (!template || !Array.isArray(template.parameters) || !(template.template instanceof Function)) {\n+      throw new Error('Invalid template');\n+    }\n+    return template;\n+  }\n+  const templateSplit = template.split(parameterRegExp);\n+  const templateSplitLength = templateSplit.length;\n+  const parameters = [];\n+  // odd indexes contain variable names\n+  for (let i = 1; i < templateSplitLength; i += 2) {\n+    const param = templateSplit[i];\n+    let paramIndex = parameters.indexOf(param);\n+    if (paramIndex === -1) {\n+      paramIndex = parameters.length;\n+      parameters.push(param);\n+    }\n+    templateSplit[i] = paramIndex;\n+  }\n+  return {\n+    parameters,\n+    template: (...args) => {\n+      let text = '';\n+      for (let i = 0; i < templateSplitLength; i++) {\n+        if (i % 2 === 0) {\n+          text += templateSplit[i];\n+        } else {\n+          text += encodeFn(args[templateSplit[i]]);\n+        }\n+      }\n+      return text;\n+    },\n+  };\n+}\n+\n+export function createTestFunction(entry) {\n+  if (typeof entry === 'string') {\n+    return arg => arg === entry;\n+  }\n+  if (Array.isArray(entry)) {\n+    return arg => entry.indexOf(arg) > -1;\n+  }\n+  if (entry instanceof RegExp) {\n+    return arg => entry.test(arg);\n+  }\n+  if (typeof entry === 'function') {\n+    return entry;\n+  }\n+  if (entry == null) {\n+    return () => true;\n+  }\n+  throw new Error(`Invalid value: ${entry}`);\n+}\n+\n+const identity = a => a;\n+\n+export function processLinkPattern(pattern) {\n+  try {\n+    const url = processTemplate(pattern.url, encodeURIComponent);\n+    const text = processTemplate(pattern.text, identity);\n+    return {\n+      object: pattern,\n+      type: createTestFunction(pattern.type),\n+      key: createTestFunction(pattern.key),\n+      value: createTestFunction(pattern.value),\n+      url,\n+      text,\n+      parameters: _uniq(url.parameters.concat(text.parameters)),\n+    };\n+  } catch (error) {\n+    // eslint-disable-next-line no-console\n+    console.error(`Ignoring invalid link pattern: ${error}`, pattern);\n+    return null;\n+  }\n+}\n+\n+export function getParameterInArray(name, array) {\n+  if (array) {\n+    return array.find(entry => entry.key === name);\n+  }\n+  return undefined;\n+}\n+\n+export function getParameterInAncestor(name, spans, startSpanIndex) {\n+  let currentSpan = { depth: spans[startSpanIndex].depth + 1 };\n+  for (let spanIndex = startSpanIndex; spanIndex >= 0; spanIndex--) {\n+    const nextSpan = spans[spanIndex];\n+    if (nextSpan.depth < currentSpan.depth) {\n+      currentSpan = nextSpan;\n+      const result =\n+        getParameterInArray(name, currentSpan.tags) || getParameterInArray(name, currentSpan.process.tags);\n+      if (result) {\n+        return result;\n+      }\n+    }\n+  }\n+  return undefined;\n+}\n+\n+export function callTemplate(template, data) {\n+  return template.template(...template.parameters.map(param => data[param]));\n+}\n+\n+export function computeLinks(linkPatterns, trace, spanIndex, items, itemIndex) {\n+  const item = items[itemIndex];\n+  const span = trace.spans[spanIndex];\n+  let type = 'logs';\n+  const processTags = span.process.tags === items;\n+  if (processTags) {\n+    type = 'process';\n+  }\n+  const spanTags = span.tags === items;\n+  if (spanTags) {\n+    type = 'tags';\n+  }\n+  const result = [];\n+  linkPatterns.forEach(pattern => {\n+    if (pattern.type(type) && pattern.key(item.key, item.value, type) && pattern.value(item.value)) {\n+      let parameterValues = {};\n+      pattern.parameters.every(parameter => {\n+        let entry = getParameterInArray(parameter, items);\n+        if (!entry && !processTags) {\n+          // do not look in ancestors for process tags because the same object may appear in different places in the hierarchy","path":"packages/jaeger-ui/src/model/link-patterns.js","position":null,"original_position":143,"commit_id":"6048d0aa8a5745f3aea3a1fc9c58fc2e09a9eb92","original_commit_id":"a159459c548770100f8b7e4970845017f19f69b9","user":{"login":"tiffon","id":2304337,"node_id":"MDQ6VXNlcjIzMDQzMzc=","avatar_url":"https://avatars0.githubusercontent.com/u/2304337?v=4","gravatar_id":"","url":"https://api.github.com/users/tiffon","html_url":"https://github.com/tiffon","followers_url":"https://api.github.com/users/tiffon/followers","following_url":"https://api.github.com/users/tiffon/following{/other_user}","gists_url":"https://api.github.com/users/tiffon/gists{/gist_id}","starred_url":"https://api.github.com/users/tiffon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tiffon/subscriptions","organizations_url":"https://api.github.com/users/tiffon/orgs","repos_url":"https://api.github.com/users/tiffon/repos","events_url":"https://api.github.com/users/tiffon/events{/privacy}","received_events_url":"https://api.github.com/users/tiffon/received_events","type":"User","site_admin":false},"body":"Great explanation, I think I've got it... Don't look in ancestors for process tags because the same process object, and therefore tags, can be used for many spans. In this case, searching a span's ancestors could yield different results (if they weren't cached). But, as the cache is keyed on the initial, shared, process tag, all spans with that process would end up getting the same results even if they have different ancestors?","created_at":"2018-08-02T00:37:25Z","updated_at":"2018-08-02T00:47:15Z","html_url":"https://github.com/jaegertracing/jaeger-ui/pull/223#discussion_r207072446","pull_request_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/223","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/comments/207072446"},"html":{"href":"https://github.com/jaegertracing/jaeger-ui/pull/223#discussion_r207072446"},"pull_request":{"href":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/223"}},"in_reply_to_id":201136610},"pull_request":{"url":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/223","id":199295879,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk5Mjk1ODc5","html_url":"https://github.com/jaegertracing/jaeger-ui/pull/223","diff_url":"https://github.com/jaegertracing/jaeger-ui/pull/223.diff","patch_url":"https://github.com/jaegertracing/jaeger-ui/pull/223.patch","issue_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/issues/223","number":223,"state":"open","locked":false,"title":"[WIP] Add links to make values in tags or log properties clickable","user":{"login":"divdavem","id":1152706,"node_id":"MDQ6VXNlcjExNTI3MDY=","avatar_url":"https://avatars1.githubusercontent.com/u/1152706?v=4","gravatar_id":"","url":"https://api.github.com/users/divdavem","html_url":"https://github.com/divdavem","followers_url":"https://api.github.com/users/divdavem/followers","following_url":"https://api.github.com/users/divdavem/following{/other_user}","gists_url":"https://api.github.com/users/divdavem/gists{/gist_id}","starred_url":"https://api.github.com/users/divdavem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/divdavem/subscriptions","organizations_url":"https://api.github.com/users/divdavem/orgs","repos_url":"https://api.github.com/users/divdavem/repos","events_url":"https://api.github.com/users/divdavem/events{/privacy}","received_events_url":"https://api.github.com/users/divdavem/received_events","type":"User","site_admin":false},"body":"This pull request contains an implementation of the feature described in #216.\r\n\r\nIt allows to define in the configuration some patterns so that the values of keys from the `Tags`, `Process` and `Logs` sections become clickable links that open the configured URL.\r\n\r\nThis has to be configured in the new `linkPatterns` property. For example:\r\n\r\n```json\r\n{\r\n  \"linkPatterns\": [{\r\n    \"type\": \"process\",\r\n    \"key\": \"jaeger.version\",\r\n    \"url\": \"https://github.com/jaegertracing/jaeger-client-go/releases/tag/#{jaeger.version}\",\r\n    \"text\": \"Information about Jaeger release #{jaeger.version}\"\r\n  }]\r\n}\r\n```\r\n\r\nWhen this is declared in the configuration, every time the `jaeger.version` key appears in the `process` section, the value of that key will be displayed as a clickable link, with an icon on the right to show that the value is clickable, for example:\r\n\r\n![jaeger link](https://user-images.githubusercontent.com/1152706/42288023-66439c8c-7fb9-11e8-9eba-e46063ed8a09.png)\r\n\r\n\r\nIf several patterns match the same tag, clicking on the value will display a popup with all the links:\r\n\r\n![jaeger multiple links](https://user-images.githubusercontent.com/1152706/42288044-72eb6064-7fb9-11e8-8ef0-78d1350d2cc3.png)\r\n\r\n\r\nLinks are opened in a new window or tab.\r\n\r\nIn the configuration of a link, there are two kinds of properties:\r\n- test properties: they determine whether the link should be displayed. These properties can contain a string or an array of strings specifying the possible values of that property that lead to the display of the link. All test properties must match for the link to be displayed. If a test property is not defined, it is considered to match.\r\n  - `type` (possible values: `process`, `logs` or `tags`)\r\n  - `key`\r\n  - `value`\r\n- template properties: they determine the url and text of the link. They are simple templates where each occurrence of `#{key}` is replaced by the value of the given `key`.\r\n  - `url`: each replacement in the URL is wrapped in a call to `encodeURIComponent`\r\n  - `text`: if there is only one link, the text of the link is displayed as a tooltip, if there are multiple links the text is displayed in the popup menu\r\n\r\n  Template properties can depend on the value of the following keys:\r\n  - for type `process`, only the keys in the current process can be used\r\n  - for other types, the search order is the following:\r\n    - for type `logs`: the keys present in the log  \r\n    - the keys of the tags or process in the span on which the log or tag being rendered can be found\r\n    - the keys of the tags or process in the parent span according to the CHILD_OF hierarchy\r\n    - other parents in the CHILD_OF hierarchy...\r\n\r\n\r\n**Commented extra features**\r\n\r\nNote that this PR originally also implemented the following possibilities that rely on the implementation of #123 (which allows the use of any JS expression instead of only JSON in the configuration). Those features have been commented in the code of the PR.\r\n- test properties can contain functions or regular expressions instead of containing only strings or arrays of strings\r\n- template properties can be implemented as an object containing two properties:\r\n  - parameters: an array of strings specifying which keys are needed\r\n  - template: a function that receives as its only argument an object with the keys declared in the `parameters` array and returns the url or the text of the link\r\n\r\nFor example, once #123 is implemented and the corresponding code is uncommented, the previous example can also be configured in the following equivalent way (using functions):\r\n\r\n```js\r\nconst JAEGER_CONFIG = {\r\n  linkPatterns: [{\r\n    type: (type) => type === \"process\",\r\n    key: (key) => key === \"jaeger.version\",\r\n    url: {\r\n      parameters: [\"jaeger.version\"],\r\n      template: data => `https://github.com/jaegertracing/jaeger-client-go/releases/tag/${encodeURIComponent(data[\"jaeger.version\"])}`\r\n    },\r\n    text: {\r\n      parameters: [\"jaeger.version\"],\r\n      template: data => `Information about Jaeger release ${data[\"jaeger.version\"]}`\r\n    }\r\n  }]\r\n}\r\n```\r\n\r\nThank you in advance for your comments.\r\n","created_at":"2018-07-04T16:49:14Z","updated_at":"2018-08-02T00:47:15Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7f0b5fe1dcb226957a16e6ebf8a9052c6f2d5694","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/223/commits","review_comments_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/223/comments","review_comment_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/comments{/number}","comments_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/issues/223/comments","statuses_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/statuses/6048d0aa8a5745f3aea3a1fc9c58fc2e09a9eb92","head":{"label":"divdavem:linkPatterns","ref":"linkPatterns","sha":"6048d0aa8a5745f3aea3a1fc9c58fc2e09a9eb92","user":{"login":"divdavem","id":1152706,"node_id":"MDQ6VXNlcjExNTI3MDY=","avatar_url":"https://avatars1.githubusercontent.com/u/1152706?v=4","gravatar_id":"","url":"https://api.github.com/users/divdavem","html_url":"https://github.com/divdavem","followers_url":"https://api.github.com/users/divdavem/followers","following_url":"https://api.github.com/users/divdavem/following{/other_user}","gists_url":"https://api.github.com/users/divdavem/gists{/gist_id}","starred_url":"https://api.github.com/users/divdavem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/divdavem/subscriptions","organizations_url":"https://api.github.com/users/divdavem/orgs","repos_url":"https://api.github.com/users/divdavem/repos","events_url":"https://api.github.com/users/divdavem/events{/privacy}","received_events_url":"https://api.github.com/users/divdavem/received_events","type":"User","site_admin":false},"repo":{"id":139738783,"node_id":"MDEwOlJlcG9zaXRvcnkxMzk3Mzg3ODM=","name":"jaeger-ui","full_name":"divdavem/jaeger-ui","owner":{"login":"divdavem","id":1152706,"node_id":"MDQ6VXNlcjExNTI3MDY=","avatar_url":"https://avatars1.githubusercontent.com/u/1152706?v=4","gravatar_id":"","url":"https://api.github.com/users/divdavem","html_url":"https://github.com/divdavem","followers_url":"https://api.github.com/users/divdavem/followers","following_url":"https://api.github.com/users/divdavem/following{/other_user}","gists_url":"https://api.github.com/users/divdavem/gists{/gist_id}","starred_url":"https://api.github.com/users/divdavem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/divdavem/subscriptions","organizations_url":"https://api.github.com/users/divdavem/orgs","repos_url":"https://api.github.com/users/divdavem/repos","events_url":"https://api.github.com/users/divdavem/events{/privacy}","received_events_url":"https://api.github.com/users/divdavem/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/divdavem/jaeger-ui","description":"Web UI for Jaeger","fork":true,"url":"https://api.github.com/repos/divdavem/jaeger-ui","forks_url":"https://api.github.com/repos/divdavem/jaeger-ui/forks","keys_url":"https://api.github.com/repos/divdavem/jaeger-ui/keys{/key_id}","collaborators_url":"https://api.github.com/repos/divdavem/jaeger-ui/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/divdavem/jaeger-ui/teams","hooks_url":"https://api.github.com/repos/divdavem/jaeger-ui/hooks","issue_events_url":"https://api.github.com/repos/divdavem/jaeger-ui/issues/events{/number}","events_url":"https://api.github.com/repos/divdavem/jaeger-ui/events","assignees_url":"https://api.github.com/repos/divdavem/jaeger-ui/assignees{/user}","branches_url":"https://api.github.com/repos/divdavem/jaeger-ui/branches{/branch}","tags_url":"https://api.github.com/repos/divdavem/jaeger-ui/tags","blobs_url":"https://api.github.com/repos/divdavem/jaeger-ui/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/divdavem/jaeger-ui/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/divdavem/jaeger-ui/git/refs{/sha}","trees_url":"https://api.github.com/repos/divdavem/jaeger-ui/git/trees{/sha}","statuses_url":"https://api.github.com/repos/divdavem/jaeger-ui/statuses/{sha}","languages_url":"https://api.github.com/repos/divdavem/jaeger-ui/languages","stargazers_url":"https://api.github.com/repos/divdavem/jaeger-ui/stargazers","contributors_url":"https://api.github.com/repos/divdavem/jaeger-ui/contributors","subscribers_url":"https://api.github.com/repos/divdavem/jaeger-ui/subscribers","subscription_url":"https://api.github.com/repos/divdavem/jaeger-ui/subscription","commits_url":"https://api.github.com/repos/divdavem/jaeger-ui/commits{/sha}","git_commits_url":"https://api.github.com/repos/divdavem/jaeger-ui/git/commits{/sha}","comments_url":"https://api.github.com/repos/divdavem/jaeger-ui/comments{/number}","issue_comment_url":"https://api.github.com/repos/divdavem/jaeger-ui/issues/comments{/number}","contents_url":"https://api.github.com/repos/divdavem/jaeger-ui/contents/{+path}","compare_url":"https://api.github.com/repos/divdavem/jaeger-ui/compare/{base}...{head}","merges_url":"https://api.github.com/repos/divdavem/jaeger-ui/merges","archive_url":"https://api.github.com/repos/divdavem/jaeger-ui/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/divdavem/jaeger-ui/downloads","issues_url":"https://api.github.com/repos/divdavem/jaeger-ui/issues{/number}","pulls_url":"https://api.github.com/repos/divdavem/jaeger-ui/pulls{/number}","milestones_url":"https://api.github.com/repos/divdavem/jaeger-ui/milestones{/number}","notifications_url":"https://api.github.com/repos/divdavem/jaeger-ui/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/divdavem/jaeger-ui/labels{/name}","releases_url":"https://api.github.com/repos/divdavem/jaeger-ui/releases{/id}","deployments_url":"https://api.github.com/repos/divdavem/jaeger-ui/deployments","created_at":"2018-07-04T15:23:42Z","updated_at":"2018-08-01T14:09:52Z","pushed_at":"2018-08-01T14:09:50Z","git_url":"git://github.com/divdavem/jaeger-ui.git","ssh_url":"git@github.com:divdavem/jaeger-ui.git","clone_url":"https://github.com/divdavem/jaeger-ui.git","svn_url":"https://github.com/divdavem/jaeger-ui","homepage":"http://jaegertracing.io/","size":3597,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"jaegertracing:master","ref":"master","sha":"fa0f161c76dffa212148e405a2af3c1157ac3dcc","user":{"login":"jaegertracing","id":28545596,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI4NTQ1NTk2","avatar_url":"https://avatars1.githubusercontent.com/u/28545596?v=4","gravatar_id":"","url":"https://api.github.com/users/jaegertracing","html_url":"https://github.com/jaegertracing","followers_url":"https://api.github.com/users/jaegertracing/followers","following_url":"https://api.github.com/users/jaegertracing/following{/other_user}","gists_url":"https://api.github.com/users/jaegertracing/gists{/gist_id}","starred_url":"https://api.github.com/users/jaegertracing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaegertracing/subscriptions","organizations_url":"https://api.github.com/users/jaegertracing/orgs","repos_url":"https://api.github.com/users/jaegertracing/repos","events_url":"https://api.github.com/users/jaegertracing/events{/privacy}","received_events_url":"https://api.github.com/users/jaegertracing/received_events","type":"Organization","site_admin":false},"repo":{"id":82920852,"node_id":"MDEwOlJlcG9zaXRvcnk4MjkyMDg1Mg==","name":"jaeger-ui","full_name":"jaegertracing/jaeger-ui","owner":{"login":"jaegertracing","id":28545596,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI4NTQ1NTk2","avatar_url":"https://avatars1.githubusercontent.com/u/28545596?v=4","gravatar_id":"","url":"https://api.github.com/users/jaegertracing","html_url":"https://github.com/jaegertracing","followers_url":"https://api.github.com/users/jaegertracing/followers","following_url":"https://api.github.com/users/jaegertracing/following{/other_user}","gists_url":"https://api.github.com/users/jaegertracing/gists{/gist_id}","starred_url":"https://api.github.com/users/jaegertracing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaegertracing/subscriptions","organizations_url":"https://api.github.com/users/jaegertracing/orgs","repos_url":"https://api.github.com/users/jaegertracing/repos","events_url":"https://api.github.com/users/jaegertracing/events{/privacy}","received_events_url":"https://api.github.com/users/jaegertracing/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/jaegertracing/jaeger-ui","description":"Web UI for Jaeger","fork":false,"url":"https://api.github.com/repos/jaegertracing/jaeger-ui","forks_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/forks","keys_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/teams","hooks_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/hooks","issue_events_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/issues/events{/number}","events_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/events","assignees_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/assignees{/user}","branches_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/branches{/branch}","tags_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/tags","blobs_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/git/refs{/sha}","trees_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/statuses/{sha}","languages_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/languages","stargazers_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/stargazers","contributors_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/contributors","subscribers_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/subscribers","subscription_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/subscription","commits_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/commits{/sha}","git_commits_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/git/commits{/sha}","comments_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/comments{/number}","issue_comment_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/issues/comments{/number}","contents_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/contents/{+path}","compare_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/merges","archive_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/downloads","issues_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/issues{/number}","pulls_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls{/number}","milestones_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/milestones{/number}","notifications_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/labels{/name}","releases_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/releases{/id}","deployments_url":"https://api.github.com/repos/jaegertracing/jaeger-ui/deployments","created_at":"2017-02-23T11:30:29Z","updated_at":"2018-08-01T21:57:09Z","pushed_at":"2018-08-01T14:08:26Z","git_url":"git://github.com/jaegertracing/jaeger-ui.git","ssh_url":"git@github.com:jaegertracing/jaeger-ui.git","clone_url":"https://github.com/jaegertracing/jaeger-ui.git","svn_url":"https://github.com/jaegertracing/jaeger-ui","homepage":"http://jaegertracing.io/","size":3715,"stargazers_count":127,"watchers_count":127,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":44,"mirror_url":null,"archived":false,"open_issues_count":45,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":44,"open_issues":45,"watchers":127,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/223"},"html":{"href":"https://github.com/jaegertracing/jaeger-ui/pull/223"},"issue":{"href":"https://api.github.com/repos/jaegertracing/jaeger-ui/issues/223"},"comments":{"href":"https://api.github.com/repos/jaegertracing/jaeger-ui/issues/223/comments"},"review_comments":{"href":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/223/comments"},"review_comment":{"href":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/jaegertracing/jaeger-ui/pulls/223/commits"},"statuses":{"href":"https://api.github.com/repos/jaegertracing/jaeger-ui/statuses/6048d0aa8a5745f3aea3a1fc9c58fc2e09a9eb92"}},"author_association":"NONE"}}
{"actor":{"display_login":"tiffon"}}