azure_application_insights 0.5.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/gem-push.yml +34 -0
  3. data/.gitignore +40 -0
  4. data/.travis.yml +22 -0
  5. data/CHANGELOG.md +17 -0
  6. data/CONTRIBUTING.md +68 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +11 -0
  9. data/README.md +161 -0
  10. data/Rakefile +15 -0
  11. data/application_insights.gemspec +30 -0
  12. data/lib/application_insights/channel/asynchronous_queue.rb +58 -0
  13. data/lib/application_insights/channel/asynchronous_sender.rb +133 -0
  14. data/lib/application_insights/channel/contracts/application.rb +14 -0
  15. data/lib/application_insights/channel/contracts/cloud.rb +14 -0
  16. data/lib/application_insights/channel/contracts/data.rb +14 -0
  17. data/lib/application_insights/channel/contracts/data_point.rb +24 -0
  18. data/lib/application_insights/channel/contracts/data_point_type.rb +7 -0
  19. data/lib/application_insights/channel/contracts/dependency_kind.rb +9 -0
  20. data/lib/application_insights/channel/contracts/dependency_source_type.rb +9 -0
  21. data/lib/application_insights/channel/contracts/device.rb +28 -0
  22. data/lib/application_insights/channel/contracts/envelope.rb +40 -0
  23. data/lib/application_insights/channel/contracts/event_data.rb +28 -0
  24. data/lib/application_insights/channel/contracts/exception_data.rb +37 -0
  25. data/lib/application_insights/channel/contracts/exception_details.rb +28 -0
  26. data/lib/application_insights/channel/contracts/internal.rb +14 -0
  27. data/lib/application_insights/channel/contracts/json_serializable.rb +59 -0
  28. data/lib/application_insights/channel/contracts/location.rb +16 -0
  29. data/lib/application_insights/channel/contracts/message_data.rb +24 -0
  30. data/lib/application_insights/channel/contracts/metric_data.rb +27 -0
  31. data/lib/application_insights/channel/contracts/operation.rb +19 -0
  32. data/lib/application_insights/channel/contracts/page_view_data.rb +30 -0
  33. data/lib/application_insights/channel/contracts/remote_dependency_data.rb +56 -0
  34. data/lib/application_insights/channel/contracts/request_data.rb +36 -0
  35. data/lib/application_insights/channel/contracts/session.rb +15 -0
  36. data/lib/application_insights/channel/contracts/severity_level.rb +13 -0
  37. data/lib/application_insights/channel/contracts/stack_frame.rb +17 -0
  38. data/lib/application_insights/channel/contracts/user.rb +19 -0
  39. data/lib/application_insights/channel/event.rb +68 -0
  40. data/lib/application_insights/channel/queue_base.rb +73 -0
  41. data/lib/application_insights/channel/sender_base.rb +88 -0
  42. data/lib/application_insights/channel/synchronous_queue.rb +45 -0
  43. data/lib/application_insights/channel/synchronous_sender.rb +17 -0
  44. data/lib/application_insights/channel/telemetry_channel.rb +131 -0
  45. data/lib/application_insights/channel/telemetry_context.rb +85 -0
  46. data/lib/application_insights/rack/track_request.rb +158 -0
  47. data/lib/application_insights/telemetry_client.rb +229 -0
  48. data/lib/application_insights/unhandled_exception.rb +49 -0
  49. data/lib/application_insights/version.rb +3 -0
  50. data/lib/application_insights.rb +9 -0
  51. data/test/application_insights/channel/contracts/test_application.rb +44 -0
  52. data/test/application_insights/channel/contracts/test_cloud.rb +44 -0
  53. data/test/application_insights/channel/contracts/test_data.rb +44 -0
  54. data/test/application_insights/channel/contracts/test_data_point.rb +109 -0
  55. data/test/application_insights/channel/contracts/test_device.rb +200 -0
  56. data/test/application_insights/channel/contracts/test_envelope.rb +209 -0
  57. data/test/application_insights/channel/contracts/test_event_data.rb +62 -0
  58. data/test/application_insights/channel/contracts/test_exception_data.rb +111 -0
  59. data/test/application_insights/channel/contracts/test_exception_details.rb +106 -0
  60. data/test/application_insights/channel/contracts/test_internal.rb +44 -0
  61. data/test/application_insights/channel/contracts/test_location.rb +70 -0
  62. data/test/application_insights/channel/contracts/test_message_data.rb +66 -0
  63. data/test/application_insights/channel/contracts/test_metric_data.rb +50 -0
  64. data/test/application_insights/channel/contracts/test_operation.rb +109 -0
  65. data/test/application_insights/channel/contracts/test_page_view_data.rb +88 -0
  66. data/test/application_insights/channel/contracts/test_remote_dependency_data.rb +209 -0
  67. data/test/application_insights/channel/contracts/test_request_data.rb +153 -0
  68. data/test/application_insights/channel/contracts/test_session.rb +57 -0
  69. data/test/application_insights/channel/contracts/test_stack_frame.rb +83 -0
  70. data/test/application_insights/channel/contracts/test_user.rb +96 -0
  71. data/test/application_insights/channel/test_asynchronous_queue.rb +47 -0
  72. data/test/application_insights/channel/test_asynchronous_sender.rb +81 -0
  73. data/test/application_insights/channel/test_event.rb +53 -0
  74. data/test/application_insights/channel/test_queue_base.rb +89 -0
  75. data/test/application_insights/channel/test_sender_base.rb +94 -0
  76. data/test/application_insights/channel/test_synchronous_queue.rb +28 -0
  77. data/test/application_insights/channel/test_synchronous_sender.rb +11 -0
  78. data/test/application_insights/channel/test_telemetry_channel.rb +167 -0
  79. data/test/application_insights/channel/test_telemetry_context.rb +83 -0
  80. data/test/application_insights/mock_sender.rb +37 -0
  81. data/test/application_insights/rack/test_track_request.rb +182 -0
  82. data/test/application_insights/test_logger.rb +10 -0
  83. data/test/application_insights/test_telemetry_client.rb +138 -0
  84. data/test/application_insights/test_unhandled_exception.rb +23 -0
  85. data/test/application_insights.rb +8 -0
  86. metadata +247 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d28bc24aac17bb3bd88e8080ec6abe6fa69faaebcda0dbb3d5f4746805f8dc6e
