Creating nested log entries in Cloud Logging Viewer from API? - google-cloud-logging

I'd like to publish logs from a custom app running on a compute engine to the cloud logging API.
However, I'd like to get nested logs (like AppEngine loglines). Is this possible through the api?

This use-case is explained in the AppEngline Logs docs.
Make sure to also set the traceId fields to non-null values on the request and app logs which you are sending. Here's sample code in Scala:
import com.google.cloud.MonitoredResource
import com.google.cloud.logging.Payload._
import com.google.cloud.logging._
import collection.JavaConverters._
import org.threeten.bp.Duration
val logging = LoggingOptions.getDefaultInstance().getService()
val traceId = "keasdfwxcbrbntpoiuwehrtiojsadf";
var firstEntry = {
LogEntry.newBuilder(StringPayload.of("string-payload-one"))
.setSeverity(Severity.DEBUG)
.setLogName("app")
.setTimestamp(1519955138399L)
.setResource(MonitoredResource.newBuilder("global").build())
.setLabels(Map("environment" -> "testing").asJava)
.setTrace(traceId)
.build()
}
var midEntry = {
LogEntry.newBuilder(StringPayload.of("string-payload-two"))
.setSeverity(Severity.INFO)
.setLogName("request")
.setResource(MonitoredResource.newBuilder("global").build())
.setHttpRequest(HttpRequest.newBuilder().setStatus(200).setRequestUrl("/about-us").setLatency(Duration.ofMillis(1234)).build())
.setTimestamp(1519955137906L)
.setLabels(Map("environment" -> "testing").asJava)
.setTrace(traceId)
.build()
}
var lastEntry = {
LogEntry.newBuilder(StringPayload.of("string-payload-three"))
.setSeverity(Severity.DEBUG)
.setLogName("app")
.setResource(MonitoredResource.newBuilder("global").build())
.setTimestamp(1519955138523L)
.setLabels(Map("environment" -> "testing").asJava)
.setTrace(traceId)
.build()
}
logging.write(List(firstEntry, midEntry, lastEntry).asJava)
At the end, the log entries should show up both in their individual logs and "cross-logged" as children of their requests, like this:

