Impala当前将查询配置文件日志保存在/ var / log / impala / profiles中,每行格式为

<Epoch-Timestamp> <QueryID> <zlib-compressed-data>

正如他们在https://impala.apache.org/docs/build/html/topics/impala_logging.html中的文档中所述

“为了节省空间,这些查询配置文件现在存储在/ var / log / impala / profiles中的zlib压缩文件中。”

我想使用一些实用程序而不是在25000年公开的Web UI以人类可读的格式解码/解压缩zlib压缩的数据。

从日志和文档中,我已经能够确定zlib压缩的数据已使用base64进行了编码。
我能够编写python代码来解压缩zlib-compression,
import base64
import datetime
import zlib

profile_data = "1587093056765 c94ef1f2e35015a2:feb1867165d545a7 eJyVVE1P1EAYLkhkXRBcI7ANMRlvkMhm+rXd3ehh2S1xI4LS5eNgYqadtzChtMt0yoe/gHg1MR78Df4AD540MSYevHry6MEf4NEpFVwImJgmk74znfd5n+d536r3ynefpMAP0Qyj9/26CYEW6GBYWLOI3gjA02pVW6ta1DItYs9ODKl3y6VORHzB9qAbCxJ22Q5MFCcVpXztbDw5UJpW1MK0PBl2050dwg8nlP+7Xjoaa8VRBL4AilYT4EM8jsVIK445ZRERMVd3U+ZvJ4JwUfHDOKXASUPXMcaFdnsRdQ97MNpacZpd51m3Ob/oFNsQkDQUqO2NwEEPuISLRDLWhhA2yQmMUnAiirJSbutYx3PYnNNshI2GhhtWtWJXzVrNkBhjnZ0eCQlaA56wOFpnxyFFe3mM9IpVwXM+3bIqdgWjFWfRaboOmvFSFlJEqBFYhBIPaGBVA6h6tA5AjLpm2j6u2r5vWbqNjdnxJRD7Md9GTUo5JMm4pst08tEahqFZ+nRu4XJPSNAEzUQSmuY8Z5WR/NAVkl1hobPUcR847dG/m2kyuPywmMeZXFekbkVXomQEOu07dcvEZl2npmlbdc8LGnUc4JqODewR3dAIjJ58nN0ennccd725cd3dDXPMTN8pn4N8RYJ4oVw1NHOAWCRmi25m3OVCm5ptWpmZQ6fmq79KfdWdwe7LdupfH7F+Ic7wP+fiMda5vjvXH+cN6euqs8T7W/VfLp0263Q2IYp6VS0o5bE/tUsaIYtAXVN+vvy++vrNx0+Db799+Zwv6sZ4ThsOwE+z1KXHIYkiFm2igEUs2QJ6YwV2U0jE6UZpgXEZ8ngfBSD87JPViMMmSwRwtJvByoEczXVxgct+lqP7tHyzReSIxpvLPUeiZYVxOasfvr77MaCUb7VCJikvZAnXCRMnx6/eHw0ql0791Eq8/0iqxRkJ2XOSETi5ePkvZeCFUruglgsruAxAUX4DOJOTpw=="

pdata = profile_data.split(" ")

ts = datetime.datetime.fromtimestamp(int(pdata[0]) / 1000.0).isoformat()
queryID = pdata[1]

encodedData = base64.b64decode(pdata[2])
zlib_data = zlib.decompress(encodedData)

print(zlib_data)

