Exemple #1
0
        /// <summary>
        /// Get details of all schemas in the project.
        /// </summary>
        /// <returns></returns>
        public async Task <JArray> GetSchemas()
        {
            if (string.IsNullOrWhiteSpace(_readKey))
            {
                throw new KeenException("An API ReadKey is required to get schemas.");
            }

            var responseMsg = await _keenHttpClient
                              .GetAsync(_eventsRelativeUrl, _readKey)
                              .ConfigureAwait(continueOnCapturedContext: false);

            var responseString = await responseMsg
                                 .Content
                                 .ReadAsStringAsync()
                                 .ConfigureAwait(continueOnCapturedContext: false);

            var response = JArray.Parse(responseString);

            // error checking, throw an exception with information from the json
            // response if available, then check the HTTP response.
            KeenUtil.CheckApiErrorCode(response);

            if (!responseMsg.IsSuccessStatusCode)
            {
                throw new KeenException("GetSchemas failed with status: " +
                                        responseMsg.StatusCode);
            }

            return(response);
        }
Exemple #2
0
        /// <summary>
        /// Get details of all schemas in the project.
        /// </summary>
        /// <returns></returns>
        public async Task <JArray> GetSchemas()
        {
            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("Authorization", _prjSettings.MasterKey);
                client.DefaultRequestHeaders.Add("Keen-Sdk", KeenUtil.GetSdkVersion());

                var responseMsg = await client.GetAsync(_serverUrl)
                                  .ConfigureAwait(continueOnCapturedContext: false);

                var responseString = await responseMsg.Content.ReadAsStringAsync()
                                     .ConfigureAwait(continueOnCapturedContext: false);

                dynamic response = JArray.Parse(responseString);

                // error checking, throw an exception with information from the json
                // response if available, then check the HTTP response.
                KeenUtil.CheckApiErrorCode(response);
                if (!responseMsg.IsSuccessStatusCode)
                {
                    throw new KeenException("GetSchemas failed with status: " + responseMsg.StatusCode);
                }

                return(response);
            }
        }
Exemple #3
0
        /// <summary>
        /// Add a single event to the specified collection.
        /// </summary>
        /// <param name="collection">Collection name</param>
        /// <param name="eventInfo">The event to add.</param>
        /// <param name="addOns">Optional collection of Data Enhancement Add-ons</param>
        public async Task AddEventAsync(string collection, object eventInfo, IEnumerable <AddOn> addOns = null)
        {
            // Preconditions
            KeenUtil.ValidateEventCollectionName(collection);
            if (null == eventInfo)
            {
                throw new KeenException("Event data is required.");
            }
            if (string.IsNullOrWhiteSpace(_prjSettings.WriteKey))
            {
                throw new KeenException("Write API key is required for AddEvent");
            }

            var jEvent = PrepareUserObject(eventInfo, addOns);

            // If an event cache has been provided, cache this event insead of sending it.
            if (null != EventCache)
            {
                await EventCache.Add(new CachedEvent(collection, jEvent))
                .ConfigureAwait(false);
            }
            else
            {
                await EventCollection.AddEvent(collection, jEvent)
                .ConfigureAwait(false);
            }
        }