This is not documented as it should be (per this answer circa 2016), but if you inspect a LogEntry from GAE, you should be able to reproduce it from elsewhere. Here's an example:
{
"httpRequest": {
"status": 500
},
"insertId": "5a93c0d800088625d8b7e45f",
"labels": {
"clone_id": "00c61b117c43aee4462ccf2cc75fa0a439d65d89992032719b9f34b7b4fa341bf0d3b7de"
},
"logName": "projects/matchmaker/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5a93be8000ff0e7e83cece7ced0001737e70726f6a656374736572656e6469700001323031373131323474313631353036000100",
"last": true,
"producer": "appengine.googleapis.com/request_id"
},
"protoPayload": {
"#type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appEngineRelease": "1.9.54",
"appId": "s~matchmaker",
"cost": 3.5092199999999997e-07,
"endTime": "2018-02-26T08:10:00.558238Z",
"finished": true,
"host": "matchmaker.appspot.com",
"httpVersion": "HTTP/1.1",
"instanceId": "00c61b117c43aee4462ccf2cc75fa0a439d65d89992032719b9f34b7b4fa341bf0d3b7de",
"instanceIndex": -1,
"ip": "0.1.0.1",
"latency": "599.608347s",
"line": [
{
"logMessage": "mail_body: Hi X and Y,<br>\n<br>\nYou've been matched!<br>\n<br>\nGo forth and one-on-one, and may it be as awesome as a peregrine falcon soaring\nthrough the rays of a setting sun.<br>\n<br>\nCheers,<br>\nProject Lemma<br>\n<br>\nPS: I'm not a calendar (yet) so it's up to you two to find a time to meet.",
"severity": "INFO",
"sourceLocation": {
"file": "/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/models/match.py",
"functionName": "send_email_and_put",
"line": "47"
},
"time": "2018-02-26T08:09:41.148490Z"
},
{
"logMessage": "Traceback (most recent call last):\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/runtime/wsgi.py\", line 267, in Handle\n result = handler(dict(self._environ), self._StartResponse)\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/lib/flask/app.py\", line 2000, in __call__\n return self.wsgi_app(environ, start_response)\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/lib/flask/app.py\", line 1988, in wsgi_app\n response = self.full_dispatch_request()\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/lib/flask/app.py\", line 1639, in full_dispatch_request\n rv = self.dispatch_request()\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/lib/flask/app.py\", line 1625, in dispatch_request\n return self.view_functions[rule.endpoint](**req.view_args)\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/cron/__init__.py\", line 11, in matches\n for match in all_matches():\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/cron/matches.py\", line 21, in all_matches\n possibilities = {u.key: u.possible_matches for u in avail}\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/cron/matches.py\", line 21, in <dictcomp>\n possibilities = {u.key: u.possible_matches for u in avail}\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/models/user.py\", line 64, in possible_matches\n return sorted(matches, reverse=True)\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/models/match.py\", line 19, in __cmp__\n return cmp(self.score, other.score)\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/models/match.py\", line 71, in score\n total_capacity = sum(f.get().cur_capacity for f in self.folks)\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/models/match.py\", line 71, in <genexpr>\n total_capacity = sum(f.get().cur_capacity for f in self.folks)\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/models/user.py\", line 33, in cur_capacity\n return int(self.settings['freq']) - len(self.cur_matches)\n File \"/base/data/home/apps/s~matchmaker/20171124t161506.405758693491065379/models/user.py\", line 47, in cur_matches\n ).fetch(1000)\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/ext/ndb/utils.py\", line 160, in positional_wrapper\n return wrapped(*args, **kwds)\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/ext/ndb/query.py\", line 1218, in fetch\n return self.fetch_async(limit, **q_options).get_result()\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py\", line 383, in get_result\n self.check_success()\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py\", line 378, in check_success\n self.wait()\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py\", line 362, in wait\n if not ev.run1():\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/ext/ndb/eventloop.py\", line 268, in run1\n delay = self.run0()\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/ext/ndb/eventloop.py\", line 230, in run0\n callback(*args, **kwds)\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py\", line 433, in _help_tasklet_along\n ns = namespace_manager.get_namespace()\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/api/namespace_manager/namespace_manager.py\", line 86, in get_namespace\n name = os.environ.get(_ENV_CURRENT_NAMESPACE, None)\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_dist/lib/python2.7/_abcoll.py\", line 382, in get\n return self[key]\n File \"/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/runtime/request_environment.py\", line 125, in __getitem__\n def __getitem__(self, key):\n DeadlineExceededError: The overall deadline for responding to the HTTP request was exceeded.",
"severity": "ERROR",
"sourceLocation": {
"file": "/base/alloc/tmpfs/dynamic_runtimes/python27/a7637d5531ec9deb_unzipped/python27_lib/versions/1/google/appengine/runtime/wsgi.py",
"functionName": "Handle",
"line": "279"
},
"time": "2018-02-26T08:10:00.549690Z"
}
],
"megaCycles": "34946",
"method": "GET",
"requestId": "5a93be8000ff0e7e83cece7ced0001737e70726f6a656374736572656e6469700001323031373131323474313631353036000100",
"resource": "/cron/matches",
"startTime": "2018-02-26T08:00:00.949891Z",
"status": 500,
"taskName": "f5915e6b03b632b41d45204c6686840b",
"taskQueueName": "__cron",
"urlMapEntry": "cron.APP",
"userAgent": "AppEngine-Google; (+http://code.google.com/appengine)",
"versionId": "20171124t161506"
},
"receiveTimestamp": "2018-02-26T08:10:00.564188790Z",
"resource": {
"labels": {
"module_id": "default",
"project_id": "matchmaker",
"version_id": "20171124t161506",
"zone": "us2"
},
"type": "gae_app"
},
"severity": "ERROR",
"timestamp": "2018-02-26T08:00:00.949891Z"
}

