{"action":"created","comment":{"url":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/comments/66400257","id":66400257,"diff_hunk":"@@ -0,0 +1,279 @@\n+########################################################################\n+# $Id: $\n+########################################################################\n+\n+\"\"\"\n+This class a wrapper around elasticsearch-py. It is used to query\n+Elasticsearch database.\n+\n+\"\"\"\n+\n+__RCSID__ = \"$Id$\"\n+\n+from DIRAC                      import gLogger, S_OK, S_ERROR\n+from elasticsearch              import Elasticsearch\n+from elasticsearch_dsl          import Search, Q, A\n+from elasticsearch.exceptions   import ConnectionError, TransportError, NotFoundError\n+from elasticsearch.helpers      import BulkIndexError\n+from elasticsearch              import helpers\n+from datetime                   import datetime\n+from DIRAC.Core.Utilities       import Time\n+\n+class ElasticSearchDB( object ):\n+  \n+  \"\"\"\n+  .. class:: ElasticSearchDB\n+\n+  :param str url: the url to the database for example: el.cern.ch:9200\n+  :param str gDebugFile: is used to save the debug information to a file\n+  :param int timeout the default time out to Elasticsearch\n+  \"\"\"\n+  __chunk_size = 1000\n+  __url = \"\"\n+  __timeout = 120\n+  ########################################################################\n+  def __init__( self, host, port, debug = False ):\n+    \"\"\" c'tor\n+    :param self: self reference\n+    :param str host: name of the database for example: MonitoringDB\n+    :param str port: The full name of the database for example: 'Monitoring/MonitoringDB'\n+    :param bool debug: save the debug information to a file   \n+    \"\"\"\n+    global gDebugFile\n+    \n+    if not hasattr( self, 'log' ):\n+      self.log = gLogger.getSubLogger( 'ElasticSearch' )\n+    self.logger = self.log\n+    \n+    self.__url = \"http://%s:%s\" % ( host, port )\n+        \n+    if debug:\n+      try:\n+        gDebugFile = open( \"%s.debug.log\" % self.__dbName, \"w\" )\n+      except IOError as e:\n+        self.log.error( e )\n+      \n+    self.__client = Elasticsearch( self.__url, timeout = self.__timeout )\n+    self.__tryToConnect()\n+  \n+  ########################################################################\n+  def setClusterName( self, name ):\n+    \"\"\"\n+      It is used to set the cluster name\n+      \n+      :param self: self reference\n+      :param str requestName: request name\n+    \n+    \"\"\"\n+    self.__clusterName = name\n+  \n+  ########################################################################\n+  def getClusterName( self ):\n+    \"\"\"\n+    It returns the cluster name\n+    \n+    :param self: self reference\n+    \"\"\"\n+    return self.__clusterName\n+  \n+  ########################################################################  \n+  def query( self, index, query ):\n+    \"\"\"It exexutes a query and it returns the result\n+    query is a dictionary. More info: search for elasticsearch dsl\n+    \n+    :param self: self reference\n+    :param dict query: It is the query in ElasticSerach DSL language\n+     \n+    \"\"\"\n+    return self.__client.search( index = index, body = query )\n+  \n+  def _Search( self, indexname ):\n+    \"\"\"\n+    it returns the object which can be used for reatriving ceratin value from the DB\n+    \"\"\"\n+    return  Search( using = self.__client, index = indexname )\n+  \n+  ########################################################################\n+  def _Q( self, name_or_query = 'match', **params ):\n+    \"\"\"\n+    It is a wrapper to ElasticDSL Query module used to create a query object. \n+    :param name_or_query str is the type of the query\n+    \"\"\"\n+    return Q( name_or_query, **params )\n+  \n+  def _A( self, name_or_agg, aggsfilter = None, **params ):\n+    \"\"\"\n+    It us a wrapper to ElasticDSL aggregation module, used to create an aggregation\n+    \"\"\"\n+    return A( name_or_agg, aggsfilter, **params )\n+  ########################################################################\n+  def __tryToConnect( self ):\n+    \"\"\"Before we use the database we try to connect and retrive the cluster name\n+    \n+    :param self: self reference\n+         \n+    \"\"\"\n+    try:\n+      if self.__client.ping():\n+        result = self.__client.info()\n+        self.setClusterName ( result.get( \"cluster_name\", \" \" ) )\n+        self.log.info( \"Database info\", result )\n+        self._connected = True\n+      else:\n+        self._connected = False\n+        self.log.error( \"Cannot connect to the database!\" )\n+    except ConnectionError as e:\n+      self.log.error( e )\n+      self._connected = False \n+\n+  ########################################################################\n+  def getIndexes( self ):\n+    \"\"\"\n+    It returns the available indexes...\n+    \"\"\"\n+    return [ index for index in self.__client.indices.get_aliases() ]\n+  \n+  ########################################################################\n+  def getDocTypes( self, indexName ):\n+    \"\"\"\n+    :param str indexName is the number of the index...\n+    :return S_OK or S_ERROR \n+    \"\"\"\n+    result = []\n+    try:\n+      result = self.__client.indices.get_mapping( indexName )\n+    except Exception as e:\n+      gLogger.error( e )\n+    doctype = ''\n+    for i in result:\n+      if not result[i].get( 'mappings' ) :\n+        return S_ERROR( \"%s does not exists!\" % indexName )\n+      doctype = result[i]['mappings']\n+      break\n+    return S_OK( doctype ) \n+  \n+  ########################################################################\n+  def isExists( self, indexName ):\n+    \"\"\"\n+    it checks the existance of an index\n+    :param str indexName: the name of the index\n+    \"\"\"\n+    return self.__client.indices.exists( indexName )\n+  \n+  ########################################################################\n+  def _generateFullIndexName( self, indexName ):\n+    \"\"\"\n+    Given an index perfix we create the actual index name.\n+    :param str indexName: it is the name of the index\n+    \"\"\"\n+    today = datetime.today().strftime( \"%Y-%m-%d\" )\n+    return \"%s-%s\" % ( indexName, today )\n+  \n+  def createIndex( self, indexPrefix, mapping ):\n+    \"\"\"\n+    :param str indexPrefix: it is the index name. \n+    :param dict mapping: the configuration of the index.\n+    \n+    \"\"\"\n+    result = None\n+    fullIndex = self._generateFullIndexName( indexPrefix )  # we have to create the an index in each day...\n+    if self.isExists( fullIndex ):\n+      result = S_OK( fullIndex )\n+    else:\n+      try:\n+        self.log.info( \"Create index: \", fullIndex + str( mapping ) )\n+        self.__client.indices.create( fullIndex, body = mapping )\n+        result = S_OK( fullIndex )\n+      except Exception as e:\n+        self.log.error( \"Can not create the index:\", e )\n+        result = S_ERROR( e )\n+    return result\n+  \n+  def deleteIndex( self, indexName ):\n+    \"\"\"\n+    :param str indexName the name of the index to be deleted...\n+    \"\"\"\n+    try:\n+      retVal = self.__client.indices.delete( indexName )\n+    except NotFoundError as e:\n+      return S_ERROR(e)\n+    except ValueError as e:\n+      return S_ERROR(e)\n+    \n+    if retVal.get( 'acknowledged' ): \n+      return S_OK(indexName)\n+    else:\n+      return S_ERROR(retVal)\n+  \n+  def index( self, indexName, doc_type, body ):\n+    try:\n+      res = self.__client.index( index = indexName, doc_type = doc_type, body = body )\n+    except TransportError as e:\n+      return S_ERROR(e)\n+    \n+    if res.get( 'created' ):\n+      return S_OK(indexName)\n+    else:\n+      return S_ERROR(res)\n+    \n+  \n+  def bulk_index( self, indexprefix, doc_type, data, mapping = {} ):\n+    \"\"\"\n+    :param str indexPrefix: it is the index name. \n+    :param str doc_type\n+    :param list data contains a list of dictionary \n+    \"\"\"\n+    indexName = self._generateFullIndexName( indexprefix )\n+    if not self.isExists( indexName ):\n+      retVal = self.createIndex( indexprefix, mapping )\n+      if not retVal['OK']:\n+        return retVal\n+    docs = []\n+    for i in data:","path":"Core/Utilities/ElasticSearchDB.py","position":232,"original_position":232,"commit_id":"98a82d18ef0ea14825a56b4b638715ca5d5678a6","original_commit_id":"98a82d18ef0ea14825a56b4b638715ca5d5678a6","user":{"login":"chaen","id":3728211,"avatar_url":"https://avatars.githubusercontent.com/u/3728211?v=3","gravatar_id":"","url":"https://api.github.com/users/chaen","html_url":"https://github.com/chaen","followers_url":"https://api.github.com/users/chaen/followers","following_url":"https://api.github.com/users/chaen/following{/other_user}","gists_url":"https://api.github.com/users/chaen/gists{/gist_id}","starred_url":"https://api.github.com/users/chaen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chaen/subscriptions","organizations_url":"https://api.github.com/users/chaen/orgs","repos_url":"https://api.github.com/users/chaen/repos","events_url":"https://api.github.com/users/chaen/events{/privacy}","received_events_url":"https://api.github.com/users/chaen/received_events","type":"User","site_admin":false},"body":"a more meaningful name than ```i``` ?","created_at":"2016-06-09T08:25:35Z","updated_at":"2016-06-09T08:25:35Z","html_url":"https://github.com/DIRACGrid/DIRAC/pull/2975#discussion_r66400257","pull_request_url":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/2975","_links":{"self":{"href":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/comments/66400257"},"html":{"href":"https://github.com/DIRACGrid/DIRAC/pull/2975#discussion_r66400257"},"pull_request":{"href":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/2975"}}},"pull_request":{"url":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/2975","id":73022445,"html_url":"https://github.com/DIRACGrid/DIRAC/pull/2975","diff_url":"https://github.com/DIRACGrid/DIRAC/pull/2975.diff","patch_url":"https://github.com/DIRACGrid/DIRAC/pull/2975.patch","issue_url":"https://api.github.com/repos/DIRACGrid/DIRAC/issues/2975","number":2975,"state":"open","locked":false,"title":"New [v6r16] Monitoring system","user":{"login":"zmathe","id":981448,"avatar_url":"https://avatars.githubusercontent.com/u/981448?v=3","gravatar_id":"","url":"https://api.github.com/users/zmathe","html_url":"https://github.com/zmathe","followers_url":"https://api.github.com/users/zmathe/followers","following_url":"https://api.github.com/users/zmathe/following{/other_user}","gists_url":"https://api.github.com/users/zmathe/gists{/gist_id}","starred_url":"https://api.github.com/users/zmathe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zmathe/subscriptions","organizations_url":"https://api.github.com/users/zmathe/orgs","repos_url":"https://api.github.com/users/zmathe/repos","events_url":"https://api.github.com/users/zmathe/events{/privacy}","received_events_url":"https://api.github.com/users/zmathe/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-06-08T10:29:44Z","updated_at":"2016-06-09T08:25:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ca4981b2f94307f075af609f367e4d5a66719145","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/2975/commits","review_comments_url":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/2975/comments","review_comment_url":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/comments{/number}","comments_url":"https://api.github.com/repos/DIRACGrid/DIRAC/issues/2975/comments","statuses_url":"https://api.github.com/repos/DIRACGrid/DIRAC/statuses/98a82d18ef0ea14825a56b4b638715ca5d5678a6","head":{"label":"zmathe:el_monitoring","ref":"el_monitoring","sha":"98a82d18ef0ea14825a56b4b638715ca5d5678a6","user":{"login":"zmathe","id":981448,"avatar_url":"https://avatars.githubusercontent.com/u/981448?v=3","gravatar_id":"","url":"https://api.github.com/users/zmathe","html_url":"https://github.com/zmathe","followers_url":"https://api.github.com/users/zmathe/followers","following_url":"https://api.github.com/users/zmathe/following{/other_user}","gists_url":"https://api.github.com/users/zmathe/gists{/gist_id}","starred_url":"https://api.github.com/users/zmathe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zmathe/subscriptions","organizations_url":"https://api.github.com/users/zmathe/orgs","repos_url":"https://api.github.com/users/zmathe/repos","events_url":"https://api.github.com/users/zmathe/events{/privacy}","received_events_url":"https://api.github.com/users/zmathe/received_events","type":"User","site_admin":false},"repo":{"id":2210861,"name":"DIRAC","full_name":"zmathe/DIRAC","owner":{"login":"zmathe","id":981448,"avatar_url":"https://avatars.githubusercontent.com/u/981448?v=3","gravatar_id":"","url":"https://api.github.com/users/zmathe","html_url":"https://github.com/zmathe","followers_url":"https://api.github.com/users/zmathe/followers","following_url":"https://api.github.com/users/zmathe/following{/other_user}","gists_url":"https://api.github.com/users/zmathe/gists{/gist_id}","starred_url":"https://api.github.com/users/zmathe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zmathe/subscriptions","organizations_url":"https://api.github.com/users/zmathe/orgs","repos_url":"https://api.github.com/users/zmathe/repos","events_url":"https://api.github.com/users/zmathe/events{/privacy}","received_events_url":"https://api.github.com/users/zmathe/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/zmathe/DIRAC","description":"DIRAC Grid","fork":true,"url":"https://api.github.com/repos/zmathe/DIRAC","forks_url":"https://api.github.com/repos/zmathe/DIRAC/forks","keys_url":"https://api.github.com/repos/zmathe/DIRAC/keys{/key_id}","collaborators_url":"https://api.github.com/repos/zmathe/DIRAC/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/zmathe/DIRAC/teams","hooks_url":"https://api.github.com/repos/zmathe/DIRAC/hooks","issue_events_url":"https://api.github.com/repos/zmathe/DIRAC/issues/events{/number}","events_url":"https://api.github.com/repos/zmathe/DIRAC/events","assignees_url":"https://api.github.com/repos/zmathe/DIRAC/assignees{/user}","branches_url":"https://api.github.com/repos/zmathe/DIRAC/branches{/branch}","tags_url":"https://api.github.com/repos/zmathe/DIRAC/tags","blobs_url":"https://api.github.com/repos/zmathe/DIRAC/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/zmathe/DIRAC/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/zmathe/DIRAC/git/refs{/sha}","trees_url":"https://api.github.com/repos/zmathe/DIRAC/git/trees{/sha}","statuses_url":"https://api.github.com/repos/zmathe/DIRAC/statuses/{sha}","languages_url":"https://api.github.com/repos/zmathe/DIRAC/languages","stargazers_url":"https://api.github.com/repos/zmathe/DIRAC/stargazers","contributors_url":"https://api.github.com/repos/zmathe/DIRAC/contributors","subscribers_url":"https://api.github.com/repos/zmathe/DIRAC/subscribers","subscription_url":"https://api.github.com/repos/zmathe/DIRAC/subscription","commits_url":"https://api.github.com/repos/zmathe/DIRAC/commits{/sha}","git_commits_url":"https://api.github.com/repos/zmathe/DIRAC/git/commits{/sha}","comments_url":"https://api.github.com/repos/zmathe/DIRAC/comments{/number}","issue_comment_url":"https://api.github.com/repos/zmathe/DIRAC/issues/comments{/number}","contents_url":"https://api.github.com/repos/zmathe/DIRAC/contents/{+path}","compare_url":"https://api.github.com/repos/zmathe/DIRAC/compare/{base}...{head}","merges_url":"https://api.github.com/repos/zmathe/DIRAC/merges","archive_url":"https://api.github.com/repos/zmathe/DIRAC/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/zmathe/DIRAC/downloads","issues_url":"https://api.github.com/repos/zmathe/DIRAC/issues{/number}","pulls_url":"https://api.github.com/repos/zmathe/DIRAC/pulls{/number}","milestones_url":"https://api.github.com/repos/zmathe/DIRAC/milestones{/number}","notifications_url":"https://api.github.com/repos/zmathe/DIRAC/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/zmathe/DIRAC/labels{/name}","releases_url":"https://api.github.com/repos/zmathe/DIRAC/releases{/id}","deployments_url":"https://api.github.com/repos/zmathe/DIRAC/deployments","created_at":"2011-08-15T16:50:01Z","updated_at":"2014-06-13T16:40:38Z","pushed_at":"2016-06-09T08:15:49Z","git_url":"git://github.com/zmathe/DIRAC.git","ssh_url":"git@github.com:zmathe/DIRAC.git","clone_url":"https://github.com/zmathe/DIRAC.git","svn_url":"https://github.com/zmathe/DIRAC","homepage":"http://diracgrid.org","size":39105,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"integration"}},"base":{"label":"DIRACGrid:rel-v6r16","ref":"rel-v6r16","sha":"30738e2ce1b0a817ad5803b0530e056f6fbf3a40","user":{"login":"DIRACGrid","id":694842,"avatar_url":"https://avatars.githubusercontent.com/u/694842?v=3","gravatar_id":"","url":"https://api.github.com/users/DIRACGrid","html_url":"https://github.com/DIRACGrid","followers_url":"https://api.github.com/users/DIRACGrid/followers","following_url":"https://api.github.com/users/DIRACGrid/following{/other_user}","gists_url":"https://api.github.com/users/DIRACGrid/gists{/gist_id}","starred_url":"https://api.github.com/users/DIRACGrid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DIRACGrid/subscriptions","organizations_url":"https://api.github.com/users/DIRACGrid/orgs","repos_url":"https://api.github.com/users/DIRACGrid/repos","events_url":"https://api.github.com/users/DIRACGrid/events{/privacy}","received_events_url":"https://api.github.com/users/DIRACGrid/received_events","type":"Organization","site_admin":false},"repo":{"id":1576831,"name":"DIRAC","full_name":"DIRACGrid/DIRAC","owner":{"login":"DIRACGrid","id":694842,"avatar_url":"https://avatars.githubusercontent.com/u/694842?v=3","gravatar_id":"","url":"https://api.github.com/users/DIRACGrid","html_url":"https://github.com/DIRACGrid","followers_url":"https://api.github.com/users/DIRACGrid/followers","following_url":"https://api.github.com/users/DIRACGrid/following{/other_user}","gists_url":"https://api.github.com/users/DIRACGrid/gists{/gist_id}","starred_url":"https://api.github.com/users/DIRACGrid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DIRACGrid/subscriptions","organizations_url":"https://api.github.com/users/DIRACGrid/orgs","repos_url":"https://api.github.com/users/DIRACGrid/repos","events_url":"https://api.github.com/users/DIRACGrid/events{/privacy}","received_events_url":"https://api.github.com/users/DIRACGrid/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/DIRACGrid/DIRAC","description":"DIRAC Grid","fork":false,"url":"https://api.github.com/repos/DIRACGrid/DIRAC","forks_url":"https://api.github.com/repos/DIRACGrid/DIRAC/forks","keys_url":"https://api.github.com/repos/DIRACGrid/DIRAC/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DIRACGrid/DIRAC/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DIRACGrid/DIRAC/teams","hooks_url":"https://api.github.com/repos/DIRACGrid/DIRAC/hooks","issue_events_url":"https://api.github.com/repos/DIRACGrid/DIRAC/issues/events{/number}","events_url":"https://api.github.com/repos/DIRACGrid/DIRAC/events","assignees_url":"https://api.github.com/repos/DIRACGrid/DIRAC/assignees{/user}","branches_url":"https://api.github.com/repos/DIRACGrid/DIRAC/branches{/branch}","tags_url":"https://api.github.com/repos/DIRACGrid/DIRAC/tags","blobs_url":"https://api.github.com/repos/DIRACGrid/DIRAC/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DIRACGrid/DIRAC/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DIRACGrid/DIRAC/git/refs{/sha}","trees_url":"https://api.github.com/repos/DIRACGrid/DIRAC/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DIRACGrid/DIRAC/statuses/{sha}","languages_url":"https://api.github.com/repos/DIRACGrid/DIRAC/languages","stargazers_url":"https://api.github.com/repos/DIRACGrid/DIRAC/stargazers","contributors_url":"https://api.github.com/repos/DIRACGrid/DIRAC/contributors","subscribers_url":"https://api.github.com/repos/DIRACGrid/DIRAC/subscribers","subscription_url":"https://api.github.com/repos/DIRACGrid/DIRAC/subscription","commits_url":"https://api.github.com/repos/DIRACGrid/DIRAC/commits{/sha}","git_commits_url":"https://api.github.com/repos/DIRACGrid/DIRAC/git/commits{/sha}","comments_url":"https://api.github.com/repos/DIRACGrid/DIRAC/comments{/number}","issue_comment_url":"https://api.github.com/repos/DIRACGrid/DIRAC/issues/comments{/number}","contents_url":"https://api.github.com/repos/DIRACGrid/DIRAC/contents/{+path}","compare_url":"https://api.github.com/repos/DIRACGrid/DIRAC/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DIRACGrid/DIRAC/merges","archive_url":"https://api.github.com/repos/DIRACGrid/DIRAC/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DIRACGrid/DIRAC/downloads","issues_url":"https://api.github.com/repos/DIRACGrid/DIRAC/issues{/number}","pulls_url":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls{/number}","milestones_url":"https://api.github.com/repos/DIRACGrid/DIRAC/milestones{/number}","notifications_url":"https://api.github.com/repos/DIRACGrid/DIRAC/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DIRACGrid/DIRAC/labels{/name}","releases_url":"https://api.github.com/repos/DIRACGrid/DIRAC/releases{/id}","deployments_url":"https://api.github.com/repos/DIRACGrid/DIRAC/deployments","created_at":"2011-04-06T11:47:53Z","updated_at":"2016-05-27T15:25:05Z","pushed_at":"2016-06-09T08:15:50Z","git_url":"git://github.com/DIRACGrid/DIRAC.git","ssh_url":"git@github.com:DIRACGrid/DIRAC.git","clone_url":"https://github.com/DIRACGrid/DIRAC.git","svn_url":"https://github.com/DIRACGrid/DIRAC","homepage":"http://diracgrid.org","size":61038,"stargazers_count":48,"watchers_count":48,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":93,"mirror_url":null,"open_issues_count":107,"forks":93,"open_issues":107,"watchers":48,"default_branch":"integration"}},"_links":{"self":{"href":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/2975"},"html":{"href":"https://github.com/DIRACGrid/DIRAC/pull/2975"},"issue":{"href":"https://api.github.com/repos/DIRACGrid/DIRAC/issues/2975"},"comments":{"href":"https://api.github.com/repos/DIRACGrid/DIRAC/issues/2975/comments"},"review_comments":{"href":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/2975/comments"},"review_comment":{"href":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/DIRACGrid/DIRAC/pulls/2975/commits"},"statuses":{"href":"https://api.github.com/repos/DIRACGrid/DIRAC/statuses/98a82d18ef0ea14825a56b4b638715ca5d5678a6"}}}}
{"actor":{"display_login":"chaen"}}