sentry-good_job 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +32 -0
- data/CODE_OF_CONDUCT.md +37 -0
- data/CONTRIBUTING.md +35 -0
- data/GOVERNANCE.md +31 -0
- data/LICENSE.txt +21 -0
- data/README.md +203 -0
- data/SECURITY.md +28 -0
- data/bin/console +15 -0
- data/bin/setup +21 -0
- data/lib/sentry/good_job/active_job_extensions.rb +141 -0
- data/lib/sentry/good_job/configuration.rb +29 -0
- data/lib/sentry/good_job/context_helpers.rb +44 -0
- data/lib/sentry/good_job/cron_helpers.rb +210 -0
- data/lib/sentry/good_job/version.rb +7 -0
- data/lib/sentry/good_job.rb +4 -0
- data/lib/sentry-good_job.rb +48 -0
- data/sentry-good_job.gemspec +49 -0
- metadata +93 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: fd17c2d28618ace1fe96fd34f6f39035c7a72db021555dcbd7239a727603f340
|
|
4
|
+
data.tar.gz: 784f07f7a32ec531bb35327f55b17ebe303b25095af640f8016373547810719f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 2ef631f7d3df7cc2de495e64ecb325980ae95b3809f208fcabcbf276529b3c3c1e0fe04660d6f7aae08b898df6d7fc73f40176e8b381ccf690cfa5868a61d289
|
|
7
|
+
data.tar.gz: c349ca2697b3435f30469d0ee21c730fec186931017eb94400bff9fa2795331a2845ed66eae82142fa7e7953b5920fc4b116d732fd531f0f23bc740038dcaf93
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 6.2.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- Initial release of sentry-good_job integration
|
|
8
|
+
- Automatic error capture for ActiveJob workers using Good Job
|
|
9
|
+
- Performance monitoring for job execution
|
|
10
|
+
- Automatic cron monitoring setup for scheduled jobs
|
|
11
|
+
- Context preservation and trace propagation
|
|
12
|
+
- Configurable error reporting options
|
|
13
|
+
- Rails integration with automatic setup
|
|
14
|
+
|
|
15
|
+
### Configuration Options
|
|
16
|
+
|
|
17
|
+
#### Good Job Specific Options
|
|
18
|
+
- `enable_cron_monitors`: Enable cron monitoring for scheduled jobs
|
|
19
|
+
|
|
20
|
+
#### ActiveJob Options (handled by sentry-rails)
|
|
21
|
+
- `config.rails.active_job_report_on_retry_error`: Only report errors after all retry attempts are exhausted
|
|
22
|
+
- `config.send_default_pii`: Include job arguments in error context
|
|
23
|
+
|
|
24
|
+
**Note**: The Good Job integration now leverages sentry-rails for core ActiveJob functionality, including trace propagation, user context preservation, and error reporting.
|
|
25
|
+
|
|
26
|
+
### Integration Features
|
|
27
|
+
|
|
28
|
+
- Seamless integration with Rails applications
|
|
29
|
+
- Automatic setup when Good Job integration is enabled
|
|
30
|
+
- Support for both manual and automatic cron monitoring
|
|
31
|
+
- Respects ActiveJob retry configuration
|
|
32
|
+
- Comprehensive error context and performance metrics
|
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We pledge to make participation in our community a harassment-free experience for everyone. We operate on principles of mutual respect, privacy, and authentic engagement. We value substantive contributions and clarity on intentions.
|
|
6
|
+
|
|
7
|
+
## Our Standards
|
|
8
|
+
|
|
9
|
+
Examples of behavior that contributes to a positive environment include:
|
|
10
|
+
|
|
11
|
+
* **Authenticity:** Engaging with genuine curiosity and admitting uncertainty rather than feigning knowledge.
|
|
12
|
+
|
|
13
|
+
* **Responsible Innovation:** Taking full responsibility for any content or code contributed, whether manually written or generated by automation tools.
|
|
14
|
+
|
|
15
|
+
* **Gentle Correction:** Responding politely to errors. We view mistakes as opportunities for learning, provided they are addressed with humility.
|
|
16
|
+
|
|
17
|
+
* **Inclusive Language:** Using language that welcomes diverse perspectives and respects the privacy and identity of all participants.
|
|
18
|
+
|
|
19
|
+
Examples of unacceptable behavior include:
|
|
20
|
+
|
|
21
|
+
* **Harassment:** Public or private harassment, trolling, or insulting comments.
|
|
22
|
+
|
|
23
|
+
* **Weaponized Complexity:** Using jargon or overwhelming volume (including automated spam) to silence others.
|
|
24
|
+
|
|
25
|
+
* **Publishing Private Information:** Sharing others' data or personal context without explicit permission.
|
|
26
|
+
|
|
27
|
+
## Artificial Intelligence & Automation
|
|
28
|
+
|
|
29
|
+
In accordance with our commitment to **Collective Awareness**:
|
|
30
|
+
|
|
31
|
+
* Contributors are responsible for the accuracy and security of any AI-generated artifacts they submit.
|
|
32
|
+
|
|
33
|
+
* "The AI wrote it" is not a valid excuse for introducing bugs, security vulnerabilities, or bias.
|
|
34
|
+
|
|
35
|
+
## Enforcement
|
|
36
|
+
|
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@kiskolabs.com. All complaints will be reviewed and investigated promptly and fairly.
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Contributing Guidelines
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing. We value **learning over perfection** but require **rigor and responsibility**.
|
|
4
|
+
|
|
5
|
+
## The Golden Rule of Automation
|
|
6
|
+
|
|
7
|
+
We welcome the use of AI and automation tools to reduce toil, but you must strictly adhere to the following:
|
|
8
|
+
|
|
9
|
+
1. **You are the Author:** You act as the responsible agent for any code you submit. You must review, debug, and understand every line.
|
|
10
|
+
|
|
11
|
+
2. **Manage Cognitive Load:** Do not submit massive, unreviewed automated dumps. Respect the reviewers' time by annotating complex logic.
|
|
12
|
+
|
|
13
|
+
3. **Security:** Never feed project secrets or private context into public AI models.
|
|
14
|
+
|
|
15
|
+
## How to Contribute
|
|
16
|
+
|
|
17
|
+
### 1. Reporting Issues
|
|
18
|
+
|
|
19
|
+
* **Verify Accuracy:** Before posting, verify your information. Avoid generalizations.
|
|
20
|
+
|
|
21
|
+
* **Use Structured Inputs:** Use our Issue Templates to provide clear goals, constraints, and reproduction steps. This helps us understand the context immediately.
|
|
22
|
+
|
|
23
|
+
### 2. Pull Request Process
|
|
24
|
+
|
|
25
|
+
* **Scope:** Keep PRs focused on a single goal.
|
|
26
|
+
|
|
27
|
+
* **Context:** Explain *why* the change is necessary. Transparency builds trust.
|
|
28
|
+
|
|
29
|
+
* **Testing:** Run all smoke tests and regression checks locally. We prioritize "Safety First."
|
|
30
|
+
|
|
31
|
+
### 3. Review Process
|
|
32
|
+
|
|
33
|
+
* We encourage **productive friction**. Expect questions about your approach.
|
|
34
|
+
|
|
35
|
+
* If a reviewer suggests a change, view it as **mutual aid**, not criticism.
|
data/GOVERNANCE.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Project Governance
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This project balances **individual autonomy** with **collective coordination**. We aim for a workflow that supports rapid iteration while maintaining strict guardrails for safety and architectural integrity.
|
|
6
|
+
|
|
7
|
+
## Roles
|
|
8
|
+
|
|
9
|
+
### Contributors
|
|
10
|
+
|
|
11
|
+
Anyone who submits code, documentation, or participates in discussions. Contributors are expected to exercise **Direct Action**—taking ownership of problems they identify—while adhering to our quality standards.
|
|
12
|
+
|
|
13
|
+
### Maintainers (Human Oversight)
|
|
14
|
+
|
|
15
|
+
Maintainers are responsible for:
|
|
16
|
+
|
|
17
|
+
1. **Strategic Judgment:** Defining scope and architectural direction.
|
|
18
|
+
|
|
19
|
+
2. **Review:** verifying that contributions (human or automated) meet security and logic standards.
|
|
20
|
+
|
|
21
|
+
3. **Consensus Building:** Facilitating decisions when the community is divided.
|
|
22
|
+
|
|
23
|
+
## Decision Making process
|
|
24
|
+
|
|
25
|
+
### Lazy Consensus
|
|
26
|
+
|
|
27
|
+
For most routine changes, we operate on "lazy consensus." If a proposal is made and no objections are raised within two weeks, it is considered approved.
|
|
28
|
+
|
|
29
|
+
### Strategic Alignment
|
|
30
|
+
|
|
31
|
+
Major architectural changes, high-risk automation integrations, or changes that affect business logic require explicit approval from the Maintainers. We prioritize **substance over performance**—a change must solve a real problem, not just appear polished.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Andrei Makarov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://sentry.io" target="_blank" align="center">
|
|
3
|
+
<img src="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" width="280">
|
|
4
|
+
</a>
|
|
5
|
+
<br>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
# sentry-good_job, the Good Job integration for Sentry's Ruby client
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
[](https://rubygems.org/gems/sentry-good_job)
|
|
13
|
+

|
|
14
|
+
[](https://codecov.io/gh/getsentry/sentry-ruby/branch/master)
|
|
15
|
+
[](https://rubygems.org/gems/sentry-good_job/)
|
|
16
|
+
[](https://dependabot.com/compatibility-score.html?dependency-name=sentry-good_job&package-manager=bundler&version-scheme=semver)
|
|
17
|
+
|
|
18
|
+
[Documentation](https://docs.sentry.io/platforms/ruby/guides/good_job/) | [Bug Tracker](https://github.com/getsentry/sentry-ruby/issues) | [Forum](https://forum.sentry.io/) | IRC: irc.freenode.net, #sentry
|
|
19
|
+
|
|
20
|
+
The official Ruby-language client and integration layer for the [Sentry](https://github.com/getsentry/sentry) error reporting API.
|
|
21
|
+
|
|
22
|
+
## Getting Started
|
|
23
|
+
|
|
24
|
+
### Install
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
gem "sentry-ruby"
|
|
28
|
+
gem "sentry-rails"
|
|
29
|
+
gem "good_job"
|
|
30
|
+
gem "sentry-good_job"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Then you're all set! `sentry-good_job` will automatically capture exceptions from your ActiveJob workers when using Good Job as the backend!
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- **Automatic Error Capture**: Captures exceptions from ActiveJob workers using Good Job
|
|
38
|
+
- **Performance Monitoring**: Tracks job execution times and performance metrics
|
|
39
|
+
- **Cron Monitoring**: Automatic setup for scheduled jobs with cron monitoring
|
|
40
|
+
- **Context Preservation**: Maintains user context and trace propagation across job executions
|
|
41
|
+
- **Configurable Reporting**: Control when errors are reported (after retries, only dead jobs, etc.)
|
|
42
|
+
- **Rails Integration**: Seamless integration with Rails applications
|
|
43
|
+
|
|
44
|
+
## Configuration
|
|
45
|
+
|
|
46
|
+
The integration can be configured through Sentry's configuration:
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
Sentry.init do |config|
|
|
50
|
+
config.dsn = 'your-dsn-here'
|
|
51
|
+
|
|
52
|
+
# Good Job specific configuration
|
|
53
|
+
config.good_job.enable_cron_monitors = true
|
|
54
|
+
|
|
55
|
+
# ActiveJob configuration (handled by sentry-rails)
|
|
56
|
+
config.rails.active_job_report_on_retry_error = false
|
|
57
|
+
config.send_default_pii = false
|
|
58
|
+
|
|
59
|
+
# Optional: Configure logging for debugging
|
|
60
|
+
config.sdk_logger = Rails.logger
|
|
61
|
+
end
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Configuration Options
|
|
65
|
+
|
|
66
|
+
#### Good Job Specific Options
|
|
67
|
+
|
|
68
|
+
- `enable_cron_monitors` (default: `true`): Enable cron monitoring for scheduled jobs
|
|
69
|
+
|
|
70
|
+
#### ActiveJob Options (handled by sentry-rails)
|
|
71
|
+
|
|
72
|
+
- `config.rails.active_job_report_on_retry_error` (default: `false`): Only report errors after all retry attempts are exhausted
|
|
73
|
+
- `config.send_default_pii` (default: `false`): Include job arguments in error context (be careful with sensitive data)
|
|
74
|
+
- `config.sdk_logger` (default: `nil`): Configure the SDK logger for custom logging needs (general Sentry configuration)
|
|
75
|
+
|
|
76
|
+
**Note**: The Good Job integration now leverages sentry-rails for core ActiveJob functionality, including trace propagation, user context preservation, and error reporting. This provides better integration and reduces duplication.
|
|
77
|
+
|
|
78
|
+
## Usage
|
|
79
|
+
|
|
80
|
+
### Automatic Setup
|
|
81
|
+
|
|
82
|
+
The integration works automatically once installed. It will:
|
|
83
|
+
|
|
84
|
+
1. **Capture exceptions** from ActiveJob workers using sentry-rails
|
|
85
|
+
2. **Set up performance monitoring** for job execution with enhanced GoodJob-specific metrics
|
|
86
|
+
3. **Automatically configure cron monitoring** for scheduled jobs
|
|
87
|
+
4. **Preserve user context and trace propagation** across job executions
|
|
88
|
+
5. **Add GoodJob-specific context** including queue name, executions, priority, and latency
|
|
89
|
+
|
|
90
|
+
### Cron Monitoring
|
|
91
|
+
|
|
92
|
+
For scheduled jobs, cron monitoring is automatically set up based on your Good Job configuration:
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
# config/application.rb
|
|
96
|
+
config.good_job.cron = {
|
|
97
|
+
'my_scheduled_job' => {
|
|
98
|
+
class: 'MyScheduledJob',
|
|
99
|
+
cron: '0 * * * *' # Every hour
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
You can also manually set up cron monitoring:
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
class MyScheduledJob < ApplicationJob
|
|
108
|
+
include Sentry::Cron::MonitorCheckIns
|
|
109
|
+
|
|
110
|
+
sentry_monitor_check_ins(
|
|
111
|
+
slug: "my_scheduled_job",
|
|
112
|
+
monitor_config: Sentry::Cron::MonitorConfig.from_crontab("0 * * * *", timezone: "UTC")
|
|
113
|
+
)
|
|
114
|
+
end
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Custom Error Handling
|
|
118
|
+
|
|
119
|
+
The integration respects ActiveJob's retry configuration and will only report errors based on your settings:
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
class MyJob < ApplicationJob
|
|
123
|
+
retry_on StandardError, wait: :exponentially_longer, attempts: 3
|
|
124
|
+
|
|
125
|
+
def perform
|
|
126
|
+
# This will only be reported to Sentry after 3 attempts if active_job_report_on_retry_error is true
|
|
127
|
+
raise "Something went wrong"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Debugging and Detailed Logging
|
|
133
|
+
|
|
134
|
+
The integration uses the standard Sentry SDK logger (`Sentry.configuration.sdk_logger`) for all logging needs. You can configure this logger to get detailed information about what the integration is doing:
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
Sentry.init do |config|
|
|
138
|
+
config.dsn = 'your-dsn-here'
|
|
139
|
+
|
|
140
|
+
# Configure the SDK logger for debugging
|
|
141
|
+
config.sdk_logger = Logger.new($stdout)
|
|
142
|
+
config.sdk_logger.level = Logger::DEBUG
|
|
143
|
+
|
|
144
|
+
# Or use Rails logger with debug level
|
|
145
|
+
# config.sdk_logger = Rails.logger
|
|
146
|
+
# config.sdk_logger.level = Logger::DEBUG
|
|
147
|
+
end
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### Log Levels
|
|
151
|
+
|
|
152
|
+
The integration logs at different levels:
|
|
153
|
+
- **INFO**: Integration setup, cron monitoring configuration, job monitoring setup
|
|
154
|
+
- **WARN**: Configuration issues, missing job classes, cron parsing errors
|
|
155
|
+
- **DEBUG**: Detailed execution flow (when debug level is enabled)
|
|
156
|
+
|
|
157
|
+
#### What Gets Logged
|
|
158
|
+
|
|
159
|
+
When logging is enabled, you'll see information about:
|
|
160
|
+
- Job execution start and completion
|
|
161
|
+
- Error capture and reporting decisions
|
|
162
|
+
- Cron monitoring setup and configuration
|
|
163
|
+
- Performance metrics collection
|
|
164
|
+
- GoodJob-specific context enhancement
|
|
165
|
+
- Integration initialization and setup
|
|
166
|
+
|
|
167
|
+
## Performance Monitoring
|
|
168
|
+
|
|
169
|
+
When performance monitoring is enabled, the integration will track:
|
|
170
|
+
|
|
171
|
+
- Job execution time
|
|
172
|
+
- Queue latency (GoodJob-specific)
|
|
173
|
+
- Retry counts
|
|
174
|
+
- Job context and metadata
|
|
175
|
+
- GoodJob-specific metrics (queue name, executions, priority)
|
|
176
|
+
|
|
177
|
+
## Error Context
|
|
178
|
+
|
|
179
|
+
The integration automatically adds relevant context to error reports:
|
|
180
|
+
|
|
181
|
+
- Job class name
|
|
182
|
+
- Job ID
|
|
183
|
+
- Queue name (GoodJob-specific)
|
|
184
|
+
- Execution count (GoodJob-specific)
|
|
185
|
+
- Priority (GoodJob-specific)
|
|
186
|
+
- Enqueued and scheduled timestamps
|
|
187
|
+
- Job arguments (if enabled via send_default_pii)
|
|
188
|
+
- Latency metrics (GoodJob-specific)
|
|
189
|
+
|
|
190
|
+
## Compatibility
|
|
191
|
+
|
|
192
|
+
- Ruby 2.4+
|
|
193
|
+
- Rails 5.2+
|
|
194
|
+
- Good Job 3.0+
|
|
195
|
+
- Sentry Ruby SDK 5.28.0+
|
|
196
|
+
|
|
197
|
+
## Contributing
|
|
198
|
+
|
|
199
|
+
We welcome contributions! Please see our [contributing guidelines](https://github.com/getsentry/sentry-ruby/blob/master/CONTRIBUTING.md) for details.
|
|
200
|
+
|
|
201
|
+
## License
|
|
202
|
+
|
|
203
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE.txt) file for details.
|
data/SECURITY.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# SECURITY
|
|
2
|
+
|
|
3
|
+
## Reporting a Vulnerability
|
|
4
|
+
|
|
5
|
+
**Do NOT** open a public GitHub issue for security vulnerabilities.
|
|
6
|
+
|
|
7
|
+
Email security details to: **security@kiskolabs.com**
|
|
8
|
+
|
|
9
|
+
Include: description, steps to reproduce, potential impact, and suggested fix (if available).
|
|
10
|
+
|
|
11
|
+
### Response Timeline
|
|
12
|
+
|
|
13
|
+
- We will acknowledge receipt of your report
|
|
14
|
+
- We will provide an initial assessment
|
|
15
|
+
- We will keep you informed of our progress and resolution timeline
|
|
16
|
+
|
|
17
|
+
### Disclosure Policy
|
|
18
|
+
|
|
19
|
+
- We will work with you to understand and resolve the issue
|
|
20
|
+
- We will credit you for the discovery (unless you prefer to remain anonymous)
|
|
21
|
+
- We will publish a security advisory after the vulnerability is patched
|
|
22
|
+
- We will coordinate public disclosure with you
|
|
23
|
+
|
|
24
|
+
## Automation Security
|
|
25
|
+
|
|
26
|
+
* **Context Isolation:** It is strictly forbidden to include production credentials, API keys, or Personally Identifiable Information (PII) in prompts sent to third-party LLMs or automation services.
|
|
27
|
+
|
|
28
|
+
* **Supply Chain:** All automated dependencies must be verified.
|
data/bin/console
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "bundler/setup"
|
|
5
|
+
require "sentry-good_job"
|
|
6
|
+
|
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
9
|
+
|
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
11
|
+
# require "pry"
|
|
12
|
+
# Pry.start
|
|
13
|
+
|
|
14
|
+
require "irb"
|
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "fileutils"
|
|
5
|
+
|
|
6
|
+
# path to your application root.
|
|
7
|
+
APP_ROOT = File.expand_path("..", __dir__)
|
|
8
|
+
|
|
9
|
+
def system!(*args)
|
|
10
|
+
system(*args) || abort("\n== Command #{args} failed ==")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
FileUtils.chdir APP_ROOT do
|
|
14
|
+
# This script is a way to set up or update your development environment automatically.
|
|
15
|
+
# This script is idempotent, so that you can run it at any time and get an expectable outcome.
|
|
16
|
+
# Add necessary setup steps to this file.
|
|
17
|
+
|
|
18
|
+
puts "== Installing dependencies =="
|
|
19
|
+
system! "gem install bundler --conservative"
|
|
20
|
+
system("bundle check") || system!("bundle install")
|
|
21
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# GoodJob-specific extensions to sentry-rails ActiveJob integration
|
|
4
|
+
# This module enhances sentry-rails ActiveJob with GoodJob-specific functionality:
|
|
5
|
+
# - GoodJob-specific context and tags
|
|
6
|
+
# - GoodJob-specific span data enhancements
|
|
7
|
+
module Sentry
|
|
8
|
+
module GoodJob
|
|
9
|
+
module ActiveJobExtensions
|
|
10
|
+
# Enhance sentry-rails ActiveJob context with GoodJob-specific data
|
|
11
|
+
def self.enhance_sentry_context(job, base_context)
|
|
12
|
+
return base_context unless job.respond_to?(:queue_name) && job.respond_to?(:executions)
|
|
13
|
+
|
|
14
|
+
# Add GoodJob-specific context to the existing sentry-rails context
|
|
15
|
+
good_job_context = {
|
|
16
|
+
queue_name: job.queue_name,
|
|
17
|
+
executions: job.executions,
|
|
18
|
+
enqueued_at: job.enqueued_at,
|
|
19
|
+
priority: job.respond_to?(:priority) ? job.priority : nil
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# Merge with base context, preserving existing structure
|
|
23
|
+
base_context.merge(good_job: good_job_context)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Enhance sentry-rails ActiveJob tags with GoodJob-specific data
|
|
27
|
+
def self.enhance_sentry_tags(job, base_tags)
|
|
28
|
+
return base_tags unless job.respond_to?(:queue_name) && job.respond_to?(:executions)
|
|
29
|
+
|
|
30
|
+
good_job_tags = {
|
|
31
|
+
queue_name: job.queue_name,
|
|
32
|
+
executions: job.executions
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Add priority if available
|
|
36
|
+
if job.respond_to?(:priority)
|
|
37
|
+
good_job_tags[:priority] = job.priority
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
base_tags.merge(good_job_tags)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Set up GoodJob-specific ActiveJob extensions
|
|
44
|
+
def self.setup
|
|
45
|
+
return unless defined?(::Rails) && ::Sentry.initialized?
|
|
46
|
+
|
|
47
|
+
# Hook into sentry-rails ActiveJob integration
|
|
48
|
+
if defined?(::Sentry::Rails::ActiveJobExtensions::SentryReporter)
|
|
49
|
+
enhance_sentry_reporter
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Set up GoodJob-specific ActiveJob extensions
|
|
53
|
+
setup_good_job_extensions
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.enhance_sentry_reporter
|
|
57
|
+
return if defined?(@reporter_enhanced) && @reporter_enhanced
|
|
58
|
+
|
|
59
|
+
# Enhance the sentry_context method in SentryReporter
|
|
60
|
+
::Sentry::Rails::ActiveJobExtensions::SentryReporter.class_eval do
|
|
61
|
+
class << self
|
|
62
|
+
alias_method :original_sentry_context, :sentry_context
|
|
63
|
+
|
|
64
|
+
def sentry_context(job)
|
|
65
|
+
base_context = original_sentry_context(job)
|
|
66
|
+
Sentry::GoodJob::ActiveJobExtensions.enhance_sentry_context(job, base_context)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
@reporter_enhanced = true
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.setup_good_job_extensions
|
|
75
|
+
# Extend ActiveJob::Base with GoodJob-specific functionality
|
|
76
|
+
ActiveSupport.on_load(:active_job) do
|
|
77
|
+
# Add GoodJob-specific attributes and methods
|
|
78
|
+
include GoodJobExtensions
|
|
79
|
+
|
|
80
|
+
# Ensure the sentry-rails integration is properly set up
|
|
81
|
+
# by checking if the ActiveJobExtensions module is already included
|
|
82
|
+
if defined?(::Sentry::Rails::ActiveJobExtensions) && !ancestors.include?(::Sentry::Rails::ActiveJobExtensions)
|
|
83
|
+
require "sentry/rails/active_job"
|
|
84
|
+
prepend ::Sentry::Rails::ActiveJobExtensions
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
private_class_method :enhance_sentry_reporter, :setup_good_job_extensions
|
|
90
|
+
|
|
91
|
+
# GoodJob-specific extensions for ActiveJob
|
|
92
|
+
module GoodJobExtensions
|
|
93
|
+
extend ActiveSupport::Concern
|
|
94
|
+
|
|
95
|
+
included do
|
|
96
|
+
# Set up around_enqueue hook for GoodJob-specific enqueue span
|
|
97
|
+
around_enqueue do |job, block|
|
|
98
|
+
next block.call unless ::Sentry.initialized?
|
|
99
|
+
|
|
100
|
+
# Create enqueue span with GoodJob-specific data
|
|
101
|
+
::Sentry.with_child_span(op: "queue.publish", description: job.class.name) do |span|
|
|
102
|
+
_sentry_set_span_data(span, job)
|
|
103
|
+
block.call
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# GoodJob-specific context is now handled through the enhanced sentry_context method
|
|
108
|
+
# The sentry-rails integration handles error capturing through SentryReporter.record
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
# Override _sentry_set_span_data to add GoodJob-specific functionality
|
|
114
|
+
def _sentry_set_span_data(span, job, retry_count: nil)
|
|
115
|
+
return unless span
|
|
116
|
+
|
|
117
|
+
# Call the base implementation if it exists (from sentry-rails)
|
|
118
|
+
if respond_to?(:_sentry_set_span_data, true) && method(:_sentry_set_span_data).super_method
|
|
119
|
+
super
|
|
120
|
+
else
|
|
121
|
+
# Fallback: implement base functionality directly
|
|
122
|
+
span.set_data("messaging.message.id", job.job_id)
|
|
123
|
+
span.set_data("messaging.destination.name", job.queue_name) if job.respond_to?(:queue_name)
|
|
124
|
+
span.set_data("messaging.message.retry.count", retry_count) if retry_count
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Add GoodJob-specific span data (latency)
|
|
128
|
+
latency = calculate_job_latency(job)
|
|
129
|
+
span.set_data("messaging.message.receive.latency", latency) if latency
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Calculate job latency in milliseconds (GoodJob-specific)
|
|
133
|
+
def calculate_job_latency(job)
|
|
134
|
+
return nil unless job.enqueued_at
|
|
135
|
+
|
|
136
|
+
((Time.now.utc - job.enqueued_at) * 1000).to_i
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sentry
|
|
4
|
+
class Configuration
|
|
5
|
+
attr_reader :good_job
|
|
6
|
+
|
|
7
|
+
add_post_initialization_callback do
|
|
8
|
+
@good_job = Sentry::GoodJob::Configuration.new
|
|
9
|
+
@excluded_exceptions = @excluded_exceptions.concat(Sentry::GoodJob::IGNORE_DEFAULT)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module GoodJob
|
|
14
|
+
IGNORE_DEFAULT = [
|
|
15
|
+
"ActiveJob::DeserializationError",
|
|
16
|
+
"ActiveJob::SerializationError"
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
class Configuration
|
|
20
|
+
# Whether to enable cron monitoring for all scheduled jobs
|
|
21
|
+
# This is GoodJob-specific functionality for monitoring scheduled tasks
|
|
22
|
+
attr_accessor :enable_cron_monitors
|
|
23
|
+
|
|
24
|
+
def initialize
|
|
25
|
+
@enable_cron_monitors = true
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Helper methods for adding GoodJob-specific information to Sentry context
|
|
4
|
+
# This works WITH sentry-rails, not against it
|
|
5
|
+
module Sentry
|
|
6
|
+
module GoodJob
|
|
7
|
+
module ContextHelpers
|
|
8
|
+
# Add GoodJob-specific information to the existing Sentry Rails context
|
|
9
|
+
def self.add_context(job, base_context = {})
|
|
10
|
+
return base_context unless job.respond_to?(:queue_name) && job.respond_to?(:executions)
|
|
11
|
+
|
|
12
|
+
good_job_context = {
|
|
13
|
+
queue_name: job.queue_name,
|
|
14
|
+
executions: job.executions,
|
|
15
|
+
enqueued_at: job.enqueued_at,
|
|
16
|
+
priority: job.respond_to?(:priority) ? job.priority : nil
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# Note: Job arguments are handled by sentry-rails via send_default_pii configuration
|
|
20
|
+
# This is controlled by Sentry.configuration.send_default_pii, not GoodJob-specific config
|
|
21
|
+
|
|
22
|
+
# Merge with base context
|
|
23
|
+
base_context.merge(good_job: good_job_context)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Add GoodJob-specific information to the existing Sentry Rails tags
|
|
27
|
+
def self.add_tags(job, base_tags = {})
|
|
28
|
+
return base_tags unless job.respond_to?(:queue_name) && job.respond_to?(:executions)
|
|
29
|
+
|
|
30
|
+
good_job_tags = {
|
|
31
|
+
queue_name: job.queue_name,
|
|
32
|
+
executions: job.executions
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Add priority if available
|
|
36
|
+
if job.respond_to?(:priority)
|
|
37
|
+
good_job_tags[:priority] = job.priority
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
base_tags.merge(good_job_tags)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Sentry Cron Monitoring for Active Job
|
|
4
|
+
# This module provides comprehensive cron monitoring for Active Job scheduled tasks
|
|
5
|
+
# It works with any Active Job adapter, including GoodJob
|
|
6
|
+
# Following Active Job's extension patterns and Sentry's integration guidelines
|
|
7
|
+
module Sentry
|
|
8
|
+
module GoodJob
|
|
9
|
+
module CronHelpers
|
|
10
|
+
# Utility methods for cron parsing and configuration
|
|
11
|
+
# These methods handle the conversion between Good Job cron expressions and Sentry monitor configs
|
|
12
|
+
module Helpers
|
|
13
|
+
# Parse cron expression and create Sentry monitor config
|
|
14
|
+
def self.monitor_config_from_cron(cron_expression, timezone: nil)
|
|
15
|
+
return nil unless cron_expression && !cron_expression.strip.empty?
|
|
16
|
+
|
|
17
|
+
# Parse cron expression using fugit (same as Good Job)
|
|
18
|
+
parsed_cron = Fugit.parse_cron(cron_expression)
|
|
19
|
+
return nil unless parsed_cron
|
|
20
|
+
|
|
21
|
+
# Convert to Sentry monitor config
|
|
22
|
+
if timezone && !timezone.strip.empty?
|
|
23
|
+
::Sentry::Cron::MonitorConfig.from_crontab(cron_expression, timezone: timezone)
|
|
24
|
+
else
|
|
25
|
+
::Sentry::Cron::MonitorConfig.from_crontab(cron_expression)
|
|
26
|
+
end
|
|
27
|
+
rescue => e
|
|
28
|
+
Sentry.configuration.sdk_logger.warn "Failed to parse cron expression '#{cron_expression}': #{e.message}"
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Generate monitor slug from job name
|
|
33
|
+
def self.monitor_slug(job_name)
|
|
34
|
+
job_name.to_s.underscore.gsub(/_job$/, "")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Parse cron expression and extract timezone
|
|
38
|
+
def self.parse_cron_with_timezone(cron_expression)
|
|
39
|
+
return [cron_expression, nil] unless cron_expression && !cron_expression.strip.empty?
|
|
40
|
+
|
|
41
|
+
parts = cron_expression.strip.split(" ")
|
|
42
|
+
return [cron_expression, nil] unless parts.length > 5
|
|
43
|
+
|
|
44
|
+
# Last part might be timezone
|
|
45
|
+
timezone = parts.last
|
|
46
|
+
# Comprehensive timezone validation that handles:
|
|
47
|
+
# - Standard timezone names (UTC, GMT)
|
|
48
|
+
# - IANA timezone identifiers (America/New_York, Europe/Stockholm)
|
|
49
|
+
# - Multi-level IANA timezones (America/Argentina/Buenos_Aires)
|
|
50
|
+
# - UTC offsets (UTC+2, UTC-5, GMT+1, GMT-8)
|
|
51
|
+
# - Numeric timezones (GMT-5, UTC+2)
|
|
52
|
+
if timezone.match?(/^[A-Za-z_]+$/) || # Simple timezone names (UTC, GMT, EST, etc.)
|
|
53
|
+
timezone.match?(/^[A-Za-z_]+\/[A-Za-z_]+$/) || # Single slash timezones (Europe/Stockholm)
|
|
54
|
+
timezone.match?(/^[A-Za-z_]+\/[A-Za-z_]+\/[A-Za-z_]+$/) || # Multi-slash timezones (America/Argentina/Buenos_Aires)
|
|
55
|
+
timezone.match?(/^[A-Za-z_]+[+-]\d+$/) || # UTC/GMT offsets (UTC+2, GMT-5)
|
|
56
|
+
timezone.match?(/^[A-Za-z_]+\/[A-Za-z_]+[+-]\d+$/) # IANA with offset (Europe/Stockholm+1)
|
|
57
|
+
cron_without_timezone = cron_expression.gsub(/\s+#{Regexp.escape(timezone)}$/, "")
|
|
58
|
+
[cron_without_timezone, timezone]
|
|
59
|
+
else
|
|
60
|
+
[cron_expression, nil]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Main integration class that handles all cron monitoring setup
|
|
66
|
+
# This class follows Good Job's integration patterns and Sentry's extension guidelines
|
|
67
|
+
class Integration
|
|
68
|
+
# Track whether setup has already been performed to prevent duplicates
|
|
69
|
+
@setup_completed = false
|
|
70
|
+
@reload_hooked = false
|
|
71
|
+
|
|
72
|
+
# Set up monitoring for all scheduled jobs from Good Job configuration
|
|
73
|
+
def self.setup_monitoring_for_scheduled_jobs
|
|
74
|
+
return unless ::Sentry.initialized?
|
|
75
|
+
return unless ::Sentry.configuration.good_job.enable_cron_monitors
|
|
76
|
+
attach_reload_hook_if_available
|
|
77
|
+
return if @setup_completed
|
|
78
|
+
|
|
79
|
+
return unless defined?(::Rails) && ::Rails.respond_to?(:application) && ::Rails.application
|
|
80
|
+
cron_config = ::Rails.application.config.good_job.cron
|
|
81
|
+
return if cron_config.blank?
|
|
82
|
+
|
|
83
|
+
added_jobs = []
|
|
84
|
+
cron_config.each do |cron_key, job_config|
|
|
85
|
+
job_name = setup_monitoring_for_job(cron_key, job_config)
|
|
86
|
+
added_jobs << job_name if job_name
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
@setup_completed = true
|
|
90
|
+
if added_jobs.any?
|
|
91
|
+
job_list = added_jobs.join(", ")
|
|
92
|
+
Sentry.configuration.sdk_logger.info "Sentry cron monitoring setup for #{added_jobs.size} scheduled jobs: #{job_list}"
|
|
93
|
+
else
|
|
94
|
+
Sentry.configuration.sdk_logger.info "Sentry cron monitoring setup for #{cron_config.keys.size} scheduled jobs"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Reset setup state (primarily for testing)
|
|
99
|
+
def self.reset_setup_state!
|
|
100
|
+
@setup_completed = false
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Set up monitoring for a specific job
|
|
104
|
+
def self.setup_monitoring_for_job(cron_key, job_config)
|
|
105
|
+
job_class_name = job_config[:class]
|
|
106
|
+
cron_expression = job_config[:cron]
|
|
107
|
+
|
|
108
|
+
return unless job_class_name && cron_expression
|
|
109
|
+
|
|
110
|
+
# Defer job class constantization to avoid boot-time issues
|
|
111
|
+
# The job class will be constantized when the job is actually executed
|
|
112
|
+
# This prevents issues during development boot and circular dependencies
|
|
113
|
+
|
|
114
|
+
# Store the monitoring configuration for later use
|
|
115
|
+
# We'll set up the monitoring when the job class is first loaded
|
|
116
|
+
deferred_setup = lambda do
|
|
117
|
+
job_class = begin
|
|
118
|
+
job_class_name.constantize
|
|
119
|
+
rescue NameError => e
|
|
120
|
+
Sentry.configuration.sdk_logger.warn "Could not find job class '#{job_class_name}' for Sentry cron monitoring: #{e.message}"
|
|
121
|
+
return
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Include Sentry::Cron::MonitorCheckIns module for cron monitoring
|
|
125
|
+
# only patch if not explicitly included in job by user
|
|
126
|
+
unless job_class.ancestors.include?(Sentry::Cron::MonitorCheckIns)
|
|
127
|
+
job_class.include(Sentry::Cron::MonitorCheckIns)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Parse cron expression and create monitor config
|
|
131
|
+
cron_without_tz, timezone = Sentry::GoodJob::CronHelpers::Helpers.parse_cron_with_timezone(cron_expression)
|
|
132
|
+
monitor_config = Sentry::GoodJob::CronHelpers::Helpers.monitor_config_from_cron(cron_without_tz, timezone: timezone)
|
|
133
|
+
|
|
134
|
+
if monitor_config
|
|
135
|
+
# Configure Sentry cron monitoring - use cron_key as slug for consistency
|
|
136
|
+
monitor_slug = Sentry::GoodJob::CronHelpers::Helpers.monitor_slug(cron_key)
|
|
137
|
+
|
|
138
|
+
job_class.sentry_monitor_check_ins(
|
|
139
|
+
slug: monitor_slug,
|
|
140
|
+
monitor_config: monitor_config
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
job_class_name
|
|
144
|
+
else
|
|
145
|
+
Sentry.configuration.sdk_logger.warn "Could not create monitor config for #{job_class_name} with cron '#{cron_expression}'"
|
|
146
|
+
nil
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Set up monitoring when the job class is first loaded
|
|
151
|
+
# This defers constantization until the job is actually needed
|
|
152
|
+
if defined?(::Rails) && ::Rails.respond_to?(:application) && ::Rails.application
|
|
153
|
+
::Rails.application.config.after_initialize do
|
|
154
|
+
deferred_setup.call
|
|
155
|
+
end
|
|
156
|
+
else
|
|
157
|
+
# Fallback for non-Rails environments
|
|
158
|
+
deferred_setup.call
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Return the job name for logging purposes
|
|
162
|
+
job_class_name
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Manually add cron monitoring to a specific job
|
|
166
|
+
def self.add_monitoring_to_job(job_class, slug: nil, cron_expression: nil, timezone: nil)
|
|
167
|
+
return unless ::Sentry.initialized?
|
|
168
|
+
|
|
169
|
+
# Include Sentry::Cron::MonitorCheckIns module for cron monitoring
|
|
170
|
+
# only patch if not explicitly included in job by user
|
|
171
|
+
unless job_class.ancestors.include?(Sentry::Cron::MonitorCheckIns)
|
|
172
|
+
job_class.include(Sentry::Cron::MonitorCheckIns)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Create monitor config
|
|
176
|
+
monitor_config = if cron_expression
|
|
177
|
+
Sentry::GoodJob::CronHelpers::Helpers.monitor_config_from_cron(cron_expression, timezone: timezone)
|
|
178
|
+
else
|
|
179
|
+
# Default to hourly monitoring if no cron expression provided
|
|
180
|
+
::Sentry::Cron::MonitorConfig.from_crontab("0 * * * *")
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
if monitor_config
|
|
184
|
+
monitor_slug = slug || Sentry::GoodJob::CronHelpers::Helpers.monitor_slug(job_class.name)
|
|
185
|
+
|
|
186
|
+
job_class.sentry_monitor_check_ins(
|
|
187
|
+
slug: monitor_slug,
|
|
188
|
+
monitor_config: monitor_config
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
Sentry.configuration.sdk_logger.info "Added Sentry cron monitoring for #{job_class.name} (#{monitor_slug})"
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def self.attach_reload_hook_if_available
|
|
196
|
+
return if @reload_hooked
|
|
197
|
+
return unless defined?(::ActiveSupport::Reloader)
|
|
198
|
+
|
|
199
|
+
::ActiveSupport::Reloader.to_prepare do
|
|
200
|
+
@setup_completed = false
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
@reload_hooked = true
|
|
204
|
+
rescue NameError
|
|
205
|
+
# ActiveSupport::Reloader not available in this environment
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "good_job"
|
|
4
|
+
require "sentry-ruby"
|
|
5
|
+
require "sentry/integrable"
|
|
6
|
+
require "sentry/good_job/version"
|
|
7
|
+
require "sentry/good_job/configuration"
|
|
8
|
+
require "sentry/good_job/context_helpers"
|
|
9
|
+
require "sentry/good_job/active_job_extensions"
|
|
10
|
+
require "sentry/good_job/cron_helpers"
|
|
11
|
+
|
|
12
|
+
module Sentry
|
|
13
|
+
module GoodJob
|
|
14
|
+
extend Sentry::Integrable
|
|
15
|
+
|
|
16
|
+
register_integration name: "good_job", version: Sentry::GoodJob::VERSION
|
|
17
|
+
|
|
18
|
+
if defined?(::Rails::Railtie)
|
|
19
|
+
class Railtie < ::Rails::Railtie
|
|
20
|
+
config.after_initialize do
|
|
21
|
+
next unless Sentry.initialized? && defined?(::Sentry::Rails)
|
|
22
|
+
|
|
23
|
+
# Automatic setup for Good Job when the integration is enabled
|
|
24
|
+
if Sentry.configuration.enabled_patches.include?(:good_job)
|
|
25
|
+
Sentry::GoodJob.setup_good_job_integration
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.setup_good_job_integration
|
|
32
|
+
# Enhance sentry-rails ActiveJob integration with GoodJob-specific context
|
|
33
|
+
Sentry::GoodJob::ActiveJobExtensions.setup
|
|
34
|
+
|
|
35
|
+
# Set up cron monitoring for all scheduled jobs (automatically configured from Good Job config)
|
|
36
|
+
if Sentry.configuration.good_job.enable_cron_monitors
|
|
37
|
+
Sentry::GoodJob::CronHelpers::Integration.setup_monitoring_for_scheduled_jobs
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
Sentry.configuration.sdk_logger.info "Sentry Good Job integration initialized automatically"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Delegate capture_exception so internal components can be tested in isolation
|
|
44
|
+
def self.capture_exception(exception, **options)
|
|
45
|
+
::Sentry.capture_exception(exception, **options)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/sentry/good_job/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "sentry-good_job"
|
|
7
|
+
spec.version = Sentry::GoodJob::VERSION
|
|
8
|
+
spec.authors = ["Sentry Team", "Andrei Makarov"]
|
|
9
|
+
spec.summary = "GoodJob integration for the Sentry error logger"
|
|
10
|
+
spec.description = "Adds Sentry instrumentation, context helpers, and cron monitoring support to GoodJob-backed ActiveJob workloads."
|
|
11
|
+
spec.email = "contact@kiskolabs.com"
|
|
12
|
+
spec.license = "MIT"
|
|
13
|
+
|
|
14
|
+
spec.platform = Gem::Platform::RUBY
|
|
15
|
+
spec.required_ruby_version = ">= 2.4"
|
|
16
|
+
spec.extra_rdoc_files = ["README.md", "LICENSE.txt"]
|
|
17
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
18
|
+
Dir[
|
|
19
|
+
"lib/**/*",
|
|
20
|
+
"bin/*",
|
|
21
|
+
"CHANGELOG.md",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE.txt",
|
|
24
|
+
"CODE_OF_CONDUCT.md",
|
|
25
|
+
"CONTRIBUTING.md",
|
|
26
|
+
"GOVERNANCE.md",
|
|
27
|
+
"SECURITY.md",
|
|
28
|
+
"sentry-good_job.gemspec"
|
|
29
|
+
].select { |path| File.file?(path) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
github_root_uri = "https://github.com/amkisko/sentry-good_job"
|
|
33
|
+
spec.homepage = github_root_uri
|
|
34
|
+
|
|
35
|
+
spec.metadata = {
|
|
36
|
+
"homepage_uri" => spec.homepage,
|
|
37
|
+
"source_code_uri" => "#{github_root_uri}/tree/main",
|
|
38
|
+
"changelog_uri" => "#{github_root_uri}/blob/main/CHANGELOG.md",
|
|
39
|
+
"bug_tracker_uri" => "#{github_root_uri}/issues",
|
|
40
|
+
"documentation_uri" => "http://www.rubydoc.info/gems/#{spec.name}/#{spec.version}"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
spec.bindir = "exe"
|
|
44
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
45
|
+
spec.require_paths = ["lib"]
|
|
46
|
+
|
|
47
|
+
spec.add_dependency "sentry-ruby", "~> 6"
|
|
48
|
+
spec.add_dependency "good_job", "~> 4"
|
|
49
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: sentry-good_job
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 6.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Sentry Team
|
|
8
|
+
- Andrei Makarov
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: sentry-ruby
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '6'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '6'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: good_job
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '4'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '4'
|
|
41
|
+
description: Adds Sentry instrumentation, context helpers, and cron monitoring support
|
|
42
|
+
to GoodJob-backed ActiveJob workloads.
|
|
43
|
+
email: contact@kiskolabs.com
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files:
|
|
47
|
+
- LICENSE.txt
|
|
48
|
+
- README.md
|
|
49
|
+
files:
|
|
50
|
+
- CHANGELOG.md
|
|
51
|
+
- CODE_OF_CONDUCT.md
|
|
52
|
+
- CONTRIBUTING.md
|
|
53
|
+
- GOVERNANCE.md
|
|
54
|
+
- LICENSE.txt
|
|
55
|
+
- README.md
|
|
56
|
+
- SECURITY.md
|
|
57
|
+
- bin/console
|
|
58
|
+
- bin/setup
|
|
59
|
+
- lib/sentry-good_job.rb
|
|
60
|
+
- lib/sentry/good_job.rb
|
|
61
|
+
- lib/sentry/good_job/active_job_extensions.rb
|
|
62
|
+
- lib/sentry/good_job/configuration.rb
|
|
63
|
+
- lib/sentry/good_job/context_helpers.rb
|
|
64
|
+
- lib/sentry/good_job/cron_helpers.rb
|
|
65
|
+
- lib/sentry/good_job/version.rb
|
|
66
|
+
- sentry-good_job.gemspec
|
|
67
|
+
homepage: https://github.com/amkisko/sentry-good_job
|
|
68
|
+
licenses:
|
|
69
|
+
- MIT
|
|
70
|
+
metadata:
|
|
71
|
+
homepage_uri: https://github.com/amkisko/sentry-good_job
|
|
72
|
+
source_code_uri: https://github.com/amkisko/sentry-good_job/tree/main
|
|
73
|
+
changelog_uri: https://github.com/amkisko/sentry-good_job/blob/main/CHANGELOG.md
|
|
74
|
+
bug_tracker_uri: https://github.com/amkisko/sentry-good_job/issues
|
|
75
|
+
documentation_uri: http://www.rubydoc.info/gems/sentry-good_job/6.2.0
|
|
76
|
+
rdoc_options: []
|
|
77
|
+
require_paths:
|
|
78
|
+
- lib
|
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '2.4'
|
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
requirements: []
|
|
90
|
+
rubygems_version: 3.6.9
|
|
91
|
+
specification_version: 4
|
|
92
|
+
summary: GoodJob integration for the Sentry error logger
|
|
93
|
+
test_files: []
|