Exemple #4
0
        /// <summary>
        /// Add all events in a single request.
        /// </summary>
        /// <param name="events"></param>
        /// <returns></returns>
        public async Task <IEnumerable <CachedEvent> > AddEvents(JObject events)
        {
            var content = events.ToString();

            using (var client = new HttpClient())
                using (var contentStream = new StreamContent(new MemoryStream(Encoding.UTF8.GetBytes(content))))
                {
                    contentStream.Headers.Add("content-type", "application/json");

                    client.DefaultRequestHeaders.Add("Authorization", _prjSettings.WriteKey);
                    client.DefaultRequestHeaders.Add("Keen-Sdk", KeenUtil.GetSdkVersion());

                    var httpResponse = await client.PostAsync(_serverUrl, contentStream)
                                       .ConfigureAwait(continueOnCapturedContext: false);

                    var responseString = await httpResponse.Content.ReadAsStringAsync()
                                         .ConfigureAwait(continueOnCapturedContext: false);

                    JObject jsonResponse = null;
                    try
                    {
                        // Normally the response content should be parsable JSON,
                        // but if the server returned a 404 error page or something
                        // like that, this will throw.
                        jsonResponse = JObject.Parse(responseString);
                    }
                    catch (Exception)
                    { }

                    if (!httpResponse.IsSuccessStatusCode)
                    {
                        throw new KeenException("AddEvents failed with status: " + httpResponse);
                    }
                    if (null == jsonResponse)
                    {
                        throw new KeenException("AddEvents failed with empty response from server.");
                    }

                    // error checking, return failed events in the list,
                    // or if the HTTP response is a failure, throw.
                    var failedItems = from respCols in jsonResponse.Properties()
                                      from eventsCols in events.Properties()
                                      where respCols.Name == eventsCols.Name
                                      let collection = respCols.Name
                                                       let combined = eventsCols.Children().Children()
                                                                      .Zip(respCols.Children().Children(),
                                                                           (e, r) => new { eventObj = (JObject)e, result = (JObject)r })
                                                                      from e in combined
                                                                      where !(bool)(e.result.Property("success").Value)
                                                                      select new CachedEvent(collection, e.eventObj, KeenUtil.GetBulkApiError(e.result));

                    return(failedItems);
                }
        }
Exemple #5
0
        /// <summary>
        /// Convert a user-supplied object to a JObject that can be sent to the Keen.IO API.
        ///
        /// This writes any global properties to the object and records the time.
        /// </summary>
        /// <param name="eventInfo"></param>
        /// <param name="addOns">Optional collection of Data Enhancement Add-ons</param>
        /// <returns></returns>
        private JObject PrepareUserObject(object eventInfo, IEnumerable <AddOn> addOns)
        {
            var jEvent = JObject.FromObject(eventInfo);

            // Add global properties to the event
            foreach (var p in _globalProperties)
            {
                // If the property value is an IDynamicPropertyValue,
                // exec the Value() to generate the property value.
                var dynProp = p.Value as IDynamicPropertyValue;
                if (dynProp == null)
                {
                    KeenUtil.ValidatePropertyName(p.Key);
                    jEvent.Add(p.Key, JToken.FromObject(p.Value));
                }
                else
                {
                    var val = dynProp.Value();
                    if (null == val)
                    {
                        throw new KeenException(string.Format("Dynamic property \"{0}\" returned a null value", p.Key));
                    }
                    jEvent.Add(p.Key, JToken.FromObject(val));
                }
            }

            // Ensure this event has a 'keen' object of the correct type
            if (null == jEvent.Property("keen"))
            {
                jEvent.Add("keen", new JObject());
            }
            else if (jEvent.Property("keen").Value.GetType() != typeof(JObject))
            {
                throw new KeenException(string.Format("Value of property \"keen\" must be an object, is {0}",
                                                      jEvent.Property("keen").GetType()));
            }


            var keen = ((JObject)jEvent.Property("keen").Value);

            if (addOns != null && addOns.Any())
            {
                keen.Add("addons", JArray.FromObject(addOns));
            }

            // Set the keen.timestamp if it has not already been set
            if (null == keen.Property("timestamp"))
            {
                keen.Add("timestamp", DateTime.Now);
            }

            return(jEvent);
        }
Exemple #6
0
        /// <summary>
        /// Retrieve the schema for the specified collection. This requires
        /// a value for the project settings Master API key.
        /// </summary>
        /// <param name="collection"></param>
        public async Task <dynamic> GetSchemaAsync(string collection)
        {
            // Preconditions
            KeenUtil.ValidateEventCollectionName(collection);
            if (string.IsNullOrWhiteSpace(_prjSettings.MasterKey))
            {
                throw new KeenException("Master API key is required for GetSchema");
            }

            return(await EventCollection.GetSchema(collection)
                   .ConfigureAwait(continueOnCapturedContext: false));
        }