4
+ data.tar.gz: 06c89fcc256eef5c841b1cb214c7dff79f735213524fcc00b8b3c0a09c459e0d
5
+ SHA512:
6
+ metadata.gz: 07312cd55bc77c5ca5b37db7d50a93e11a4876a3b156272b9ebe73104c236881c52509427a5f0caebe5f8c690041786abea5844c606a5aac4e38e9de49c93969
7
+ data.tar.gz: 582cb4bb087073c4b579c99cac093f64b9a96a2f0a305f9345460095495a36ececac8496b4c3a0755cafbfe582e1bbb0761ff69b2ef893e303d69b7255b36980
@@ -0,0 +1,34 @@
1
+ name: Ruby Gem
2
+
3
+ on:
4
+ create:
5
+ branches: [ "master" ]
6
+ tags:
7
+ - 'v*'
8
+
9
+ jobs:
10
+ build:
11
+ name: Build + Publish
12
+ runs-on: ubuntu-latest
13
+ environment: production
14
+ permissions:
15
+ contents: read
16
+ packages: write
17
+
18
+ steps:
19
+ - uses: actions/checkout@v3
20
+ - name: Set up Ruby 2.6
21
+ uses: actions/setup-ruby@v1
22
+ with:
23
+ ruby-version: 2.6.x
24
+
25
+ - name: Publish to RubyGems
26
+ run: |
27
+ mkdir -p $HOME/.gem
28
+ touch $HOME/.gem/credentials
29
+ chmod 0600 $HOME/.gem/credentials
30
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
31
+ gem build *.gemspec
32
+ gem push *.gem
33
+ env:
34
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
data/.gitignore ADDED
@@ -0,0 +1,40 @@
1
+ *.gem
2
+ *.rbc
3
+ *.bundle
4
+ mkmf.log
5
+ /.config
6
+ /coverage/
7
+ /InstalledFiles
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /test/tmp/
12
+ /test/version_tmp/
13
+ /tmp/
14
+
15
+ ## Specific to RubyMotion:
16
+ .dat*
17
+ .repl_history
18
+ build/
19
+
20
+ ## Specific to RubyMine:
21
+ /.idea/
22
+
23
+ ## Documentation cache and generated files:
24
+ /.yardoc/
25
+ /_yardoc/
26
+ /doc/
27
+ /rdoc/
28
+
29
+ ## Environment normalisation:
30
+ /.bundle/
31
+ /lib/bundler/man/
32
+
33
+ # for a library or gem, you might want to ignore these files since the code is
34
+ # intended to run in multiple environments; otherwise, check them in:
35
+ Gemfile.lock
36
+ .ruby-version
37
+ .ruby-gemset
38
+
39
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
40
+ .rvmrc
data/.travis.yml ADDED
@@ -0,0 +1,22 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
6
+ - 2.2.0
7
+ - 2.3.3
8
+ - 2.4.0
9
+ - 2.5.0
10
+ - ruby-head
11
+
12
+ cache: bundler
13
+
14
+ before_install:
15
+ - gem install bundler
16
+
17
+ matrix:
18
+ allow_failures:
19
+ - rvm: ruby-head
20
+
21
+ install:
22
+ - bundle install
data/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ This file needs to be updated with every significant pull request. It is used to write down release notes.
4
+
5
+ ## Version 0.5.6
6
+ * Expose request id to parent Rack application when using `ApplicationInsights::Rack::TrackRequest` middleware through `env['ApplicationInsights.request.id']`.
7
+ * Implement operation context functionality for `ApplicationInsights::Rack::TrackRequest`.
8
+ * Add functionality to accept a Request-Id header for telemetry correlation.
9
+ * Add operation context to request tracking middleware.
10
+
11
+ ## Version 0.5.5
12
+ * Add some basic logging when failed to send telemetry to the server
13
+ * Add timestamp as an optional parameter to the TelemetryChannel::write() method
14
+
15
+ ## Version 0.5.4
16
+
17
+ Changelog started after this release.
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,68 @@
1
+ # How to Contribute
2
+
3
+ If you're interested in contributing, take a look at the general [contributer's guide](https://github.com/Microsoft/ApplicationInsights-Home/blob/master/CONTRIBUTING.md) first.
4
+
5
+ ## Build Gem
6
+
7
+ Run ```gem build application_insights.gemspec``` to generate the gem file.
8
+
9
+ And you can install the gem to test it locally by running ```gem install application_insights-[version].gem```.
10
+
11
+ ## Run Test
12
+
13
+ Make sure you have bundler installed, you can install it by ```sudo gem install bundler```. And run ```bundler install``` once to install all dependencies.
14
+
15
+ Run ```rake test```.
16
+
17
+ ## Releasing new version
18
+
19
+ This is for repository maintainers only:
20
+
21
+ 1. Create and merge develop->master PR https://github.com/Microsoft/ApplicationInsights-Ruby/compare/master...develop?expand=1
22
+ 2. Checkout latest `master`
23
+ ```
24
+ git checkout master
25
+ git pull
26
+ ```
27
+
28
+ 3. Remove old gem: `rm *.gem`
29
+ 4. [Build gem](https://github.com/Microsoft/ApplicationInsights-Ruby/blob/develop/CONTRIBUTING.md#build-gem)
30
+ 5. Push gem: `gem push application_insights-0.5.5.gem`
31
+ 6. Check gem on [rubygems](https://rubygems.org/gems/application_insights)
32
+ 7. Tag code:
33
+ ```
34
+ git tag -a v0.5.5
35
+ git push origin v0.5.5
36
+ ```
37
+ 8. Update description of [release](https://github.com/Microsoft/ApplicationInsights-Ruby/releases/edit/v0.5.5) from [CHANGELOG.md](https://github.com/Microsoft/ApplicationInsights-Ruby/blob/master/CHANGELOG.md)
38
+ 9. Create a branch off `develop` branch
39
+ ```
40
+ git checkout develop
41
+ git pull
42
+ git checkout -b releaseUpdates
43
+ git push --set-upstream origin releaseUpdates
44
+ ```
45
+ 10. Update version in `/lib/application_insights/version.rb`
46
+ 11. Create new entry for the next release in `/CHANGELOG.md`
47
+ 12. Push changes
48
+ ```
49
+ git add -A
50
+ git commit -m "post release updates"
51
+ git push
52
+ ```
53
+ 13. Submit releaseUpdates->develop PR: https://github.com/Microsoft/ApplicationInsights-Ruby/compare/develop...releaseUpdates?expand=1
54
+
55
+ ## Contributing
56
+
57
+ This project welcomes contributions and suggestions. Most contributions require you to
58
+ agree to a Contributor License Agreement (CLA) declaring that you have the right to,
59
+ and actually do, grant us the rights to use your contribution. For details, visit
60
+ https://cla.microsoft.com.
61
+
62
+ When you submit a pull request, a CLA-bot will automatically determine whether you need
63
+ to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the
64
+ instructions provided by the bot. You will only need to do this once across all repositories using our CLA.
65
+
66
+ This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
67
+ For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
68
+ or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in application_insights.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,11 @@
1
+ AppInsights-Ruby
2
+ Copyright (c) Microsoft Corporation
3
+ All rights reserved.
4
+
5
+ MIT License
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
+
11
+ THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # Application Insights SDK for Ruby #
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/application_insights.svg)](http://badge.fury.io/rb/application_insights)
4
+ [![Build Status](https://travis-ci.org/Microsoft/ApplicationInsights-Ruby.svg)](https://travis-ci.org/Microsoft/ApplicationInsights-Ruby)
5
+
6
+ >Ruby is a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write.
7
+ > -- <cite>[Ruby - Official Site](https://www.ruby-lang.org/en/)</cite>
8
+
9
+ This project extends the Application Insights API surface to support Ruby. [Application Insights](http://azure.microsoft.com/en-us/services/application-insights/) is a service that allows developers to keep their application available, performing and succeeding. This Ruby gem will allow you to send telemetry of various kinds (event, trace, exception, etc.) to the Application Insights service where they can be visualized in the Azure Portal.
10
+
11
+
12
+ ## Requirements ##
13
+
14
+ Ruby 1.9.3 is currently supported by this gem.
15
+
16
+ ## Installation ##
17
+
18
+ To install the latest release you can use *gem*.
19
+
20
+ ```
21
+ $ gem install application_insights
22
+ ```
23
+
24
+ ## Usage ##
25
+
26
+ Once installed, you can send telemetry to Application Insights. Here are a few samples.
27
+
28
+ >**Note**: before you can send data to you will need an instrumentation key. Please see the [Getting an Application Insights Instrumentation Key](https://github.com/Microsoft/AppInsights-Home/wiki#getting-an-application-insights-instrumentation-key) section for more information.
29
+
30
+
31
+ ### Sending a simple event telemetry item ###
32
+ ```ruby
33
+ require 'application_insights'
34
+ tc = ApplicationInsights::TelemetryClient.new '<YOUR INSTRUMENTATION KEY GOES HERE>'
35
+ tc.track_event 'My event'
36
+ tc.flush
37
+ ```
38
+
39
+ ### Sending an event telemetry item with custom properties and measurements ###
40
+ ```ruby
41
+ require 'application_insights'
42
+ tc = ApplicationInsights::TelemetryClient.new '<YOUR INSTRUMENTATION KEY GOES HERE>'
43
+ tc.track_event 'My event', :properties => { 'custom property' => 'some value' }, :measurements => { 'custom metric' => 13 }
44
+ tc.flush
45
+ ```
46
+
47
+ ### Sending a trace telemetry item with custom properties ###
48
+ ```ruby
49
+ require 'application_insights'
50
+ tc = ApplicationInsights::TelemetryClient.new '<YOUR INSTRUMENTATION KEY GOES HERE>'
51
+ tc.track_trace 'My trace statement', ApplicationInsights::Channel::Contracts::SeverityLevel::INFORMATION, :properties => { 'custom property' => 'some value' }
52
+ tc.flush
53
+ ```
54
+
55
+ ### Sending a metric telemetry item (without and with optional values) ###
56
+ ```ruby
57
+ require 'application_insights'
58
+ tc = ApplicationInsights::TelemetryClient.new '<YOUR INSTRUMENTATION KEY GOES HERE>'
59
+ tc.track_metric 'My metric', 42
60
+ # with all optional values set
61
+ tc.track_metric 'My metric', 42, :kind => ApplicationInsights::Channel::Contracts::DataPointType::AGGREGATION, :count => 3, :min => 1, :max => 100, :std_dev => 10, :properties => { 'custom property' => 'some value' }
62
+ tc.flush
63
+ ```
64
+
65
+ ### Sending an exception telemetry item with custom properties and measurements ###
66
+ ```ruby
67
+ require 'application_insights'
68
+ tc = ApplicationInsights::TelemetryClient.new '<YOUR INSTRUMENTATION KEY GOES HERE>'
69
+ begin
70
+ raise ArgumentError, 'Something has gone wrong!'
71
+ rescue => e
72
+ tc.track_exception e
73
+ end
74
+ tc.flush
75
+ ```
76
+
77
+ ### Configuring context for a telemetry client instance ###
78
+ ```ruby
79
+ require 'application_insights'
80
+ tc = ApplicationInsights::TelemetryClient.new '<YOUR INSTRUMENTATION KEY GOES HERE>'
81
+ tc.context.application.ver = '1.2.3'
82
+ tc.context.device.id = 'My current device'
83
+ tc.context.device.oem_name = 'Asus'
84
+ tc.context.device.model = 'X31A'
85
+ tc.context.device.type = "Other"
86
+ tc.context.user.id = 'santa@northpole.net'
87
+ tc.track_trace 'My trace with context'
88
+ tc.flush
89
+ ```
90
+
91
+ ### Configuring synchronous (default) channel properties ###
92
+ ```ruby
93
+ require 'application_insights'
94
+ tc = ApplicationInsights::TelemetryClient.new
95
+ # flush telemetry if we have 10 or more telemetry items in our queue
96
+ tc.channel.queue.max_queue_length = 10
97
+ # send telemetry to the service in batches of 5
98
+ tc.channel.sender.send_buffer_size = 5
99
+ ```
100
+
101
+ ### Configuring an asynchronous channel instead of the synchronous default ###
102
+ ```ruby
103
+ require 'application_insights'
104
+ sender = ApplicationInsights::Channel::AsynchronousSender.new
105
+ queue = ApplicationInsights::Channel::AsynchronousQueue.new sender
106
+ channel = ApplicationInsights::Channel::TelemetryChannel.new nil, queue
107
+ tc = ApplicationInsights::TelemetryClient.new '<YOUR INSTRUMENTATION KEY GOES HERE>', channel
108
+ # Note: the event will be sent on a separate thread; if the app finishes before
109
+ # the thread finishes, the data is lost
110
+ tc.track_event 'My event'
111
+ ```
112
+
113
+ ### Configuring asynchronous channel properties ###
114
+ ```ruby
115
+ require 'application_insights'
116
+ sender = ApplicationInsights::Channel::AsynchronousSender.new
117
+ queue = ApplicationInsights::Channel::AsynchronousQueue.new sender
118
+ channel = ApplicationInsights::Channel::TelemetryChannel.new nil, queue
119
+ tc = ApplicationInsights::TelemetryClient.new '<YOUR INSTRUMENTATION KEY GOES HERE>', channel
120
+ # flush telemetry if we have 10 or more telemetry items in our queue
121
+ tc.channel.queue.max_queue_length = 10
122
+ # send telemetry to the service in batches of 5
123
+ tc.channel.sender.send_buffer_size = 5
124
+ # the background worker thread will be active for 5 seconds before it shuts down. if
125
+ # during this time items are picked up from the queue, the timer is reset.
126
+ tc.channel.sender.send_time = 5
127
+ # the background worker thread will poll the queue every 0.5 seconds for new items
128
+ tc.channel.sender.send_interval = 0.5
129
+ ```
130
+
131
+ ### Collecting unhandled exceptions ###
132
+ ```ruby
133
+ require 'application_insights'
134
+ # setup unhandled exception handler
135
+ ApplicationInsights::UnhandledException.collect('<YOUR INSTRUMENTATION KEY GOES HERE>')
136
+ # raise an exception and this would be send to Application Insights Service
137
+ raise Exception, 'Boom!'
138
+ ```
139
+
140
+ ### Collecting requests for rack applications ###
141
+ ```ruby
142
+ # set up the TrackRequest middleware in the rackup (config.ru) file
143
+ require 'application_insights'
144
+ use ApplicationInsights::Rack::TrackRequest, '<YOUR INSTRUMENTATION KEY GOES HERE>', <buffer size>
145
+ # For rails, suggest to set up this middleware in application.rb so that unhandled exceptions from controllers are also collected
146
+ config.middleware.use 'ApplicationInsights::Rack::TrackRequest', '<YOUR INSTRUMENTATION KEY GOES HERE>', <buffer size>
147
+ ```
148
+
149
+ #### Rerieving the Request-Id value from ApplicationInsights ####
150
+ ```ruby
151
+ # from time to time you may need to access a request's id from within your app
152
+ application_insights_request_id = env['ApplicationInsights.request.id']
153
+
154
+ # this can be used for a number of different purposes, including telemetry correlation
155
+ uri = URI('http://api.example.com/search/?q=test')
156
+
157
+ req = Net::HTTP::Get.new(uri)
158
+ req['Request-Id'] = "#{application_insights_request_id}1" if application_insights_request_id
159
+
160
+ Net::HTTP.start(uri.hostname, uri.port) { |http| http.request(req) }
161
+ ```
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+ require 'yard'
4
+
5
+ Rake::TestTask.new do |test|
6
+ test.libs << 'test'
7
+ test.test_files = FileList['test/application_insights.rb']
8
+ test.verbose = true
9
+ end
10
+
11
+ YARD::Rake::YardocTask.new do |task|
12
+ task.files = ['lib/**/*.rb', '-', 'LICENSE.txt', 'README.md']
13
+ end
14
+
15
+ task :default => [ :test, :build, :yard ]
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'application_insights/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'azure_application_insights'
8
+ spec.version = ApplicationInsights::VERSION
9
+ spec.authors = ['Daniel Blasina']
10
+ spec.email = ['blzk100@gmail.com']
11
+ spec.summary = %q{Forked Application Insights SDK for Ruby}
12
+ spec.description = %q{This project extends the Application Insights API surface to support Ruby.}
13
+ spec.homepage = 'https://github.com/blasko03/ApplicationInsights-Ruby/'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.required_ruby_version = '>= 1.9.3'
22
+
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'yard', '~> 0.9.11'
25
+ spec.add_development_dependency 'redcarpet', '~> 3.2.2'
26
+ spec.add_development_dependency 'rack', '>= 1.0.0'
27
+ spec.add_development_dependency 'test-unit', '~> 3.0.8'
28
+ spec.add_development_dependency 'mocha', '~> 1.5.0'
29
+
30
+ end
@@ -0,0 +1,58 @@
1
+ require_relative 'event'
2
+ require_relative 'queue_base'
3
+
4
+ module ApplicationInsights
5
+ module Channel
6
+ # An asynchronous queue for use in conjunction with the {AsynchronousSender}.
7
+ # The queue will notify the sender that it needs to pick up items when it
8
+ # reaches {#max_queue_length}, or when the consumer calls {#flush} via the
9
+ # {#flush_notification} event.
10
+ #
11
+ # @example
12
+ # require 'application_insights'
13
+ # require 'thread'
14
+ # queue = ApplicationInsights::Channel::AsynchronousQueue.new nil
15
+ # Thread.new do
16
+ # sleep 1
17
+ # queue.push 1
18
+ # queue.flush
19
+ # end
20
+ # queue.flush_notification.wait
21
+ # queue.flush_notification.clear
22
+ # result = queue.pop
23
+ class AsynchronousQueue < QueueBase
24
+ # Initializes a new instance of the class.
25
+ # @param [SenderBase] sender the sender object that will be used in
26
+ # conjunction with this queue. In addition to the sender object must
27
+ # support a {AsynchronousSender#start} method which is invoked each time
28
+ # an item is pushed to the queue as well as use the {#flush_notification}
29
+ # event.
30
+ def initialize(sender)
31
+ @flush_notification = Event.new
32
+ super sender
33
+ end
34
+
35
+ # The flush notification {ApplicationInsights::Channel::Event} that the {#sender}
36
+ # will use to get notified that a flush is needed.
37
+ # @return [Event] object that the {#sender} can wait on.
38
+ attr_reader :flush_notification
39
+
40
+ # Adds the passed in item object to the queue and notifies the {#sender}
41
+ # to start an asynchronous send operation
42
+ # by calling {AsynchronousSender#start}.
43
+ # @param [Contracts::Envelope] item the telemetry envelope object to send
44
+ # to the service.
45
+ def push(item)
46
+ super item
47
+ @sender.start if @sender
48
+ end
49
+
50
+ # Flushes the current queue by notifying the {#sender} via the
51
+ # {#flush_notification} event.
52
+ def flush
53
+ @flush_notification.set
54
+ @sender.start if @sender
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,133 @@
1
+ require_relative 'sender_base'
2
+ require 'thread'
3
+
4
+ module ApplicationInsights
5
+ module Channel
6
+ # An asynchronous sender that works in conjunction with the {AsynchronousQueue}.
7
+ # The sender object will start a worker thread that will pull items from the
8
+ # {#queue}. The thread will be created when the client calls {#start} and
9
+ # will check for queue items every {#send_interval} seconds. The worker thread
10
+ # can also be forced to check the queue by setting the
11
+ # {AsynchronousQueue#flush_notification} event.
12
+ #
13
+ # - If no items are found, the thread will go back to sleep.
14
+ # - If items are found, the worker thread will send items to the specified
15
+ # service in batches of {#send_buffer_size}.
16
+ #
17
+ # If no queue items are found for {#send_time} seconds, the worker thread
18
+ # will shut down (and {#start} will need to be called again).
19
+ class AsynchronousSender < SenderBase
20
+ SERVICE_ENDPOINT_URI = 'https://dc.services.visualstudio.com/v2/track'
21
+ # Initializes a new instance of the class.
22
+ # @param [String] service_endpoint_uri the address of the service to send
23
+ # telemetry data to.
24
+ def initialize(service_endpoint_uri = SERVICE_ENDPOINT_URI)
25
+ @send_interval = 1.0
26
+ @send_remaining_time = 0
27
+ @send_time = 3.0
28
+ @lock_work_thread = Mutex.new
29
+ @work_thread = nil
30
+ @start_notification_processed = true
31
+ super service_endpoint_uri
32
+ end
33
+
34
+ # The time span in seconds at which the the worker thread will check the
35
+ # {#queue} for items (defaults to: 1.0).
36
+ # @return [Fixnum] the interval in seconds.
37
+ attr_accessor :send_interval
38
+
39
+ # The time span in seconds for which the worker thread will stay alive if
40
+ # no items are found in the {#queue} (defaults to 3.0).
41
+ # @return [Fixnum] the interval in seconds.
42
+ attr_accessor :send_time
43
+
44
+ # The worker thread which checks queue items and send data every
45
+ # (#send_interval) seconds or upon flush.
46
+ # @return [Thread] the work thread
47
+ attr_reader :work_thread
48
+
49
+ # Calling this method will create a worker thread that checks the {#queue}
50
+ # every {#send_interval} seconds for a total duration of {#send_time}
51
+ # seconds for new items. If a worker thread has already been created,
52
+ # calling this method does nothing.
53
+ def start
54
+ @start_notification_processed = false
55
+ # Maintain one working thread at one time
56
+ unless @work_thread
57
+ @lock_work_thread.synchronize do
58
+ unless @work_thread
59
+ local_send_interval = [@send_interval, 0.1].max
60
+ @send_remaining_time = [@send_time, local_send_interval].max
61
+ @work_thread = Thread.new { run }
62
+ @work_thread.abort_on_exception = false
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def run
71
+ # save the queue locally
72
+ local_queue = @queue
73
+ if local_queue.nil?
74
+ @work_thread = nil
75
+ return
76
+ end
77
+
78
+ begin
79
+ # fix up the send interval (can't be lower than 100ms)
80
+ local_send_interval = [@send_interval, 0.1].max
81
+
82
+ while true
83
+ @start_notification_processed = true
84
+ while true
85
+ # get at most @send_buffer_size items from the queue
86
+ data = []
87
+ @send_buffer_size.downto(1) do
88
+ item = local_queue.pop
89
+ break if not item
90
+ data.push item
91
+ end
92
+
93
+ # if we didn't get any items from the queue, we're done here
94
+ break if data.length == 0
95
+
96
+ # reset the send time
97
+ @send_remaining_time = @send_time
98
+
99
+ # finally send the data
100
+ send data
101
+ end
102
+
103
+ # wait at most @send_interval ms (or until we get signalled)
104
+ result = local_queue.flush_notification.wait local_send_interval
105
+ if result
106
+ local_queue.flush_notification.clear
107
+ next
108
+ end
109
+
110
+ # decrement the remaining time
111
+ @send_remaining_time -= local_send_interval
112
+ # If remaining time <=0 and there is no start notification unprocessed,
113
+ # then stop the working thread
114
+ if @send_remaining_time <= 0 && @start_notification_processed
115
+ # Note: there is still a chance some start notification could be
116
+ # missed, e.g., the start method got triggered between the above and
117
+ # following line. However the data is not lost as it would be
118
+ # processed later when next start notification comes after the worker
119
+ # thread stops. The cost to ensure no notification miss is high where
120
+ # a lock is required each time the start method calls.
121
+ @work_thread = nil
122
+ break
123
+ end
124
+ end
125
+ rescue Exception => e
126
+ # Make sure work_thread sets to nil when it terminates abnormally
127
+ @work_thread = nil
128
+ @logger.error('application_insights') { "Asynchronous sender work thread terminated abnormally: #{e.to_s}" }
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'json_serializable'
2
+
3
+ module ApplicationInsights::Channel::Contracts
4
+ class Application
5
+ include JsonSerializable
6
+
7
+ attr_accessor :ver, :build
8
+
9
+ attribute_mapping(
10
+ ver: 'ai.application.ver',
11
+ build: 'ai.application.build'
12
+ )
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'json_serializable'
2
+
3
+ module ApplicationInsights::Channel::Contracts
4
+ class Cloud
5
+ include JsonSerializable
6
+
7
+ attr_accessor :role_name, :role_instance
8
+
9
+ attribute_mapping(
10
+ role_name: 'ai.cloud.role',
11
+ role_instance: 'ai.cloud.roleInstance'
12
+ )
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'json_serializable'
2
+
3
+ module ApplicationInsights::Channel::Contracts
4
+ class Data
5
+ include JsonSerializable
6
+
7
+ attr_accessor :base_type, :base_data
8
+
9
+ attribute_mapping(
10
+ base_type: 'baseType',
11
+ base_data: 'baseData'
12
+ )
13
+ end
14
+ end