上面的Python实用工具提供了以下输出,其中包含一些有意义的信息,但并不完整。
b'\x19<\x18,Query (id=c94ef1f2e35015a2:feb1867165d545a7)\x15\x04\x19,\x18\x11InactiveTotalTime\x15\n\x16\x00\x00\x18\tTotalTime\x15\n\x16\x00\x00\x16\x01\x11\x1b\x00\x19\x08\x1b\x00\x00\x18\x07Summary\x15\x00\x19,\x18\x11InactiveTotalTime\x15\n\x16\x00\x00\x18\tTotalTime\x15\n\x16\x00\x00\x16\x01\x11\x1b\x11\x88\x0eConnected User\x04root\x0bCoordinator\x19quickstart.cloudera:22000\x08DDL Type\x0cCREATE_TABLE\nDefault Db\x0bexperiments\x0eDelegated User\x00\x08End Time\x1d2020-04-17 03:10:56.764883000\x0eImpala VersionWimpalad version 2.5.0-cdh5.7.0 RELEASE (build ad3f5adabedf56fe6bd9eea39147c067cc552703)\x0fNetwork Address\x0f127.0.0.1:33152\x1bQuery Options (non default)\x00\x0bQuery State\x08FINISHED\x0cQuery Status\x02OK\nQuery Type\x03DDL\nSession ID!9540492d44759bbf:90f082030ba231ae\x0cSession Type\x07BEESWAX\rSql Statement\x17create table t1 (x int)\nStart Time\x1d2020-04-17 03:10:56.417452000\x04User\x04root\x19\xf8\x11\nSession ID\x0cSession Type\nStart Time\x08End Time\nQuery Type\x0bQuery State\x0cQuery Status\x0eImpala Version\x04User\x0eConnected User\x0eDelegated User\x0fNetwork Address\nDefault Db\rSql Statement\x0bCoordinator\x1bQuery Options (non default)\x08DDL Type\x1b\x00\x19,\x18\x00\x19\x06\x19\x08\x00\x18\x0eQuery Timeline\x19V\x00\xec\x93\xe0U\x98\x9c\xc5\xc8\x02\xae\xda\xcd\xca\x02\xae\xda\xcd\xca\x02\x19X\x0fStart execution\x11Planning finished\x10Request finished\x11First row fetched\x10Unregister query\x00\x00\x18\x0cImpalaServer\x15\x00\x19\\\x18\x12CatalogOpExecTimer\x15\n\x16\xc4\xd1\xba\xe8\x01\x00\x18\x14ClientFetchWaitTimer\x15\n\x16\x96\xbe\x88\x02\x00\x18\x11InactiveTotalTime\x15\n\x16\x00\x00\x18\x17RowMaterializationTimer\x15\n\x16\x00\x00\x18\tTotalTime\x15\n\x16\x00\x00\x16\x01\x11\x1b\x00\x19\x08\x1b\x01\x8a\x008\x12CatalogOpExecTimer\x14ClientFetchWaitTimer\x17RowMaterializationTimer\x00\x00'


以编程方式理解/解析Impala配置文件日志的任何指针都是很有意义的。

最佳答案

更新。 编辑为包括源代码和一些注释。

我猜这是您要查找的脚本(摘自Impala Git here):

    import base64
    import datetime
    import zlib
    from thrift.protocol import TCompactProtocol
    from thrift.TSerialization import deserialize
    from RuntimeProfile.ttypes import TRuntimeProfileTree

    def decode_profile_line(line):
      space_separated = line.split(" ")
      if len(space_separated) == 3:
        ts = int(space_separated[0])
        print datetime.datetime.fromtimestamp(ts / 1000.0).isoformat(), space_separated[1]
        base64_encoded = space_separated[2]
      elif len(space_separated) == 1:
        base64_encoded = space_separated[0]
      else:
        raise Exception("Unexpected line: " + line)
      possibly_compressed = base64.b64decode(base64_encoded)
      # Handle both compressed and uncompressed Thrift profiles
      try:
        thrift = zlib.decompress(possibly_compressed)
      except zlib.error:
        thrift = possibly_compressed

      tree = TRuntimeProfileTree()
      deserialize(tree, thrift, protocol_factory=TCompactProtocol.TCompactProtocolFactory())
      tree.validate()

    return tree

    encoded_line = "timestamp queryid encoded_profile_string"
    decoded_tree = decode_profile_line(encoded_line)

基本上,它的功能与您的代码片段中的功能相同,但是之后还会解密Thrift特定的编码。 “thrift”代表Apache Thrift本身的库(有关更多信息,请参见Apache Thrift的docsGit),RuntimeProfile是Impala的结构定义(您可以在Impala Git中查看),其中包含节点和脚本执行摘要:
    // A flattened tree of runtime profiles, obtained by an
    // pre-order traversal
    struct TRuntimeProfileTree {
      1: required list<TRuntimeProfileNode> nodes
      2: optional ExecStats.TExecSummary exec_summary
    }

让我们仔细看看Thrift中的"deserialize"方法:
    def deserialize(base,
            buf,
            protocol_factory=TBinaryProtocol.TBinaryProtocolFactory()):
      transport = TTransport.TMemoryBuffer(buf)
      protocol = protocol_factory.getProtocol(transport)
      base.read(protocol)
      return base

“base”代表一棵将返回给您的树,其中包含所有的节点和子节点。因此,有两种选择可以从这里开始:
  • 浏览Impala代码;似乎所有必需的定义都存储在其Git的subfolder中;可以复制他们的逻辑。
  • 编写自定义的“反序列化”并调试“protocol_factory.getProtocol(transport)”的输出以定义“基础”树(再次:在Impala源代码中查找必要的节点可能会容易一些)。
  • 关于python - 如何了解Apache Impala的zlib压缩查询配置文件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61296108/

    10-16 16:42