Exemple #7
0
        /// <summary>
        /// Delete the specified collection. Deletion may be denied for collections with many events.
        /// Master API key is required.
        /// </summary>
        /// <param name="collection">Name of collection to delete.</param>
        public async Task DeleteCollectionAsync(string collection)
        {
            // Preconditions
            KeenUtil.ValidateEventCollectionName(collection);
            if (string.IsNullOrWhiteSpace(_prjSettings.MasterKey))
            {
                throw new KeenException("Master API key is required for DeleteCollection");
            }

            await EventCollection.DeleteCollection(collection)
            .ConfigureAwait(continueOnCapturedContext: false);
        }
Exemple #8
0
        public async System.Threading.Tasks.Task DeleteCollection(string collection)
        {
            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("Authorization", _prjSettings.MasterKey);
                client.DefaultRequestHeaders.Add("Keen-Sdk", KeenUtil.GetSdkVersion());

                var responseMsg = await client.DeleteAsync(_serverUrl + collection)
                                  .ConfigureAwait(continueOnCapturedContext: false);

                if (!responseMsg.IsSuccessStatusCode)
                {
                    throw new KeenException("DeleteCollection failed with status: " + responseMsg.StatusCode);
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// Add a static global property. This property will be added to
        /// every event.
        /// </summary>
        /// <param name="property">Property name</param>
        /// <param name="value">Property value. This may be a simple value, array, or object,
        /// or an object that supports IDynamicPropertyValue returning one of those.</param>
        public void AddGlobalProperty(string property, object value)
        {
            // Verify that the property name is allowable, and that the value is populated.
            KeenUtil.ValidatePropertyName(property);
            if (value == null)
            {
                throw new KeenException("Global properties must have a non-null value.");
            }
            var dynProp = value as IDynamicPropertyValue;

            if (dynProp != null)
            {
                // Execute the property once before it is needed to check the value
                ExecDynamicPropertyValue(property, dynProp);
            }

            _globalProperties.Add(property, value);
        }
Exemple #10
0
        public async Task AddEvent(string collection, JObject anEvent)
        {
            if (string.IsNullOrWhiteSpace(_writeKey))
            {
                throw new KeenException("An API WriteKey is required to add events.");
            }

            var content = anEvent.ToString();

            var responseMsg = await _keenHttpClient
                              .PostAsync(GetCollectionUrl(collection), _writeKey, content)
                              .ConfigureAwait(continueOnCapturedContext: false);

            var responseString = await responseMsg
                                 .Content
                                 .ReadAsStringAsync()
                                 .ConfigureAwait(continueOnCapturedContext: false);

            JObject jsonResponse = null;

            try
            {
                // Normally the response content should be parsable JSON,
                // but if the server returned a 404 error page or something
                // like that, this will throw.
                jsonResponse = JObject.Parse(responseString);
            }
            catch (Exception)
            {
            }

            // error checking, throw an exception with information from the
            // json response if available, then check the HTTP response.
            KeenUtil.CheckApiErrorCode(jsonResponse);

            if (!responseMsg.IsSuccessStatusCode)
            {
                throw new KeenException("AddEvent failed with status: " + responseMsg.StatusCode);
            }
        }
Exemple #11
0
        public async System.Threading.Tasks.Task AddEvent(string collection, JObject anEvent)
        {
            var content = anEvent.ToString();

            using (var client = new HttpClient())
                using (var contentStream = new StreamContent(new MemoryStream(Encoding.UTF8.GetBytes(content))))
                {
                    contentStream.Headers.Add("content-type", "application/json");

                    client.DefaultRequestHeaders.Add("Authorization", _prjSettings.WriteKey);
                    client.DefaultRequestHeaders.Add("Keen-Sdk", KeenUtil.GetSdkVersion());

                    var httpResponse = await client.PostAsync(_serverUrl + collection, contentStream)
                                       .ConfigureAwait(continueOnCapturedContext: false);

                    var responseString = await httpResponse.Content.ReadAsStringAsync()
                                         .ConfigureAwait(continueOnCapturedContext: false);

                    JObject jsonResponse = null;
                    try
                    {
                        // Normally the response content should be parsable JSON,
                        // but if the server returned a 404 error page or something
                        // like that, this will throw.
                        jsonResponse = JObject.Parse(responseString);
                    }
                    catch (Exception)
                    { }

                    // error checking, throw an exception with information from the
                    // json response if available, then check the HTTP response.
                    KeenUtil.CheckApiErrorCode(jsonResponse);
                    if (!httpResponse.IsSuccessStatusCode)
                    {
                        throw new KeenException("AddEvent failed with status: " + httpResponse);
                    }
                }
        }
Exemple #12
0
        public async Task <JObject> GetSchema(string collection)
        {
            // TODO : So much of this code, both in the constructor and in the actual message
            // dispatch, response parsing and error checking is copy/paste across Queries, Event
            // and EventCollection everywhere we use KeenHttpClient. We could shove some of that
            // into shared factory functionality (for the ctor stuff) and some of it into the
            // KeenHttpClient (for the dispatch/response portions).


            if (string.IsNullOrWhiteSpace(_readKey))
            {
                throw new KeenException("An API ReadKey is required to get collection schema.");
            }

            var responseMsg = await _keenHttpClient
                              .GetAsync(GetCollectionUrl(collection), _readKey)
                              .ConfigureAwait(continueOnCapturedContext: false);

            var responseString = await responseMsg
                                 .Content
                                 .ReadAsStringAsync()
                                 .ConfigureAwait(continueOnCapturedContext: false);

            dynamic response = JObject.Parse(responseString);

            // error checking, throw an exception with information from the json
            // response if available, then check the HTTP response.
            KeenUtil.CheckApiErrorCode(response);

            if (!responseMsg.IsSuccessStatusCode)
            {
                throw new KeenException("GetSchema failed with status: " + responseMsg.StatusCode);
            }

            return(response);
        }
Exemple #13
0
        /// <summary>
        /// Add all events in a single request.
        /// </summary>
        /// <param name="events"></param>
        /// <returns></returns>
        public async Task <IEnumerable <CachedEvent> > AddEvents(JObject events)
        {
            if (string.IsNullOrWhiteSpace(_writeKey))
            {
                throw new KeenException("An API WriteKey is required to add events.");
            }

            var content = events.ToString();

            var responseMsg = await _keenHttpClient
                              .PostAsync(_eventsRelativeUrl, _writeKey, content)
                              .ConfigureAwait(continueOnCapturedContext: false);

            var responseString = await responseMsg
                                 .Content
                                 .ReadAsStringAsync()
                                 .ConfigureAwait(continueOnCapturedContext: false);

            JObject jsonResponse = null;

            try
            {
                // Normally the response content should be parsable JSON,
                // but if the server returned a 404 error page or something
                // like that, this will throw.
                jsonResponse = JObject.Parse(responseString);

                // TODO : Why do we not call KeenUtil.CheckApiErrorCode(jsonResponse); ??
            }
            catch (Exception)
            {
            }

            if (!responseMsg.IsSuccessStatusCode)
            {
                throw new KeenException("AddEvents failed with status: " + responseMsg.StatusCode);
            }

            if (null == jsonResponse)
            {
                throw new KeenException("AddEvents failed with empty response from server.");
            }

            // error checking, return failed events in the list,
            // or if the HTTP response is a failure, throw.
            var failedItems =
                from respCols in jsonResponse.Properties()
                from eventsCols in events.Properties()
                where respCols.Name == eventsCols.Name
                let collection = respCols.Name
                                 let combined = eventsCols.Children().Children()
                                                .Zip(respCols.Children().Children(),
                                                     (e, r) => new { eventObj = (JObject)e, result = (JObject)r })
                                                from e in combined
                                                where !(bool)(e.result.Property("success").Value)
                                                select new CachedEvent(collection,
                                                                       e.eventObj,
                                                                       KeenUtil.GetBulkApiError(e.result));

            return(failedItems);
        }