3 years later and here we go....
That concept from app engine is grouping by long running operations
You just need to specify the paramether operation in the api call with the object LogentryOperation
Here is the reference for this object
https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogEntryOperation

Related

Cannot get ui_guage to display each message after specified delay time

My experiment is to change the ui_guage according to the numbers from a csv file. Each number is delayed for 5 sec.(code at end)
Input to csv file is a multi-line msg.payload with three values per line.i.e,
name1, numerical1,numerical11
name2 numerical2,numerical22, etc
problem: i get no delay of 5sec per message on the gauge...it directly shows the final value present in the last column (i have used a delay node also but still...)
example: display column 3 numericals as indicator with 5 sec delay on gauge.
gauge output: numerical22 (the indicator sets to this position at once)
So, the required per message delay (5 sec) is absent.
I require the delay.
I'am working on IBM cloud lite plan, node red v1.0.6
please review the following code
any help is welcome
if similar is answered before please re-direct me the solution.
To run following code:
open Node-RED
Click the three lines (top right)
import
Copy & paste the following flow json code and click "import" button
know more : Importing and Exporting Flows in Node-RED
The code:
[
{
"id": "c9b43c3a.da2e4",
"type": "ui_gauge",
"z": "ac0d0d22.69ebb",
"name": "",
"group": "c604d450.9712c8",
"order": 13,
"width": "5",
"height": "5",
"gtype": "gage",
"title": "<img height=\"50\" width=\"50\" src=\"https://upload.wikimedia.org/wikipedia/commons/b/bf/Pressure_gauge.svg\"/>",
"label": "units",
"format": " {{msg.payload.col3}}",
"min": 0,
"max": 10,
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "",
"seg2": "",
"x": 840,
"y": 320,
"wires": []
},
{
"id": "c604d450.9712c8",
"type": "ui_group",
"z": "",
"name": "tab1",
"tab": "c733c61c.6e4828",
"order": 1,
"disp": true,
"width": "12",
"collapse": false
},
{
"id": "c733c61c.6e4828",
"type": "ui_tab",
"z": "",
"name": "Home1",
"icon": "dashboard",
"disabled": false,
"hidden": false
}
]

Test and convert avro schema (.avsc) to .avro. AttributeError, array and encoding

I'm just starting hadoop, and I'm using Avro (fastavro).
1- I want to validate schema and convert to .avro file.
{
"type": "record",
"name": "Node",
"fields": [
{
"name": "nom",
"type": "string"
},
{
"name": "zone",
"type": {
"type": "map",
"values": "string"
}
},
{
"name": "price",
"type": "float"
},
{
"name": "type",
"type": "string"
}
]
}
My test file (validate schema) :
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import json
import fastavro
schema = json.load(open("myschema.avsc"))
records = [
{
"nom": "blabla",
"zone": ["north", "south", "east"],
"prix": 4.0,
"type": "geoloc"
}
]
fastavro.writer(open("myschema.avro", "wb"), schema, records)
I've this error :
Traceback (most recent call last):
File "test-schema.py", line 17, in <module>
fastavro.writer(open("myschema.avro", "wb"), schema, records)
File "/var/www/data-machine/HDFS/env/lib/python3.5/site-packages/fastavro/writer.py", line 614, in writer
output.write(record)
File "/var/www/data-machine/HDFS/env/lib/python3.5/site-packages/fastavro/writer.py", line 537, in write
write_data(self.io, record, self.schema)
File "/var/www/data-machine/HDFS/env/lib/python3.5/site-packages/fastavro/writer.py", line 432, in write_data
return fn(fo, datum, schema)
File "/var/www/data-machine/HDFS/env/lib/python3.5/site-packages/fastavro/writer.py", line 363, in write_record
name, field.get('default')), field['type'])
File "/var/www/data-machine/HDFS/env/lib/python3.5/site-packages/fastavro/writer.py", line 432, in write_data
return fn(fo, datum, schema)
File "/var/www/data-machine/HDFS/env/lib/python3.5/site-packages/fastavro/writer.py", line 232, in write_map
for key, val in iteritems(datum):
File "/var/www/data-machine/HDFS/env/lib/python3.5/site-packages/fastavro/six.py", line 27, in py3_iteritems
return obj.items()
AttributeError: 'list' object has no attribute 'items'
2- And, if I add an array :
{
"name": "ingredients",
"type": ["string"]
},
The error :
File "/var/www/data-machine/HDFS/env/lib/python3.5/site-packages/fastavro/writer.py", line 345, in write_union
raise ValueError(msg)
ValueError: ["north", "south", "east"] (type <class 'list'>) do not match ['string']
And, finishing, I want to make the "zone" field optionnal...
Thanks :)
Fabrice
Your record information for the map is wrong. It is expecting something like
"zone":{"key1":"val1","key2":"val2","key3":"val3"},
it is a map, not a set. If you want something like your example, you will need to use an array instead of a map

