{"id":1337,"date":"2020-10-20T03:02:50","date_gmt":"2020-10-20T01:02:50","guid":{"rendered":"http:\/\/blog.zhaw.ch\/splab\/?p=1337"},"modified":"2020-10-19T22:48:33","modified_gmt":"2020-10-19T20:48:33","slug":"deep-tracing-of-cloud-function-execution","status":"publish","type":"post","link":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/","title":{"rendered":"Deep tracing of cloud function execution"},"content":{"rendered":"\n<p>In an increasingly self-aware and knowledge-driven software world, understanding the execution behaviour of an application is mandatory for cost-effective delivery. This applies especially to cloud functions, because many complex applications are composed of those functions. Similar short-lived, event-driven processing models can be found inside databases and message brokers. This means systematic tracing of cloud functions should be conducted so that a large variety of applications benefits from rightsizing memory allocation and associated fair microbilling.<\/p>\n\n\n\n<p>We <a href=\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/10\/wosc-paper-accepted-revisiting-pay-per-use-models-in-serverless-applications\/\" data-type=\"post\" data-id=\"1330\">recently reported<\/a> on our upcoming presentation on generating static trace profiles for cloud functions. In general, tracing techniques help reporting with high precision how much memory an application requires. But in practice, the memory needs depend on a number of factors that change over time. Similar to how static environment variables have been replaced by dynamic queries to updateable key-value stores to increase dynamics, we should be able to produce dynamic traces that show at least a correlation to certain values within the function, like the number of rows in a table. This research blog post shows one approach to do that.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"480\" src=\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png\" alt=\"\" class=\"wp-image-1338\" srcset=\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png 640w, https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines-300x225.png 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n\n\n\n<!--more-->\n\n\n\n<p>Given that many cloud functions are written in programming languages that allow for dynamic in(tro)spection, one technique is to create a wrapper function that executes the actual function code in a second thread. The main thread performs a parallel measurement of the consumed memory and event-triggered peeks into the local variables, including the input parameters, of the executed function. The figure above shows that this works in principle. Using the <code>tracemalloc<\/code> module of Python, an application processing lines in text files is observed, and the memory consumption is found to be directly proportional to the number of lines in each file, represented through a local <code>lines<\/code> variable. An excerpt of an exemplary function, abstracted from a concrete FaaS syntax, is shown below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def mainfunction():\n    datfiles = glob.glob(\"*.dat\")\n\n    for datfile in datfiles:\n        print(datfile)\n        tx = time.time()\n        f = open(datfile)\n        lines = f.readlines()\n        ....<\/code><\/pre>\n\n\n\n<p>Correlation is not causation, and thus the assignment of any value to the <code>lines<\/code> variable does not necessarily imply that the memory needs are a result of the assignment being executed. Rather, the preceeding <code>readlines<\/code> call pumps data into the memory, and the only way to know that beforehand is to inspect the <code>f<\/code> variable. Tracing the entire function execution is costly &#8211; doing so only in a learning\/training phase, and then using selective breakpoints (for instance just after assigning the value of <code>f<\/code>) suggests that a high-performance solution may be available.<\/p>\n\n\n\n<p>Is this only working with a locally executed function as shown above? No. Another function whose execution time and memory consumption depends on a randomly generated variable is deployed to Google Cloud Functions and traced while executing there. The correlation between the variable and the memory consumption is crystal-clear, as indicated by the next figure (note log scale on the y axis). The dropping lines by the end of each spectrum signal that the function execution has just ended whereas the memory is measured one more time before the wrapper terminates as well.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"480\" src=\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/multimem-gcf.png\" alt=\"\" class=\"wp-image-1339\" srcset=\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/multimem-gcf.png 640w, https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/multimem-gcf-300x225.png 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n\n\n\n<p>This contrasts the standard memory measurements in Google Cloud Functions (and similar ones by other providers) that give basic statistical distributions on memory consumption, but do not break this down to per-function instance and especially not to any variable values during the execution. A screenshot is shown below. The Google Cloud Monitoring\/Stackdriver APIs give a few more metrics, but again not the same level of detail and real application-level insights.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"630\" height=\"366\" src=\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/multimem-stackdriver.png\" alt=\"\" class=\"wp-image-1340\" srcset=\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/multimem-stackdriver.png 630w, https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/multimem-stackdriver-300x174.png 300w\" sizes=\"auto, (max-width: 630px) 100vw, 630px\" \/><\/figure>\n\n\n\n<p>While the work explained here is preliminary research, the early results are promising that by combining function wrapping with tracing, machine learning, breakpoint injection and dynamic vertical scalability features of the underlying execution architectures, application engineers will be able to determine more precisely how much memory was spent by the software in operation. And especially, why. We will continue to investigate with the aim of bringing the best serverless and cloud-native technologies to a broader market.<\/p>\n<div class=\"pt-sm\">Schlagw\u00f6rter: <a href=\"http:\/\/blog.zhaw.ch\/splab\/tag\/configuration\/\">configuration<\/a>, <a href=\"http:\/\/blog.zhaw.ch\/splab\/tag\/faas\/\">faas<\/a>, <a href=\"http:\/\/blog.zhaw.ch\/splab\/tag\/googlecloud\/\">googlecloud<\/a>, <a href=\"http:\/\/blog.zhaw.ch\/splab\/tag\/memory\/\">memory<\/a>, <a href=\"http:\/\/blog.zhaw.ch\/splab\/tag\/serverless\/\">serverless<\/a>, <a href=\"http:\/\/blog.zhaw.ch\/splab\/tag\/software-development\/\">software development<\/a>, <a href=\"http:\/\/blog.zhaw.ch\/splab\/tag\/tracing\/\">tracing<\/a><br><\/div>","protected":false},"excerpt":{"rendered":"<p>In an increasingly self-aware and knowledge-driven software world, understanding the execution behaviour of an application is mandatory for cost-effective delivery. This applies especially to cloud functions, because many complex applications are composed of those functions. Similar short-lived, event-driven processing models can be found inside databases and message brokers. This means systematic tracing of cloud functions [&hellip;]<\/p>\n","protected":false},"author":203,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[4],"tags":[176,7,165,102,8,49,175],"features":[],"class_list":["post-1337","post","type-post","status-publish","format-standard","hentry","category-research","tag-configuration","tag-faas","tag-googlecloud","tag-memory","tag-serverless","tag-software-development","tag-tracing"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Deep tracing of cloud function execution - Service Prototyping Lab<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Deep tracing of cloud function execution\" \/>\n<meta property=\"og:description\" content=\"In an increasingly self-aware and knowledge-driven software world, understanding the execution behaviour of an application is mandatory for cost-effective delivery. This applies especially to cloud functions, because many complex applications are composed of those functions. Similar short-lived, event-driven processing models can be found inside databases and message brokers. This means systematic tracing of cloud functions [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/\" \/>\n<meta property=\"og:site_name\" content=\"Service Prototyping Lab\" \/>\n<meta property=\"article:published_time\" content=\"2020-10-20T01:02:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png\" \/>\n<meta name=\"author\" content=\"Josef Spillner\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Josef Spillner\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/\"},\"author\":{\"name\":\"Josef Spillner\",\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/#\/schema\/person\/33a5227c6cc1fa3329279d33c3cc440e\"},\"headline\":\"Deep tracing of cloud function execution\",\"datePublished\":\"2020-10-20T01:02:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/\"},\"wordCount\":634,\"commentCount\":0,\"image\":{\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png\",\"keywords\":[\"configuration\",\"faas\",\"googlecloud\",\"memory\",\"serverless\",\"software development\",\"tracing\"],\"articleSection\":[\"Research\"],\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/\",\"url\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/\",\"name\":\"Deep tracing of cloud function execution - Service Prototyping Lab\",\"isPartOf\":{\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png\",\"datePublished\":\"2020-10-20T01:02:50+00:00\",\"author\":{\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/#\/schema\/person\/33a5227c6cc1fa3329279d33c3cc440e\"},\"breadcrumb\":{\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#primaryimage\",\"url\":\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png\",\"contentUrl\":\"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\/\/blog.zhaw.ch\/splab\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Deep tracing of cloud function execution\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/#website\",\"url\":\"https:\/\/blog.zhaw.ch\/splab\/\",\"name\":\"Service Prototyping Lab\",\"description\":\"A Blog of the ZHAW Zurich University of Applied Sciences\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.zhaw.ch\/splab\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.zhaw.ch\/splab\/#\/schema\/person\/33a5227c6cc1fa3329279d33c3cc440e\",\"name\":\"Josef Spillner\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/c57d7019e91373902c08eac230e003cb4f8498ecf68c9d119e9ecb82fdf6c400?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/c57d7019e91373902c08eac230e003cb4f8498ecf68c9d119e9ecb82fdf6c400?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/c57d7019e91373902c08eac230e003cb4f8498ecf68c9d119e9ecb82fdf6c400?s=96&d=mm&r=g\",\"caption\":\"Josef Spillner\"},\"description\":\"Head of the Service Prototyping Lab. Research on distributed systems and application computing paradigms. Senior lecturer at Zurich University of Applied Sciences.\",\"url\":\"https:\/\/blog.zhaw.ch\/splab\/author\/spio\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Deep tracing of cloud function execution - Service Prototyping Lab","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/","og_locale":"en_GB","og_type":"article","og_title":"Deep tracing of cloud function execution","og_description":"In an increasingly self-aware and knowledge-driven software world, understanding the execution behaviour of an application is mandatory for cost-effective delivery. This applies especially to cloud functions, because many complex applications are composed of those functions. Similar short-lived, event-driven processing models can be found inside databases and message brokers. This means systematic tracing of cloud functions [&hellip;]","og_url":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/","og_site_name":"Service Prototyping Lab","article_published_time":"2020-10-20T01:02:50+00:00","og_image":[{"url":"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png","type":"","width":"","height":""}],"author":"Josef Spillner","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Josef Spillner","Estimated reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#article","isPartOf":{"@id":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/"},"author":{"name":"Josef Spillner","@id":"https:\/\/blog.zhaw.ch\/splab\/#\/schema\/person\/33a5227c6cc1fa3329279d33c3cc440e"},"headline":"Deep tracing of cloud function execution","datePublished":"2020-10-20T01:02:50+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/"},"wordCount":634,"commentCount":0,"image":{"@id":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png","keywords":["configuration","faas","googlecloud","memory","serverless","software development","tracing"],"articleSection":["Research"],"inLanguage":"en-GB","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/","url":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/","name":"Deep tracing of cloud function execution - Service Prototyping Lab","isPartOf":{"@id":"https:\/\/blog.zhaw.ch\/splab\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#primaryimage"},"image":{"@id":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png","datePublished":"2020-10-20T01:02:50+00:00","author":{"@id":"https:\/\/blog.zhaw.ch\/splab\/#\/schema\/person\/33a5227c6cc1fa3329279d33c3cc440e"},"breadcrumb":{"@id":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/"]}]},{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#primaryimage","url":"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png","contentUrl":"https:\/\/blog.zhaw.ch\/splab\/files\/2020\/10\/mem-lines.png"},{"@type":"BreadcrumbList","@id":"https:\/\/blog.zhaw.ch\/splab\/2020\/10\/20\/deep-tracing-of-cloud-function-execution\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/blog.zhaw.ch\/splab\/"},{"@type":"ListItem","position":2,"name":"Deep tracing of cloud function execution"}]},{"@type":"WebSite","@id":"https:\/\/blog.zhaw.ch\/splab\/#website","url":"https:\/\/blog.zhaw.ch\/splab\/","name":"Service Prototyping Lab","description":"A Blog of the ZHAW Zurich University of Applied Sciences","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.zhaw.ch\/splab\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Person","@id":"https:\/\/blog.zhaw.ch\/splab\/#\/schema\/person\/33a5227c6cc1fa3329279d33c3cc440e","name":"Josef Spillner","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/c57d7019e91373902c08eac230e003cb4f8498ecf68c9d119e9ecb82fdf6c400?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/c57d7019e91373902c08eac230e003cb4f8498ecf68c9d119e9ecb82fdf6c400?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c57d7019e91373902c08eac230e003cb4f8498ecf68c9d119e9ecb82fdf6c400?s=96&d=mm&r=g","caption":"Josef Spillner"},"description":"Head of the Service Prototyping Lab. Research on distributed systems and application computing paradigms. Senior lecturer at Zurich University of Applied Sciences.","url":"https:\/\/blog.zhaw.ch\/splab\/author\/spio\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/posts\/1337","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/users\/203"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/comments?post=1337"}],"version-history":[{"count":1,"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/posts\/1337\/revisions"}],"predecessor-version":[{"id":1341,"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/posts\/1337\/revisions\/1341"}],"wp:attachment":[{"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/media?parent=1337"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/categories?post=1337"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/tags?post=1337"},{"taxonomy":"features","embeddable":true,"href":"https:\/\/blog.zhaw.ch\/splab\/wp-json\/wp\/v2\/features?post=1337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}