"Creating Apps in Kivy" openweathermap API Key Error

That's my first stackoverflow question.
I started with kivy and bought the book "Crating Apps in Kivy" from Dusty Phillips and all went well till he got to the openweatherapp chapter. (Which after a search other users had problems too...)
There you use the Openweather API to search for a location with a button and it should print the results in a list.
It's not the original code anymore. Others pointed out that the Link to the website changed, you have to use the API key. Of course I linked it correctly, I just typed "myAPIKey" here so it's not accesssable. The JSOn File on the bottom is what the site prints!
Also, the book formated cities in found location like that: d['name], d['sys']['country'] which I guess was also wrong, maybe the site changed here too?
My problem is that the UrlRequest from kivy doesn't seem to load anything. Or the iteration in found location is wrong, I don't know. It always says "KeyError: city" And I guess it's because it doesn't read it correctly at all. I tried a different approach with the python class requests - and it works perfectly fine! But I still want to know why this solution doesn't work.
My Questions: Where is my error with the json iteration? I have really problems with understanding because I'm also new to python.
Also: Why is request in the methode head? Where is it used?
Here the code from the book (I hope everything is typed correctly. If there is still an error with variables please point it out but I typed the code multiple times - my problem will probably be somewhere else...):
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.network.urlrequest import UrlRequest
import json
class AddLocationForm(BoxLayout):
search_input = ObjectProperty()
search_results = ObjectProperty()
def search_location(self):
search_template = "http://api.openweathermap.org/data/2.5/forecast/daily?APPID=myAPIKey=" + "{}"
search_url = search_template.format(self.search_input.text)
request = UrlRequest(search_url, self.found_location)
def found_location(self, request, data):
data = json.loads(data.decode()) if not isinstance(data, dict) else data
cities = ["{} ({})".format(d["city"]["name"], d["city"]["country"])for d in data["list"]]
self.search_results.item_strings = cities
KV File:
AddLocationForm:
<AddLocationForm>:
orientation: "vertical"
search_input: search_box
search_results: search_results_list
BoxLayout:
height: "40dp"
size_hint_y: None
TextInput:
id: search_box
size_hint_x: 50
Button:
text: "Search"
size_hint_x: 25
on_press: root.search_location()
Button:
text: "Current Location"
size_hint_x: 25
ListView:
id: search_results_list
item_strings: []
JSON File:
{
"city": {
"id": 2761369,
"name": "Vienna",
"coord": {
"lon": 16.37208,
"lat": 48.208488
},
"country": "AT",
"population": 0
},
"cod": "200",
"message": 0.0098,
"cnt": 7,
"list": [{
"dt": 1476439200,
"temp": {
"day": 285.58,
"min": 283.71,
"max": 285.58,
"night": 283.71,
"eve": 285.43,
"morn": 285.58
},
"pressure": 985.46,
"humidity": 73,
"weather": [{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}],
"speed": 7.16,
"deg": 154,
"clouds": 0
}, {
"dt": 1476525600,
"temp": {
"day": 287.33,
"min": 282.7,
"max": 291.08,
"night": 285.72,
"eve": 291.01,
"morn": 283.35
},
"pressure": 983.21,
"humidity": 71,
"weather": [{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}],
"speed": 4.51,
"deg": 150,
"clouds": 32,
"rain": 0.23
}, {
"dt": 1476612000,
"temp": {
"day": 286.88,
"min": 283.94,
"max": 287.15,
"night": 283.94,
"eve": 286.44,
"morn": 286.26
},
"pressure": 989.94,
"humidity": 98,
"weather": [{
"id": 501,
"main": "Rain",
"description": "moderate rain",
"icon": "10d"
}],
"speed": 4.36,
"deg": 315,
"clouds": 92,
"rain": 5.51
}, {
"dt": 1476698400,
"temp": {
"day": 287.39,
"min": 283.49,
"max": 287.39,
"night": 284.89,
"eve": 285.05,
"morn": 283.49
},
"pressure": 984.76,
"humidity": 0,
"weather": [{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}],
"speed": 1.64,
"deg": 132,
"clouds": 69,
"rain": 1.55
}, {
"dt": 1476784800,
"temp": {
"day": 285.91,
"min": 283.52,
"max": 285.91,
"night": 283.52,
"eve": 284.45,
"morn": 284.18
},
"pressure": 982.64,
"humidity": 0,
"weather": [{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}],
"speed": 3.23,
"deg": 137,
"clouds": 81,
"rain": 2.4
}, {
"dt": 1476871200,
"temp": {
"day": 283.71,
"min": 282.37,
"max": 283.71,
"night": 282.37,
"eve": 282.52,
"morn": 282.59
},
"pressure": 978.26,
"humidity": 0,
"weather": [{
"id": 502,
"main": "Rain",
"description": "heavy intensity rain",
"icon": "10d"
}],
"speed": 2.68,
"deg": 128,
"clouds": 96,
"rain": 14.37
}, {
"dt": 1476957600,
"temp": {
"day": 286.52,
"min": 282.13,
"max": 286.52,
"night": 282.13,
"eve": 282.72,
"morn": 282.19
},
"pressure": 975.05,
"humidity": 0,
"weather": [{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}],
"speed": 1.47,
"deg": 173,
"clouds": 13,
"rain": 2.83
}]
}
Btw, it's not a duplicate from how do i use json api in my kivy program becaue it didn't really help... The code doesn't work anymore because the API changed.
(If anyone finds this question and is looking for a working URL reader, here is my code. Don't forget to import requests)
def search_location(self):
#Get URL From Weather API + Input
search_template = "http://api.openweathermap.org/data/2.5/forecast/daily?APPID='enteryourweatherAPIKeyhere'&q=" + "{}"
search_url = search_template.format(self.search_input.text)
#Reads the Website and saves it in a string
urlresults = (requests.get(search_url)).text
#Converts Json to Python Dictionary
urlresults = json.loads(urlresults)
cities = ["{} ({})".format(urlresults["city"]["name"], urlresults["city"]["country"])]
Go to this page:
http://openweathermap.org/faq#error401
the API now requires a key. After registering on openweathermap, a key will be mailed to you. Replace the current URL with the one given in the mail.
This worked for me.

Configuring line charts with remote data in Kendo UI

I am looking to render a line chart using Kendo UI. http://demos.telerik.com/kendo-ui/line-charts/remote-data-binding
It expects the json data to be directly an array like in the format (from their example):
[
{
"date": "12/30/2011",
"close": 405,
"volume": 6414369,
"open": 403.51,
"high": 406.28,
"low": 403.49,
"symbol": "2. AAPL"
},
{
"date": "11/30/2011",
"close": 382.2,
"volume": 14464710,
"open": 381.29,
"high": 382.276,
"low": 378.3,
"symbol": "2. AAPL"
}
]
However, I have a URL that returns the data in the following format. Note the extra object 'ranks' at the beginning which has the array:
{
"ranks": [
{
"id": 2,
"rank": 3,
"rankdate": "2015-05-17T00:00:00+0000",
"student": {
"id": 203,
"name": "Student1",
"currentRank": 3,
"LastVerified": "2015-05-17T22:30:00+0000"
}
},
{
"id": 1,
"rank": 4,
"rankdate": "2015-05-16T00:00:00+0000",
"student": {
"id": 203,
"name": "Student1",
"currentRank": 3,
"LastVerified": "2015-05-17T22:30:00+0000"
}
}
]
}
I was wondering if there was a way to have the datasource look inside "ranks" for the array instead of expecting it directly.
Found it. One can customize the schema in Kendo for the datasource using:
schema: {
data: "ranks"
},

Ruby: Checking JSON and Naming Variables

I'm really new to working with JSON in Ruby, and am having a hard time figuring out why a script I'm running is generating blank lines as a result. Let's say that I'm parsing a file where one element is not always present. I want to check if that element exists, and depending on the result name variables in a specific way. Here is what I've been trying
require 'rubygems'
require 'json'
file = File.open("/path/to/file.json", encoding: 'UTF-8')
json = file.read
data = JSON.parse(json)
if data["snapshots"][-1]["responses"][2].nil?
item = something
elseif
item = something else
end
puts item
This is not generating an error, but is just producing a blank line. I'm sure I'm doing something obvious wrong, but would appreciate any help. Thanks!
Your main problem is that you had elseif instead of elsif
Full code using the JSON you provided below:
require 'json'
json = <<EOS
{
"snapshots": [
{
"steps": 10,
"responses": [
{
"tokens": [
"Answer"
],
"questionPrompt": "Question1?"
},
{
"tokens": [
"Answer"
],
"questionPrompt": "Question2?"
},
{
"locationResponse": {
"location": {
"speed": 0,
"timestamp": "2014-04-20T17: 28: 37-0400",
"longitude": "-xx.xxxxxxx",
"latitude": "xx.xxxxxx",
"verticalAccuracy": 3,
"course": 0,
"horizontalAccuracy": 5
},
"text": "Response"
},
"questionPrompt": "Question3?"
},
{
"tokens": [
"Answer"
],
"questionPrompt": "Question4?"
}
],
"battery": 0.75,
"sectionIdentifier": "1-2014-5-7",
"audio": {
"avg": -49.84988,
"peak": -39.73056
},
"background": 0,
"date": "2014-05-07T23: 20: 57-0400",
"location": {
"speed": -1,
"placemark": {
"subAdministrativeArea": "County",
"subLocality": "CityName",
"thoroughfare": "Street",
"administrativeArea": "xx",
"subThoroughfare": "xxx",
"postalCode": "xxxxx",
"region": "<+xx.xxxxxx",
"radius": 28.13,
"country": "UnitedStates",
"locality": "CityName",
"name": "Address"
},
"timestamp": "2014-05-07T23: 20: 58-0400",
"longitude": "-xx.xxxxxxx",
"latitude": "xx.xxxxxxx",
"verticalAccuracy": 10,
"course": 0,
"horizontalAccuracy": 65
},
"dwellStatus": 0,
"weather": {
"relativeHumidity": "68%",
"visibilityKM": 16.1,
"tempC": 13.3,
"precipTodayIn": 0,
"windKPH": 0,
"latitude": 40.813984,
"windDegrees": 159,
"stationID": "xxxxxxxx",
"visibilityMi": 10,
"pressureIn": 30.2,
"pressureMb": 1023,
"feelslikeF": 55.9,
"windGustKPH": 12.4,
"longitude": -77.895775,
"feelslikeC": 13.3,
"precipTodayMetric": 0,
"tempF": 55.9,
"windDirection": "SSE",
"dewpointC": 8,
"uv": 0,
"weather": "Overcast",
"windGustMPH": 7.7,
"windMPH": 0
},
"connection": 1,
"sync": 0,
"reportImpetus": 0,
"draft": 0
}
]
}
EOS
data = JSON.parse(json)
if data["snapshots"][-1]["responses"][2].nil?
item = "was nil"
elsif # THIS WAS elseif before
item = "NOT nil"
end
puts item

Resources