├── .github
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
└── workflows
│ ├── changelog-release.yml
│ ├── changelog-update.yml
│ ├── dependabot-auto-merge.yml
│ ├── docs.yml
│ ├── pull-request-description-check.yml
│ ├── release-description-update.yml
│ ├── static-analyze.yml
│ └── tests.yml
├── .gitignore
├── .php-cs-fixer.php
├── AppInsightsPHPBundle.php
├── CHANGELOG.md
├── Cache
└── NullCache.php
├── Command
├── TrackDependencyCommand.php
├── TrackEventCommand.php
├── TrackExceptionCommand.php
└── TrackMetricCommand.php
├── DependencyInjection
├── AppInsightsPHPExtension.php
├── Compiler
│ └── DoctrineDependencyPassPass.php
└── Configuration.php
├── FlatArray.php
├── LICENSE
├── Listener
├── ExceptionListener.php
├── HttpRequestListener.php
└── KernelTerminateListener.php
├── README.md
├── Resources
├── config
│ ├── app_insights_php.php
│ ├── app_insights_php_console.php
│ ├── app_insights_php_doctrine.php
│ ├── app_insights_php_monolog.php
│ ├── app_insights_php_symfony.php
│ └── app_insights_php_twig.php
└── doc
│ ├── dependencies.md
│ ├── how_it_works.md
│ ├── index.md
│ ├── page_views.md
│ └── traces.md
├── Tests
├── Command
│ ├── TrackDependencyCommandTest.php
│ ├── TrackEventCommandTest.php
│ ├── TrackExceptionCommandTest.php
│ └── TrackMetricCommandTest.php
├── DependencyInjection
│ ├── AppInsightsPHPExtensionTest.php
│ └── ConfigurationTest.php
├── FlatArrayTest.php
├── Functional
│ ├── AppKernel.php
│ ├── README.md
│ ├── bin
│ │ └── console
│ └── config
│ │ └── app_insights_php.php.dist
├── Listener
│ └── KernelTerminateListenerTest.php
└── Twig
│ └── TelemetryExtensionTest.php
├── Twig
└── TelemetryExtension.php
├── composer.json
├── composer.lock
├── phpunit.xml.dist
└── shell.nix
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
Change Log
3 |
4 |
Added
5 |
8 |
Fixed
9 |
12 |
Changed
13 |
16 |
Removed
17 |
20 |
Deprecated
21 |
24 |
Security
25 |
28 |
29 |
30 |
31 | Description
32 |
33 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "composer"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 |
--------------------------------------------------------------------------------
/.github/workflows/changelog-release.yml:
--------------------------------------------------------------------------------
1 | name: "Changelog - Release Unreleased"
2 |
3 | ###################################################################
4 | # WARNING - THIS ACTION WILL PUSH COMMIT DIRECTLY INTO REPOSITORY #
5 | ###################################################################
6 |
7 | on:
8 | push:
9 | tags:
10 | - '*'
11 |
12 | jobs:
13 | changelog-release-unreleased:
14 | name: "Update Changelog - Release Unreleased"
15 |
16 | runs-on: "ubuntu-latest"
17 |
18 | steps:
19 | - id: "tag-name"
20 | run: |
21 | tag=$(echo ${{ github.event.ref }} | cut -c11-)
22 | echo "::set-output name=tag::$tag"
23 | - name: "Update CHANGELOG"
24 | uses: "docker://aeonphp/automation:latest"
25 | env:
26 | AEON_AUTOMATION_GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
27 | with:
28 | entrypoint: "/composer/vendor/bin/automation"
29 | args: "changelog:release:unreleased ${{ github.repository }} CHANGELOG.md ${{ steps.tag-name.outputs.tag }} --github-file-changelog-update"
30 |
--------------------------------------------------------------------------------
/.github/workflows/changelog-update.yml:
--------------------------------------------------------------------------------
1 | name: "Changelog - Update Unreleased"
2 |
3 | ###################################################################
4 | # WARNING - THIS ACTION WILL PUSH COMMIT DIRECTLY INTO REPOSITORY #
5 | ###################################################################
6 |
7 | on:
8 | push:
9 | branches:
10 | - 1.x
11 |
12 | jobs:
13 | changelog-update-unreleased:
14 | name: "Changelog - Update Unreleased"
15 |
16 | runs-on: "ubuntu-latest"
17 |
18 | steps:
19 | - name: "Checkout"
20 | uses: "actions/checkout@v2"
21 |
22 | - name: "Restore Automation cache"
23 | uses: "actions/cache@v2"
24 | with:
25 | path: |
26 | cache
27 | key: "${{ runner.os }}-automation-${{ hashFiles('**/CHANGELOG.md') }}"
28 | restore-keys: |
29 | ${{ runner.os }}-automation-
30 |
31 | - name: "Update CHANGELOG"
32 | uses: "docker://aeonphp/automation:latest"
33 | env:
34 | AEON_AUTOMATION_GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
35 | EON_AUTOMATION_CACHE_DIR: "/github/workspace/cache"
36 | with:
37 | entrypoint: "/composer/vendor/bin/automation"
38 | args: "changelog:generate ${{ github.repository }} --github-file-update-path=CHANGELOG.md --skip-from=\"dependabot[bot]\" --skip-from=\"aeon-automation\""
39 |
--------------------------------------------------------------------------------
/.github/workflows/dependabot-auto-merge.yml:
--------------------------------------------------------------------------------
1 | name: Dependabot - Auto Merge
2 | on: pull_request
3 |
4 | permissions:
5 | contents: write
6 | pull-requests: write
7 |
8 | jobs:
9 | dependabot:
10 | runs-on: ubuntu-latest
11 | if: ${{ github.actor == 'dependabot[bot]' }}
12 | steps:
13 | - name: Dependabot metadata
14 | id: metadata
15 | uses: dependabot/fetch-metadata@v1
16 | with:
17 | github-token: "${{ secrets.GITHUB_TOKEN }}"
18 | - name: Enable auto-merge for Dependabot PRs
19 | if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}}
20 | run: gh pr merge --auto --merge "$PR_URL"
21 | env:
22 | PR_URL: ${{github.event.pull_request.html_url}}
23 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: "Documentation Linter"
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches:
7 | - "1.x"
8 |
9 | jobs:
10 | documentation-linter:
11 | name: "Documentation Linter"
12 |
13 | runs-on: "ubuntu-latest"
14 |
15 | steps:
16 | - name: "Checkout"
17 | uses: "actions/checkout@v2"
18 |
19 | - name: "MD Link Linter"
20 | uses: "docker://norberttech/md-link-linter:latest"
21 | with:
22 | entrypoint: "/composer/vendor/bin/mdlinklint"
23 | args: "--exclude=vendor ."
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.github/workflows/pull-request-description-check.yml:
--------------------------------------------------------------------------------
1 | name: "Pull Request Description Check"
2 |
3 | on:
4 | pull_request:
5 | types: ["opened", "edited", "reopened", "ready_for_review"]
6 |
7 | jobs:
8 | pull-request-description-check:
9 | name: "Pull Request Description"
10 |
11 | runs-on: "ubuntu-latest"
12 |
13 | steps:
14 | - name: "Pull Request Description - Check"
15 | uses: "docker://aeonphp/automation:latest"
16 | env:
17 | AEON_AUTOMATION_GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
18 | with:
19 | entrypoint: "/composer/vendor/bin/automation"
20 | args: "pull-request:description:check aeon-php/automation ${{ github.event.pull_request.number }} --skip-from=\"dependabot[bot]\""
--------------------------------------------------------------------------------
/.github/workflows/release-description-update.yml:
--------------------------------------------------------------------------------
1 | name: "Release - Description Update"
2 |
3 | #########################################################
4 | # WARNING - THIS ACTION WILL UPDATE RELEASE DESCRIPTION #
5 | #########################################################
6 |
7 | on:
8 | release:
9 | types:
10 | - created
11 |
12 | jobs:
13 | release-description-update:
14 | name: "Release - Description Update"
15 |
16 | runs-on: "ubuntu-latest"
17 |
18 | steps:
19 | - name: "Update CHANGELOG"
20 | uses: "docker://aeonphp/automation:latest"
21 | env:
22 | AEON_AUTOMATION_GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
23 | with:
24 | entrypoint: "/composer/vendor/bin/automation"
25 | args: "changelog:generate ${{ github.repository }} --tag=${{ github.event.release.tag_name }} --github-release-update --skip-from=\"dependabot[bot]\" --skip-from=\"aeon-automation\""
26 |
--------------------------------------------------------------------------------
/.github/workflows/static-analyze.yml:
--------------------------------------------------------------------------------
1 | name: "Static Analyze"
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches:
7 | - "1.x"
8 | schedule:
9 | - cron: '* 8 * * *'
10 |
11 | jobs:
12 | static-analyze:
13 | name: "Static Analyze"
14 |
15 | runs-on: ${{ matrix.operating-system }}
16 |
17 | strategy:
18 | matrix:
19 | dependencies:
20 | - "locked"
21 | php-version:
22 | - "8.1"
23 | operating-system:
24 | - "ubuntu-latest"
25 |
26 | steps:
27 | - name: "Checkout"
28 | uses: "actions/checkout@v2"
29 |
30 | - name: "Install PHP"
31 | uses: "shivammathur/setup-php@v2"
32 | with:
33 | coverage: pcov
34 | tools: composer:v2
35 | php-version: "${{ matrix.php-version }}"
36 | ini-values: memory_limit=-1
37 |
38 | - name: "Get Composer Cache Directory"
39 | id: composer-cache
40 | run: |
41 | echo "::set-output name=dir::$(composer config cache-files-dir)"
42 |
43 | - name: "Cache Composer dependencies"
44 | uses: "actions/cache@v2"
45 | with:
46 | path: |
47 | ${{ steps.composer-cache.outputs.dir }}
48 | key: "php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-${{ hashFiles('**/composer.lock') }}"
49 | restore-keys: |
50 | php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-
51 |
52 | - name: "Install locked dependencies"
53 | run: "composer install --no-interaction --no-progress --no-suggest"
54 |
55 | - name: "Static Analyze"
56 | run: "composer static:analyze"
57 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: "Tests"
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches:
7 | - "1.x"
8 | schedule:
9 | - cron: '* 8 * * *'
10 |
11 | jobs:
12 | tests:
13 | name: "Tests"
14 |
15 | runs-on: ${{ matrix.operating-system }}
16 |
17 | strategy:
18 | matrix:
19 | dependencies:
20 | - "locked"
21 | - "lowest"
22 | - "highest"
23 | php-version:
24 | - "8.1"
25 | - "8.2"
26 | operating-system:
27 | - "ubuntu-latest"
28 |
29 | steps:
30 | - name: "Checkout"
31 | uses: "actions/checkout@v2"
32 |
33 | - name: "Install PHP"
34 | uses: "shivammathur/setup-php@v2"
35 | with:
36 | coverage: pcov
37 | tools: composer:v2
38 | php-version: "${{ matrix.php-version }}"
39 | ini-values: memory_limit=-1
40 |
41 | - name: "Get Composer Cache Directory"
42 | id: composer-cache
43 | run: |
44 | echo "::set-output name=dir::$(composer config cache-files-dir)"
45 |
46 | - name: "Cache Composer dependencies"
47 | uses: "actions/cache@v2"
48 | with:
49 | path: |
50 | ${{ steps.composer-cache.outputs.dir }}
51 | key: "php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-${{ hashFiles('**/composer.lock') }}"
52 | restore-keys: |
53 | php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-
54 |
55 | - name: "Install lowest dependencies"
56 | if: ${{ matrix.dependencies == 'lowest' }}
57 | run: "composer update --prefer-lowest --no-interaction --no-progress --no-suggest"
58 |
59 | - name: "Install highest dependencies"
60 | if: ${{ matrix.dependencies == 'highest' }}
61 | run: "composer update --no-interaction --no-progress --no-suggest"
62 |
63 | - name: "Install locked dependencies"
64 | if: ${{ matrix.dependencies == 'locked' }}
65 | run: "composer install --no-interaction --no-progress --no-suggest"
66 |
67 | - name: "Test"
68 | run: "composer test"
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor/
2 | *.cache
3 | var
4 | /Tests/Functional/config/app_insights_php.php
--------------------------------------------------------------------------------
/.php-cs-fixer.php:
--------------------------------------------------------------------------------
1 | files()
5 | ->in([
6 | __DIR__ . '/',
7 | ]);
8 |
9 | if (!\file_exists(__DIR__ . '/var')) {
10 | \mkdir(__DIR__ . '/var');
11 | }
12 |
13 | /**
14 | * This configuration was taken from https://github.com/sebastianbergmann/phpunit/blob/master/.php_cs.dist
15 | * and slightly adjusted.
16 | */
17 | $config = new PhpCsFixer\Config();
18 |
19 | return $config
20 | ->setRiskyAllowed(true)
21 | ->setCacheFile(__DIR__.'/var/.php_cs.cache')
22 | ->setRules([
23 | 'align_multiline_comment' => true,
24 | 'array_indentation' => true,
25 | 'array_syntax' => ['syntax' => 'short'],
26 | 'blank_line_after_namespace' => true,
27 | 'blank_line_before_statement' => [
28 | 'statements' => [
29 | 'break',
30 | 'continue',
31 | 'declare',
32 | 'default',
33 | 'do',
34 | 'exit',
35 | 'for',
36 | 'foreach',
37 | 'goto',
38 | 'if',
39 | 'include',
40 | 'include_once',
41 | 'require',
42 | 'require_once',
43 | 'return',
44 | 'switch',
45 | 'throw',
46 | 'try',
47 | 'while',
48 | ],
49 | ],
50 | 'braces' => true,
51 | 'cast_spaces' => true,
52 | 'class_attributes_separation' => ['elements' => ['const'=>'one', 'method'=>'one', 'property'=>'one']],
53 | 'combine_consecutive_issets' => true,
54 | 'combine_consecutive_unsets' => true,
55 | 'compact_nullable_typehint' => true,
56 | 'concat_space' => ['spacing' => 'one'],
57 | 'constant_case' => true,
58 | 'declare_equal_normalize' => ['space' => 'none'],
59 | 'declare_strict_types' => true,
60 | 'dir_constant' => true,
61 | 'elseif' => true,
62 | 'encoding' => true,
63 | 'echo_tag_syntax' => true,
64 | 'explicit_indirect_variable' => true,
65 | 'explicit_string_variable' => true,
66 | 'full_opening_tag' => true,
67 | 'fully_qualified_strict_types' => true,
68 | 'function_typehint_space' => true,
69 | 'function_declaration' => true,
70 | 'global_namespace_import' => [
71 | 'import_classes' => false,
72 | 'import_constants' => false,
73 | 'import_functions' => false,
74 | ],
75 | 'heredoc_to_nowdoc' => true,
76 | 'increment_style' => [
77 | 'style' => PhpCsFixer\Fixer\Operator\IncrementStyleFixer::STYLE_POST,
78 | ],
79 | 'indentation_type' => true,
80 | 'is_null' => true,
81 | 'line_ending' => true,
82 | 'list_syntax' => ['syntax' => 'short'],
83 | 'logical_operators' => true,
84 | 'lowercase_keywords' => true,
85 | 'lowercase_static_reference' => true,
86 | 'magic_constant_casing' => true,
87 | 'magic_method_casing' => true,
88 | 'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
89 | 'modernize_types_casting' => false,
90 | 'multiline_comment_opening_closing' => true,
91 | 'multiline_whitespace_before_semicolons' => true,
92 | 'native_constant_invocation' => false,
93 | 'native_function_casing' => false,
94 | 'native_function_invocation' => ['include'=>['@all']],
95 | 'native_function_type_declaration_casing' => true,
96 | 'new_with_braces' => false,
97 | 'no_alias_functions' => true,
98 | 'no_alternative_syntax' => true,
99 | 'no_blank_lines_after_class_opening' => true,
100 | 'no_blank_lines_after_phpdoc' => true,
101 | 'no_blank_lines_before_namespace' => false,
102 | 'no_closing_tag' => true,
103 | 'no_empty_comment' => true,
104 | 'no_empty_phpdoc' => true,
105 | 'no_empty_statement' => true,
106 | 'no_extra_blank_lines' => true,
107 | 'no_homoglyph_names' => true,
108 | 'no_leading_import_slash' => true,
109 | 'no_leading_namespace_whitespace' => true,
110 | 'no_mixed_echo_print' => ['use' => 'print'],
111 | 'no_multiline_whitespace_around_double_arrow' => true,
112 | 'no_null_property_initialization' => true,
113 | 'no_php4_constructor' => true,
114 | 'no_short_bool_cast' => true,
115 | 'no_singleline_whitespace_before_semicolons' => true,
116 | 'no_spaces_after_function_name' => true,
117 | 'no_spaces_around_offset' => true,
118 | 'no_spaces_inside_parenthesis' => true,
119 | 'no_superfluous_elseif' => true,
120 | 'no_superfluous_phpdoc_tags' => false,
121 | 'no_trailing_comma_in_list_call' => true,
122 | 'no_trailing_comma_in_singleline_array' => true,
123 | 'no_trailing_whitespace' => true,
124 | 'no_trailing_whitespace_in_comment' => true,
125 | 'no_unneeded_control_parentheses' => true,
126 | 'no_unneeded_curly_braces' => true,
127 | 'no_unneeded_final_method' => true,
128 | 'no_unreachable_default_argument_value' => true,
129 | 'no_unset_on_property' => true,
130 | 'no_unused_imports' => true,
131 | 'no_useless_else' => true,
132 | 'no_useless_return' => true,
133 | 'no_whitespace_before_comma_in_array' => true,
134 | 'no_whitespace_in_blank_line' => true,
135 | 'non_printable_character' => true,
136 | 'normalize_index_brace' => true,
137 | 'object_operator_without_whitespace' => true,
138 | 'ordered_class_elements' => [
139 | 'order' => [
140 | 'use_trait',
141 | 'constant_public',
142 | 'constant_protected',
143 | 'constant_private',
144 | 'property_public_static',
145 | 'property_protected_static',
146 | 'property_private_static',
147 | 'property_public',
148 | 'property_protected',
149 | 'property_private',
150 | 'construct',
151 | 'method_public_static',
152 | 'destruct',
153 | 'magic',
154 | 'phpunit',
155 | 'method_public',
156 | 'method_protected',
157 | 'method_private',
158 | 'method_protected_static',
159 | 'method_private_static',
160 | ],
161 | ],
162 | 'ordered_imports' => [
163 | 'imports_order' => [
164 | PhpCsFixer\Fixer\Import\OrderedImportsFixer::IMPORT_TYPE_CONST,
165 | PhpCsFixer\Fixer\Import\OrderedImportsFixer::IMPORT_TYPE_FUNCTION,
166 | PhpCsFixer\Fixer\Import\OrderedImportsFixer::IMPORT_TYPE_CLASS,
167 | ]
168 | ],
169 | 'ordered_interfaces' => [
170 | 'direction' => 'ascend',
171 | 'order' => 'alpha',
172 | ],
173 | 'phpdoc_add_missing_param_annotation' => false,
174 | 'phpdoc_align' => ['align' => 'left'],
175 | 'phpdoc_annotation_without_dot' => true,
176 | 'phpdoc_indent' => true,
177 | 'phpdoc_no_access' => true,
178 | 'phpdoc_no_empty_return' => true,
179 | 'phpdoc_no_package' => true,
180 | 'phpdoc_order' => true,
181 | 'phpdoc_return_self_reference' => true,
182 | 'phpdoc_scalar' => true,
183 | 'phpdoc_separation' => true,
184 | 'phpdoc_single_line_var_spacing' => true,
185 | 'phpdoc_summary' => true,
186 | 'phpdoc_to_comment' => false,
187 | 'phpdoc_trim' => true,
188 | 'phpdoc_trim_consecutive_blank_line_separation' => true,
189 | 'phpdoc_types' => ['groups' => ['simple', 'meta']],
190 | 'phpdoc_types_order' => true,
191 | 'phpdoc_var_without_name' => true,
192 | 'pow_to_exponentiation' => true,
193 | 'protected_to_private' => true,
194 | 'return_assignment' => true,
195 | 'return_type_declaration' => ['space_before' => 'one'],
196 | 'self_accessor' => true,
197 | 'self_static_accessor' => true,
198 | 'semicolon_after_instruction' => true,
199 | 'set_type_to_cast' => true,
200 | 'short_scalar_cast' => true,
201 | 'simple_to_complex_string_variable' => true,
202 | 'simplified_null_return' => false,
203 | 'single_blank_line_at_eof' => true,
204 | 'single_import_per_statement' => true,
205 | 'single_line_after_imports' => true,
206 | 'single_quote' => true,
207 | 'standardize_not_equals' => true,
208 | 'strict_param' => true,
209 | 'ternary_to_null_coalescing' => true,
210 | 'trailing_comma_in_multiline' => true,
211 | 'trim_array_spaces' => true,
212 | 'unary_operator_spaces' => true,
213 | 'visibility_required' => [
214 | 'elements' => [
215 | 'const',
216 | 'method',
217 | 'property',
218 | ],
219 | ],
220 | 'void_return' => true,
221 | 'whitespace_after_comma_in_array' => true,
222 | ])
223 | ->setFinder($finder);
--------------------------------------------------------------------------------
/AppInsightsPHPBundle.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle;
15 |
16 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\DependencyInjection\Compiler\DoctrineDependencyPassPass;
17 | use Symfony\Component\DependencyInjection\ContainerBuilder;
18 | use Symfony\Component\HttpKernel\Bundle\Bundle;
19 |
20 | final class AppInsightsPHPBundle extends Bundle
21 | {
22 | public function build(ContainerBuilder $container) : void
23 | {
24 | $container->addCompilerPass(new DoctrineDependencyPassPass());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [0.3.1] - 2023-03-28
2 |
3 | ### Updated
4 | - [6d2e19](https://github.com/app-insights-php/app-insights-php-bundle/commit/6d2e19d2a70fcc262c990cdb361aecc2af7ba2ec) - **symfony dependencies** - [@norberttech](https://github.com/norberttech)
5 |
6 | ## [0.3.0] - 2023-03-28
7 |
8 | ### Updated
9 | - [bfea42](https://github.com/app-insights-php/app-insights-php-bundle/commit/bfea420bad6faa4ddda45fe0213471392798bc54) - **php version to php ~8.1||~8.2** - [@norberttech](https://github.com/norberttech)
10 |
11 | ## [0.2.9] - 2022-08-09
12 |
13 | ### Updated
14 | - [231d81](https://github.com/app-insights-php/app-insights-php-bundle/commit/231d810e8efc5ec05ffd2c4512dd9d20c5231564) - **dependencieS** - [@norberttech](https://github.com/norberttech)
15 |
16 | ## [0.2.8] - 2022-08-02
17 |
18 | ### Updated
19 | - [8e8d14](https://github.com/app-insights-php/app-insights-php-bundle/commit/8e8d14417d488f808aefd575ee2b34b5690ab8ea) - **client to the latest version** - [@norberttech](https://github.com/norberttech)
20 | - [1be250](https://github.com/app-insights-php/app-insights-php-bundle/commit/1be250cd511871379bb71763e9be6abca76088f8) - **dependencies** - [@norberttech](https://github.com/norberttech)
21 |
22 | ### Removed
23 | - [bd2655](https://github.com/app-insights-php/app-insights-php-bundle/commit/bd2655c9852a5d4ce599e4cb21171f06c3696dcf) - **var from git repo** - [@norberttech](https://github.com/norberttech)
24 |
25 | ## [0.2.7] - 2022-04-15
26 |
27 | ### Changed
28 | - [#112](https://github.com/app-insights-php/app-insights-php-bundle/pull/112) - **Updated project to php 8.1** - [@norberttech](https://github.com/norberttech)
29 |
30 | ## [0.2.6] - 2021-02-14
31 |
32 | ### Added
33 | - [#39](https://github.com/app-insights-php/app-insights-php-bundle/pull/39) - **Support for Twig ^3.0** - [@norberttech](https://github.com/norberttech)
34 |
35 | ### Changed
36 | - [#39](https://github.com/app-insights-php/app-insights-php-bundle/pull/39) - **Moved from XML to PHP bundle configuration** - [@norberttech](https://github.com/norberttech)
37 | - [de4c55](https://github.com/app-insights-php/app-insights-php-bundle/commit/de4c557604dbb52764cc4b8677b1efc5ece1e15c) - **dependencies** - [@norberttech](https://github.com/norberttech)
38 | - [779365](https://github.com/app-insights-php/app-insights-php-bundle/commit/779365cb122cbb45071d759c01b48bcc80e53a53) - **PHP 8 update, aeon-php/automation integration, updated dependencies** - [@norberttech](https://github.com/norberttech)
39 |
40 | ## [0.2.5] - 2020-06-25
41 |
42 | ### Changed
43 | - [#35](https://github.com/app-insights-php/app-insights-php-bundle/pull/35) - **Do not execute listeners when telemetry is disabled** - [@norberttech](https://github.com/norberttech)
44 |
45 | ## [0.2.4] - 2020-01-21
46 |
47 | ### Fixed
48 | - [#28](https://github.com/app-insights-php/app-insights-php-bundle/pull/28) - **replace classes that have been removed from Symfony 5** - [@smindel](https://github.com/smindel)
49 |
50 | ## [0.2.3] - 2020-01-16
51 |
52 | ### Changed
53 | - [#26](https://github.com/app-insights-php/app-insights-php-bundle/pull/26) - **Reverted change in folders structure, moved to github actions, added …** - [@norberttech](https://github.com/norberttech)
54 |
55 | ### Fixed
56 | - [#27](https://github.com/app-insights-php/app-insights-php-bundle/pull/27) - **cache action** - [@norberttech](https://github.com/norberttech)
57 |
58 | ## [0.2.2] - 2019-09-04
59 |
60 | ### Changed
61 | - [#22](https://github.com/app-insights-php/app-insights-php-bundle/pull/22) - **Update app-insights-client** - [@tomaszhanc](https://github.com/tomaszhanc)
62 | - [cbf410](https://github.com/app-insights-php/app-insights-php-bundle/commit/cbf410654881a013a1c3d006fb7fc2cc9fea1672) - **Update README.md** - [@norberttech](https://github.com/norberttech)
63 |
64 | ## [0.2.1] - 2019-07-25
65 |
66 | ### Changed
67 | - [#19](https://github.com/app-insights-php/app-insights-php-bundle/pull/19) - **Log more parameters for a request** - [@tomaszhanc](https://github.com/tomaszhanc)
68 |
69 | ## [0.2.0] - 2019-07-04
70 |
71 | ### Changed
72 | - [#18](https://github.com/app-insights-php/app-insights-php-bundle/pull/18) - **Remove failure cache from KernelTerminateListener** - [@tomaszhanc](https://github.com/tomaszhanc)
73 |
74 | ## [0.1.15] - 2019-06-28
75 |
76 | ### Changed
77 | - [#17](https://github.com/app-insights-php/app-insights-php-bundle/pull/17) - **Move checking instrumentation key directly into listeners** - [@norberttech](https://github.com/norberttech)
78 |
79 | ## [0.1.14] - 2019-06-28
80 |
81 | ### Changed
82 | - [#16](https://github.com/app-insights-php/app-insights-php-bundle/pull/16) - **Improve registration of symfony listeners** - [@norberttech](https://github.com/norberttech)
83 |
84 | ## [0.1.13] - 2019-06-27
85 |
86 | ### Added
87 | - [#15](https://github.com/app-insights-php/app-insights-php-bundle/pull/15) - **possibility to cache failed app insights flushes** - [@norberttech](https://github.com/norberttech)
88 |
89 | ### Changed
90 | - [339d08](https://github.com/app-insights-php/app-insights-php-bundle/commit/339d089a95b4eb2d1a5b7ca11f5378b1a0172287) - **Update index.md** - [@norberttech](https://github.com/norberttech)
91 |
92 | ## [0.1.12] - 2019-06-26
93 |
94 | ### Added
95 | - [#14](https://github.com/app-insights-php/app-insights-php-bundle/pull/14) - **telemetry client channel content to fallback logger** - [@norberttech](https://github.com/norberttech)
96 |
97 | ## [0.1.11] - 2019-06-21
98 |
99 | ### Added
100 | - [#13](https://github.com/app-insights-php/app-insights-php-bundle/pull/13) - **fallback logger to KernelTerminateListener** - [@norberttech](https://github.com/norberttech)
101 |
102 | ## [0.1.10] - 2019-04-27
103 |
104 | ### Changed
105 | - [#10](https://github.com/app-insights-php/app-insights-php-bundle/pull/10) - **Feature/track exception cli** - [@norberttech](https://github.com/norberttech)
106 |
107 | ## [0.1.9] - 2019-04-18
108 |
109 | ### Added
110 | - [#9](https://github.com/app-insights-php/app-insights-php-bundle/pull/9) - **CLI Telemetry client commands** - [@norberttech](https://github.com/norberttech)
111 |
112 | ## [0.1.8] - 2019-04-15
113 |
114 | ### Changed
115 | - [#8](https://github.com/app-insights-php/app-insights-php-bundle/pull/8) - **Do not track users through JS client when app insights configuration …** - [@norberttech](https://github.com/norberttech)
116 |
117 | ## [0.1.7] - 2019-04-06
118 |
119 | ### Changed
120 | - [#7](https://github.com/app-insights-php/app-insights-php-bundle/pull/7) - **Don't mark 3XX status code as not successful** - [@javiermadueno](https://github.com/javiermadueno)
121 | - [a9bc7d](https://github.com/app-insights-php/app-insights-php-bundle/commit/a9bc7dc91c45c829e7877bf4ef2421fa0f68205d) - **Update README.md** - [@norberttech](https://github.com/norberttech)
122 |
123 | ## [0.1.6] - 2019-03-03
124 |
125 | ### Added
126 | - [#5](https://github.com/app-insights-php/app-insights-php-bundle/pull/5) - **support for app insights monolog dependency handler** - [@norberttech](https://github.com/norberttech)
127 |
128 | ## [0.1.5] - 2019-03-03
129 |
130 | ### Added
131 | - [7c3f68](https://github.com/app-insights-php/app-insights-php-bundle/commit/7c3f68040df8407639319a57f4c701915a915a3e) - **adding file headers to cs fixer rule** - [@norberttech](https://github.com/norberttech)
132 |
133 | ### Fixed
134 | - [a5663e](https://github.com/app-insights-php/app-insights-php-bundle/commit/a5663e82aeaf5f5ae6c9e07d93063b03182c6831) - **failing tests** - [@norberttech](https://github.com/norberttech)
135 | - [aedb90](https://github.com/app-insights-php/app-insights-php-bundle/commit/aedb9008eca154dfb38f02ee0f1eb9572cd4dcc1) - **setting operation id in page view** - [@norberttech](https://github.com/norberttech)
136 |
137 | ## [0.1.4] - 2019-03-03
138 |
139 | ### Added
140 | - [c0df76](https://github.com/app-insights-php/app-insights-php-bundle/commit/c0df7623459828b30d57666b7a8ee69b53c86355) - **missing is_safe option to TelemetryTwig Extension** - [@norberttech](https://github.com/norberttech)
141 |
142 | ## [0.1.3] - 2019-03-03
143 |
144 | ### Added
145 | - [#3](https://github.com/app-insights-php/app-insights-php-bundle/pull/3) - **query parameters as a properties to request logger** - [@norberttech](https://github.com/norberttech)
146 |
147 | ### Changed
148 | - [#4](https://github.com/app-insights-php/app-insights-php-bundle/pull/4) - **Twig helper for PageView tracking integration & docs update** - [@norberttech](https://github.com/norberttech)
149 |
150 | ## [0.1.2] - 2019-02-27
151 |
152 | ### Changed
153 | - [#2](https://github.com/app-insights-php/app-insights-php-bundle/pull/2) - **dependencies** - [@norberttech](https://github.com/norberttech)
154 |
155 | ## [0.1.1] - 2019-02-22
156 |
157 | ### Added
158 | - [#1](https://github.com/app-insights-php/app-insights-php-bundle/pull/1) - **possibility to register many monolog handlers** - [@norberttech](https://github.com/norberttech)
159 | - [91a81b](https://github.com/app-insights-php/app-insights-php-bundle/commit/91a81b971c59b9d70eccdbd66e076643f2913508) - **master branch alias in composer.json** - [@norberttech](https://github.com/norberttech)
160 |
161 | ## [0.1.0] - 2019-02-21
162 |
163 | ### Changed
164 | - [79ae97](https://github.com/app-insights-php/app-insights-php-bundle/commit/79ae975fb9ecc36b3fe3118be7e04604f56e13cf) - **readme** - [@norberttech](https://github.com/norberttech)
165 | - [2d15f0](https://github.com/app-insights-php/app-insights-php-bundle/commit/2d15f05d13fcad55f21dc1adcd7e505671c91c1d) - **Simplified travis testsuite** - [@norberttech](https://github.com/norberttech)
166 | - [8018f1](https://github.com/app-insights-php/app-insights-php-bundle/commit/8018f1498180ab21765cf3357608dec852827f34) - **Update README.md** - [@norberttech](https://github.com/norberttech)
167 | - [41426a](https://github.com/app-insights-php/app-insights-php-bundle/commit/41426a847bc628eadd27ad25f07fff7f27965ead) - **Update README.md** - [@norberttech](https://github.com/norberttech)
168 | - [6a4c59](https://github.com/app-insights-php/app-insights-php-bundle/commit/6a4c591c20e462283adb48f9e688eb6516efec11) - **dependencies to stable versions** - [@norberttech](https://github.com/norberttech)
169 | - [6874e5](https://github.com/app-insights-php/app-insights-php-bundle/commit/6874e5a4597077c44319ec961cafe365e5b96ef2) - **cs-fixer dependency** - [@norberttech](https://github.com/norberttech)
170 | - [965ff9](https://github.com/app-insights-php/app-insights-php-bundle/commit/965ff9cf4678312b9c73044e5701e61ace6a1f27) - **Initial commit** - [@norberttech](https://github.com/norberttech)
171 | - [15f8f9](https://github.com/app-insights-php/app-insights-php-bundle/commit/15f8f938647381efae8c7d6e77afa214819754e0) - **Initial commit** - [@norberttech](https://github.com/norberttech)
172 |
173 | ### Fixed
174 | - [1f4466](https://github.com/app-insights-php/app-insights-php-bundle/commit/1f44661f3d236c1d68917ded0a1c177da145cc56) - **lowest-dependencies test by forcing guzzle version 6 and higher** - [@norberttech](https://github.com/norberttech)
175 | - [3de06b](https://github.com/app-insights-php/app-insights-php-bundle/commit/3de06bae02f0317915d35f9c5f6574adf1f85f19) - **composer php cs script** - [@norberttech](https://github.com/norberttech)
176 | - [b07a04](https://github.com/app-insights-php/app-insights-php-bundle/commit/b07a0443233983515ad9427dd9ea55a545f890d9) - **tests** - [@norberttech](https://github.com/norberttech)
177 | - [a56f58](https://github.com/app-insights-php/app-insights-php-bundle/commit/a56f58b8779452e999dcca586065cdc31ba2aaad) - **invalid dependencies** - [@norberttech](https://github.com/norberttech)
178 |
179 | Generated by [Automation](https://github.com/aeon-php/automation)
--------------------------------------------------------------------------------
/Cache/NullCache.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Cache;
15 |
16 | use Psr\SimpleCache\CacheInterface;
17 |
18 | final class NullCache implements CacheInterface
19 | {
20 | public function get($key, $default = null) : void
21 | {
22 | }
23 |
24 | public function set($key, $value, $ttl = null) : void
25 | {
26 | }
27 |
28 | public function delete($key) : void
29 | {
30 | }
31 |
32 | public function clear() : void
33 | {
34 | }
35 |
36 | public function getMultiple($keys, $default = null) : void
37 | {
38 | }
39 |
40 | public function setMultiple($values, $ttl = null) : void
41 | {
42 | }
43 |
44 | public function deleteMultiple($keys) : void
45 | {
46 | }
47 |
48 | public function has($key)
49 | {
50 | return false;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Command/TrackDependencyCommand.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use Symfony\Component\Console\Command\Command;
18 | use Symfony\Component\Console\Input\InputArgument;
19 | use Symfony\Component\Console\Input\InputInterface;
20 | use Symfony\Component\Console\Input\InputOption;
21 | use Symfony\Component\Console\Output\OutputInterface;
22 | use Symfony\Component\Console\Style\SymfonyStyle;
23 |
24 | final class TrackDependencyCommand extends Command
25 | {
26 | public const NAME = 'app-insights:track:dependency';
27 |
28 | protected static $defaultName = self::NAME;
29 |
30 | private $client;
31 |
32 | public function __construct(Client $client)
33 | {
34 | parent::__construct();
35 | $this->client = $client;
36 | }
37 |
38 | protected function configure() : void
39 | {
40 | $this
41 | ->setDescription('[App Insights] Track Dependency.')
42 | ->addArgument('name', InputArgument::REQUIRED, 'Dependency name')
43 | ->addOption('type', null, InputOption::VALUE_OPTIONAL, 'Dependency type', '')
44 | ->addOption('commandName', null, InputOption::VALUE_OPTIONAL, 'Dependency command name', '')
45 | ->addOption('startTime', null, InputOption::VALUE_OPTIONAL, 'Start time (timestamp) when call to dependency was initialized', \time())
46 | ->addOption('durationTime', null, InputOption::VALUE_OPTIONAL, 'Dependency call duration time in milliseconds', 0)
47 | ->addOption('isSuccessful', null, InputOption::VALUE_OPTIONAL, 'Was the dependency call successful', true)
48 | ->addOption('resultCode', null, InputOption::VALUE_OPTIONAL, 'Dependency result code')
49 | ->addOption('properties', null, InputOption::VALUE_OPTIONAL, 'Dependency additional properties passed as json object')
50 | ->addOption('dont-flush', null, InputOption::VALUE_OPTIONAL, 'Don\'t flush client directly in the command, wait for the KernelTerminateListener', false);
51 | }
52 |
53 | protected function execute(InputInterface $input, OutputInterface $output) : int
54 | {
55 | $io = new SymfonyStyle($input, $output);
56 |
57 | $this->client->trackDependency(
58 | $input->getArgument('name'),
59 | $input->getOption('type'),
60 | $input->getOption('commandName'),
61 | (int) $input->getOption('startTime'),
62 | (int) $input->getOption('durationTime'),
63 | (bool) $input->getOption('isSuccessful'),
64 | $input->getOption('resultCode'),
65 | $input->getOption('properties') ? \json_decode($input->getOption('properties'), true) : null
66 | );
67 |
68 | $dontFlush = false !== $input->getOption('dont-flush');
69 |
70 | if ($dontFlush) {
71 | $io->success('Telemetry sent.');
72 |
73 | return 0;
74 | }
75 |
76 | $response = $this->client->flush();
77 |
78 | if (null === $response) {
79 | $io->warning('Telemetry was not sent.');
80 | $io->note('Configuration is disabled or there was an error. Please check fallback logs.');
81 |
82 | return 0;
83 | }
84 |
85 | if (200 === $response->getStatusCode()) {
86 | $io->success('Telemetry successfully sent.');
87 | $io->note((string) $response->getBody());
88 | } else {
89 | $io->success('Something went wrong.');
90 | $io->note('Status Code: ' . $response->getStatusCode());
91 | $io->note((string) $response->getBody());
92 | }
93 |
94 | return 0;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/Command/TrackEventCommand.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use Symfony\Component\Console\Command\Command;
18 | use Symfony\Component\Console\Input\InputArgument;
19 | use Symfony\Component\Console\Input\InputInterface;
20 | use Symfony\Component\Console\Input\InputOption;
21 | use Symfony\Component\Console\Output\OutputInterface;
22 | use Symfony\Component\Console\Style\SymfonyStyle;
23 |
24 | final class TrackEventCommand extends Command
25 | {
26 | public const NAME = 'app-insights:track:event';
27 |
28 | protected static $defaultName = self::NAME;
29 |
30 | private $client;
31 |
32 | public function __construct(Client $client)
33 | {
34 | parent::__construct();
35 | $this->client = $client;
36 | }
37 |
38 | protected function configure() : void
39 | {
40 | $this
41 | ->setDescription('[App Insights] Track Event.')
42 | ->addArgument('name', InputArgument::REQUIRED, 'Event name')
43 | ->addOption('properties', null, InputOption::VALUE_OPTIONAL, 'Event additional properties passed as json object')
44 | ->addOption('measurements', null, InputOption::VALUE_OPTIONAL, 'Event additional measurements passed as json object')
45 | ->addOption('dont-flush', null, InputOption::VALUE_OPTIONAL, 'Don\'t flush client directly in the command, wait for the KernelTerminateListener', false);
46 | }
47 |
48 | protected function execute(InputInterface $input, OutputInterface $output) : int
49 | {
50 | $io = new SymfonyStyle($input, $output);
51 |
52 | $this->client->trackEvent(
53 | $input->getArgument('name'),
54 | $input->getOption('properties') ? \json_decode($input->getOption('properties'), true) : null,
55 | $input->getOption('measurements') ? \json_decode($input->getOption('measurements'), true) : null
56 | );
57 |
58 | $dontFlush = false !== $input->getOption('dont-flush');
59 |
60 | if ($dontFlush) {
61 | $io->success('Telemetry sent.');
62 |
63 | return 0;
64 | }
65 |
66 | $response = $this->client->flush();
67 |
68 | if (null === $response) {
69 | $io->warning('Telemetry was not sent.');
70 | $io->note('Configuration is disabled or there was an error. Please check fallback logs.');
71 |
72 | return 0;
73 | }
74 |
75 | if (200 === $response->getStatusCode()) {
76 | $io->success('Telemetry successfully sent.');
77 | $io->note((string) $response->getBody());
78 | } else {
79 | $io->success('Something went wrong.');
80 | $io->note('Status Code: ' . $response->getStatusCode());
81 | $io->note((string) $response->getBody());
82 | }
83 |
84 | return 0;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Command/TrackExceptionCommand.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use Symfony\Component\Console\Command\Command;
18 | use Symfony\Component\Console\Input\InputArgument;
19 | use Symfony\Component\Console\Input\InputInterface;
20 | use Symfony\Component\Console\Input\InputOption;
21 | use Symfony\Component\Console\Output\OutputInterface;
22 | use Symfony\Component\Console\Style\SymfonyStyle;
23 |
24 | final class TrackExceptionCommand extends Command
25 | {
26 | public const NAME = 'app-insights:track:exception';
27 |
28 | protected static $defaultName = self::NAME;
29 |
30 | private $client;
31 |
32 | public function __construct(Client $client)
33 | {
34 | parent::__construct();
35 | $this->client = $client;
36 | }
37 |
38 | protected function configure() : void
39 | {
40 | $this
41 | ->setDescription('[App Insights] Track Exception.')
42 | ->addArgument('class', InputArgument::OPTIONAL, 'Exception class', '\\Exception')
43 | ->addArgument('message', InputArgument::OPTIONAL, 'Exception message', '')
44 | ->addOption('properties', null, InputOption::VALUE_OPTIONAL, 'Exception additional properties passed as json object')
45 | ->addOption('measurements', null, InputOption::VALUE_OPTIONAL, 'Exception additional measurements passed as json object')
46 | ->addOption('dont-flush', null, InputOption::VALUE_OPTIONAL, 'Don\'t flush client directly in the command, wait for the KernelTerminateListener', false);
47 | }
48 |
49 | protected function initialize(InputInterface $input, OutputInterface $output) : void
50 | {
51 | if (!\class_exists($input->getArgument('class'))) {
52 | throw new \InvalidArgumentException('Argument class must be a valid class');
53 | }
54 | }
55 |
56 | protected function execute(InputInterface $input, OutputInterface $output) : int
57 | {
58 | $io = new SymfonyStyle($input, $output);
59 |
60 | $class = $input->getArgument('class');
61 |
62 | $this->client->trackException(
63 | new $class($input->getArgument('message')),
64 | $input->getOption('properties') ? \json_decode($input->getOption('properties'), true) : null,
65 | $input->getOption('measurements') ? \json_decode($input->getOption('measurements'), true) : null
66 | );
67 |
68 | $dontFlush = false !== $input->getOption('dont-flush');
69 |
70 | if ($dontFlush) {
71 | $io->success('Telemetry sent.');
72 |
73 | return 0;
74 | }
75 |
76 | $response = $this->client->flush();
77 |
78 | if (null === $response) {
79 | $io->warning('Telemetry was not sent.');
80 | $io->note('Configuration is disabled or there was an error. Please check fallback logs.');
81 |
82 | return 0;
83 | }
84 |
85 | if (200 === $response->getStatusCode()) {
86 | $io->success('Telemetry successfully sent.');
87 | $io->note((string) $response->getBody());
88 | } else {
89 | $io->success('Something went wrong.');
90 | $io->note('Status Code: ' . $response->getStatusCode());
91 | $io->note((string) $response->getBody());
92 | }
93 |
94 | return 0;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/Command/TrackMetricCommand.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use ApplicationInsights\Channel\Contracts\Data_Point_Type;
18 | use Symfony\Component\Console\Command\Command;
19 | use Symfony\Component\Console\Input\InputArgument;
20 | use Symfony\Component\Console\Input\InputInterface;
21 | use Symfony\Component\Console\Input\InputOption;
22 | use Symfony\Component\Console\Output\OutputInterface;
23 | use Symfony\Component\Console\Style\SymfonyStyle;
24 |
25 | final class TrackMetricCommand extends Command
26 | {
27 | public const NAME = 'app-insights:track:metric';
28 |
29 | protected static $defaultName = self::NAME;
30 |
31 | private $client;
32 |
33 | public function __construct(Client $client)
34 | {
35 | parent::__construct();
36 | $this->client = $client;
37 | }
38 |
39 | protected function configure() : void
40 | {
41 | $this
42 | ->setDescription('[App Insights] Track Metric.')
43 | ->addArgument('name', InputArgument::REQUIRED, 'Metric name')
44 | ->addArgument('value', InputArgument::REQUIRED, 'Metric value')
45 | ->addOption('type', null, InputOption::VALUE_OPTIONAL, 'Metric type, 0 = Measurement, 1 = Aggregation', Data_Point_Type::Measurement)
46 | ->addOption('count', null, InputOption::VALUE_OPTIONAL, 'Metric count')
47 | ->addOption('min', null, InputOption::VALUE_OPTIONAL, 'Metric max')
48 | ->addOption('max', null, InputOption::VALUE_OPTIONAL, 'Metric max')
49 | ->addOption('standardDeviation', null, InputOption::VALUE_OPTIONAL, 'Standard deviation')
50 | ->addOption('measurements', null, InputOption::VALUE_OPTIONAL, 'Metric additional measurements passed as json object')
51 | ->addOption('dont-flush', null, InputOption::VALUE_OPTIONAL, 'Don\'t flush client directly in the command, wait for the KernelTerminateListener', false);
52 | }
53 |
54 | protected function initialize(InputInterface $input, OutputInterface $output) : void
55 | {
56 | if (!\is_numeric($input->getArgument('value'))) {
57 | throw new \InvalidArgumentException('Argument value must be a valid number');
58 | }
59 |
60 | if ($input->getOption('type') && !\in_array($input->getOption('type'), [Data_Point_Type::Measurement, Data_Point_Type::Aggregation], true)) {
61 | throw new \InvalidArgumentException('Invalid measurement type');
62 | }
63 | }
64 |
65 | protected function execute(InputInterface $input, OutputInterface $output) : int
66 | {
67 | $io = new SymfonyStyle($input, $output);
68 |
69 | $this->client->trackMetric(
70 | $input->getArgument('name'),
71 | (float) $input->getArgument('value'),
72 | $input->getOption('type'),
73 | $input->getOption('count') ? (int) $input->getOption('count') : null,
74 | $input->getOption('min') ? (int) $input->getOption('min') : null,
75 | $input->getOption('max') ? (int) $input->getOption('max') : null,
76 | $input->getOption('standardDeviation') ? (float) $input->getOption('standardDeviation') : null,
77 | $input->getOption('measurements') ? \json_decode($input->getOption('measurements'), true) : null
78 | );
79 |
80 | $dontFlush = false !== $input->getOption('dont-flush');
81 |
82 | if ($dontFlush) {
83 | $io->success('Telemetry sent.');
84 |
85 | return 0;
86 | }
87 |
88 | $response = $this->client->flush();
89 |
90 | if (null === $response) {
91 | $io->warning('Telemetry was not sent.');
92 | $io->note('Configuration is disabled or there was an error. Please check fallback logs.');
93 |
94 | return 0;
95 | }
96 |
97 | if (200 === $response->getStatusCode()) {
98 | $io->success('Telemetry successfully sent.');
99 | $io->note((string) $response->getBody());
100 | } else {
101 | $io->success('Something went wrong.');
102 | $io->note('Status Code: ' . $response->getStatusCode());
103 | $io->note((string) $response->getBody());
104 | }
105 |
106 | return 0;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/DependencyInjection/AppInsightsPHPExtension.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\DependencyInjection;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use AppInsightsPHP\Client\Configuration;
18 | use AppInsightsPHP\Client\Configuration\Dependenies;
19 | use AppInsightsPHP\Client\Configuration\Exceptions;
20 | use AppInsightsPHP\Client\Configuration\Requests;
21 | use AppInsightsPHP\Client\Configuration\Traces;
22 | use AppInsightsPHP\Monolog\Handler\AppInsightsDependencyHandler;
23 | use AppInsightsPHP\Monolog\Handler\AppInsightsTraceHandler;
24 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Cache\NullCache;
25 | use Psr\Log\NullLogger;
26 | use Symfony\Component\Config\FileLocator;
27 | use Symfony\Component\DependencyInjection\ContainerBuilder;
28 | use Symfony\Component\DependencyInjection\Definition;
29 | use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
30 | use Symfony\Component\DependencyInjection\Reference;
31 | use Symfony\Component\HttpKernel\DependencyInjection\Extension;
32 |
33 | final class AppInsightsPHPExtension extends Extension
34 | {
35 | public function load(array $configs, ContainerBuilder $container) : void
36 | {
37 | $config = $this->processConfiguration($this->getConfiguration($configs, $container), $configs);
38 |
39 | $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
40 | $loader->load('app_insights_php.php');
41 | $loader->load('app_insights_php_console.php');
42 |
43 | $container->setParameter('app_insights_php.instrumentation_key', $config['instrumentation_key']);
44 | $container->setParameter('app_insights_php.doctrine.track_dependency', $config['doctrine']['track_dependency']);
45 |
46 | // Make autowiring possible
47 | $container->setAlias(Client::class, 'app_insights_php.telemetry')->setPublic(true);
48 |
49 | $container->setDefinition(
50 | 'app_insights_php.configuration.exceptions',
51 | new Definition(Exceptions::class, [
52 | $config['exceptions']['enabled'],
53 | (array) $config['exceptions']['ignored_exceptions'],
54 | ])
55 | );
56 | $container->setDefinition(
57 | 'app_insights_php.configuration.dependencies',
58 | new Definition(Dependenies::class, [
59 | $config['dependencies']['enabled'],
60 | ])
61 | );
62 | $container->setDefinition(
63 | 'app_insights_php.configuration.requests',
64 | new Definition(Requests::class, [
65 | $config['requests']['enabled'],
66 | ])
67 | );
68 | $container->setDefinition(
69 | 'app_insights_php.configuration.traces',
70 | new Definition(Traces::class, [
71 | $config['traces']['enabled'],
72 | ])
73 | );
74 | $container->setDefinition(
75 | 'app_insights_php.configuration',
76 | new Definition(Configuration::class, [
77 | $config['enabled'],
78 | $config['gzip_enabled'],
79 | new Reference('app_insights_php.configuration.exceptions'),
80 | new Reference('app_insights_php.configuration.dependencies'),
81 | new Reference('app_insights_php.configuration.requests'),
82 | new Reference('app_insights_php.configuration.traces'),
83 | ])
84 | );
85 |
86 | $container
87 | ->getDefinition('app_insights_php.telemetry.factory')
88 | ->replaceArgument(1, new Reference('app_insights_php.configuration'));
89 |
90 | if ((bool) $config['failure_cache_service_id']) {
91 | $container->getDefinition('app_insights_php.telemetry.factory')
92 | ->replaceArgument(2, new Reference($config['failure_cache_service_id']));
93 | } else {
94 | $container->setDefinition('app_insights_php.failure_cache.null', new Definition(NullCache::class));
95 | $container->getDefinition('app_insights_php.telemetry.factory')
96 | ->replaceArgument(2, new Reference('app_insights_php.failure_cache.null'));
97 | }
98 |
99 | if ((bool) $config['fallback_logger']) {
100 | $container->getDefinition('app_insights_php.telemetry.factory')
101 | ->replaceArgument(3, new Reference($config['fallback_logger']['service_id']));
102 |
103 | if (isset($config['fallback_logger']['monolog_channel'])) {
104 | $container->getDefinition('app_insights_php.telemetry.factory')
105 | ->addTag('monolog.logger', ['channel' => $config['fallback_logger']['monolog_channel']]);
106 | }
107 | } else {
108 | $container->setDefinition('app_insights_php.logger.null', new Definition(NullLogger::class));
109 | $container->getDefinition('app_insights_php.telemetry.factory')
110 | ->replaceArgument(3, new Reference('app_insights_php.logger.null'));
111 | }
112 |
113 | // Symfony
114 | if ($config['enabled']) {
115 | $loader->load('app_insights_php_symfony.php');
116 | }
117 |
118 | // Twig
119 | if (\class_exists('Twig_Environment') || \class_exists('Twig\\Environment')) {
120 | $loader->load('app_insights_php_twig.php');
121 | }
122 |
123 | // Doctrine
124 | if ($config['doctrine']['track_dependency']) {
125 | if (!\class_exists('AppInsightsPHP\\Doctrine\\DBAL\\Logging\\DependencyLogger')) {
126 | throw new \RuntimeException('Please first run `composer require download app-insights-php/doctrine-dependency-logger` if you want to log DBAL queries.');
127 | }
128 |
129 | $loader->load('app_insights_php_doctrine.php');
130 | }
131 |
132 | // Monolog
133 | if (\count($config['monolog']['handlers'])) {
134 | foreach ($config['monolog']['handlers'] as $name => $handlerConfig) {
135 | $id = \sprintf(\sprintf('app_insights_php.monolog.handler.%s', $name));
136 |
137 | switch ($handlerConfig['type']) {
138 | case 'trace':
139 | $class = AppInsightsTraceHandler::class;
140 | $arguments = [
141 | new Reference('app_insights_php.telemetry'),
142 | $this->levelToMonologConst($handlerConfig['level']),
143 | (bool) $handlerConfig['bubble'],
144 | ];
145 |
146 | break;
147 | case 'dependency':
148 | $class = AppInsightsDependencyHandler::class;
149 | $arguments = [
150 | new Reference('app_insights_php.telemetry'),
151 | ];
152 |
153 | break;
154 |
155 | default:
156 | throw new \RuntimeException('Unrecognized monolog handler type %s', $handlerConfig['type']);
157 | }
158 |
159 | $container->register($id, $class)
160 | ->setArguments($arguments)
161 | ->setPublic(false);
162 | }
163 | }
164 | }
165 |
166 | private function levelToMonologConst($level)
167 | {
168 | return \is_int($level) ? $level : \constant('Monolog\Logger::' . \strtoupper($level));
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/DependencyInjection/Compiler/DoctrineDependencyPassPass.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\DependencyInjection\Compiler;
15 |
16 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
17 | use Symfony\Component\DependencyInjection\ContainerBuilder;
18 | use Symfony\Component\DependencyInjection\Reference;
19 |
20 | final class DoctrineDependencyPassPass implements CompilerPassInterface
21 | {
22 | public function process(ContainerBuilder $container) : void
23 | {
24 | if (false === $container->getParameter('app_insights_php.doctrine.track_dependency')) {
25 | return;
26 | }
27 |
28 | $doctrine = $container->getParameter('doctrine.connections');
29 |
30 | foreach ($doctrine as $connectionId) {
31 | $container
32 | ->getDefinition(\sprintf('%s.configuration', $connectionId))
33 | ->addMethodCall('setSQLLogger', [new Reference('app_insights_php.doctrine.logger.dependency')]);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/DependencyInjection/Configuration.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\DependencyInjection;
15 |
16 | use Monolog\Logger;
17 | use Symfony\Component\Config\Definition\Builder\TreeBuilder;
18 | use Symfony\Component\Config\Definition\ConfigurationInterface;
19 |
20 | final class Configuration implements ConfigurationInterface
21 | {
22 | public function getConfigTreeBuilder()
23 | {
24 | $treeBuilder = new TreeBuilder('app_insights_php');
25 | $rootNode = \method_exists(TreeBuilder::class, 'getRootNode') ? $treeBuilder->getRootNode() : $treeBuilder->root('app_insights_php');
26 |
27 | $allowedLoggerTypes = ['trace', 'dependency'];
28 |
29 | $rootNode
30 | ->children()
31 | ->booleanNode('enabled')->defaultTrue()->end()
32 | ->booleanNode('gzip_enabled')->defaultFalse()->end()
33 | ->scalarNode('instrumentation_key')->isRequired()->end()
34 | ->arrayNode('fallback_logger')
35 | ->addDefaultsIfNotSet()
36 | ->children()
37 | ->scalarNode('service_id')->end()
38 | ->scalarNode('monolog_channel')->end()
39 | ->end()
40 | ->end()
41 | ->scalarNode('failure_cache_service_id')->defaultNull()->end()
42 | ->arrayNode('exceptions')
43 | ->addDefaultsIfNotSet()
44 | ->children()
45 | ->booleanNode('enabled')->defaultTrue()->end()
46 | ->arrayNode('ignored_exceptions')
47 | ->scalarPrototype()->end()
48 | ->end()
49 | ->end()
50 | ->end()
51 | ->arrayNode('dependencies')
52 | ->addDefaultsIfNotSet()
53 | ->children()
54 | ->booleanNode('enabled')->defaultTrue()->end()
55 | ->end()
56 | ->end()
57 | ->arrayNode('traces')
58 | ->addDefaultsIfNotSet()
59 | ->children()
60 | ->booleanNode('enabled')->defaultTrue()->end()
61 | ->end()
62 | ->end()
63 | ->arrayNode('requests')
64 | ->addDefaultsIfNotSet()
65 | ->children()
66 | ->booleanNode('enabled')->defaultTrue()->end()
67 | ->end()
68 | ->end()
69 | ->arrayNode('doctrine')
70 | ->addDefaultsIfNotSet()
71 | ->children()
72 | ->booleanNode('track_dependency')->defaultFalse()->end()
73 | ->end()
74 | ->end()
75 | ->arrayNode('monolog')
76 | ->addDefaultsIfNotSet()
77 | ->children()
78 | ->arrayNode('handlers')
79 | ->canBeUnset()
80 | ->useAttributeAsKey('name')
81 | ->arrayPrototype()
82 | ->children()
83 | ->scalarNode('name')->end()
84 | ->scalarNode('level')->defaultValue(Logger::DEBUG)->end()
85 | ->scalarNode('bubble')->defaultTrue()->end()
86 | ->scalarNode('type')
87 | ->defaultValue('trace')
88 | ->validate()
89 | ->ifNotInArray($allowedLoggerTypes)
90 | ->thenInvalid(\sprintf('Allowed types: [%s]', \implode(', ', $allowedLoggerTypes)))
91 | ->end()
92 | ->end()
93 | ->end()
94 | ->end()
95 | ->end()
96 | ->end()
97 | ->end();
98 |
99 | return $treeBuilder;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/FlatArray.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle;
15 |
16 | final class FlatArray
17 | {
18 | private $array;
19 |
20 | public function __construct(array $array)
21 | {
22 | $this->array = $array;
23 | }
24 |
25 | public function __invoke() : array
26 | {
27 | return $this->flatterArray($this->array);
28 | }
29 |
30 | private function flatterArray(array $array, string $prefix = '') : array
31 | {
32 | $result = [];
33 |
34 | foreach ($array as $key => $value) {
35 | if (\is_array($value) && \count($value) > 1) {
36 | $result += $this->flatterArray($value, $prefix . $key . '.');
37 | } else {
38 | $result[$prefix . $key] = \is_array($value) ? \current($value) : $value;
39 | }
40 | }
41 |
42 | return $result;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 App Insights PHP
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.
22 |
--------------------------------------------------------------------------------
/Listener/ExceptionListener.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Listener;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18 | use Symfony\Component\HttpKernel\Event\ExceptionEvent;
19 | use Symfony\Component\HttpKernel\KernelEvents;
20 |
21 | final class ExceptionListener implements EventSubscriberInterface
22 | {
23 | private $telemetryClient;
24 |
25 | private $exceptionLogged;
26 |
27 | public function __construct(Client $telemetryClient)
28 | {
29 | $this->telemetryClient = $telemetryClient;
30 | $this->exceptionLogged = false;
31 | }
32 |
33 | public static function getSubscribedEvents()
34 | {
35 | return [
36 | KernelEvents::EXCEPTION => ['onException', 1000],
37 | ];
38 | }
39 |
40 | public function onException(ExceptionEvent $event) : void
41 | {
42 | if (!$this->telemetryClient->getContext()->getInstrumentationKey()) {
43 | // instrumentation key is emtpy
44 | return;
45 | }
46 |
47 | if (!$this->telemetryClient->configuration()->exceptions()->isEnabled()) {
48 | return;
49 | }
50 |
51 | if ($this->exceptionLogged) {
52 | return;
53 | }
54 |
55 | $this->telemetryClient->trackException($event->getThrowable());
56 | $this->exceptionLogged = true;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Listener/HttpRequestListener.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Listener;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\FlatArray;
18 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19 | use Symfony\Component\HttpKernel\Event\KernelEvent;
20 | use Symfony\Component\HttpKernel\Event\RequestEvent;
21 | use Symfony\Component\HttpKernel\Event\ResponseEvent;
22 | use Symfony\Component\HttpKernel\KernelEvents;
23 |
24 | final class HttpRequestListener implements EventSubscriberInterface
25 | {
26 | private $telemetryClient;
27 |
28 | private $request;
29 |
30 | private $requestStartTime;
31 |
32 | private $requestStartTimeMs;
33 |
34 | public function __construct(Client $telemetryClient)
35 | {
36 | $this->telemetryClient = $telemetryClient;
37 | }
38 |
39 | public static function getSubscribedEvents()
40 | {
41 | return [
42 | KernelEvents::REQUEST => ['onKernelRequest', 1000],
43 | KernelEvents::RESPONSE => ['onKernelResponse', -1000],
44 | ];
45 | }
46 |
47 | public function onKernelRequest(RequestEvent $event) : void
48 | {
49 | if (!$this->isMainRequest($event)) {
50 | return;
51 | }
52 |
53 | if (!$this->telemetryClient->configuration()->requests()->isEnabled()) {
54 | return;
55 | }
56 |
57 | if (!$this->telemetryClient->getContext()->getInstrumentationKey()) {
58 | // instrumentation key is emtpy
59 | return;
60 | }
61 |
62 | $this->requestStartTime = \time();
63 | $this->requestStartTimeMs = (int) \round(\microtime(true) * 1000, 1);
64 |
65 | $request = $event->getRequest();
66 |
67 | $this->telemetryClient->getContext()->getLocationContext()->setIp($request->getClientIp());
68 |
69 | if ($request->hasSession()) {
70 | $this->telemetryClient->getContext()->getSessionContext()->setId($request->getSession()->getId());
71 | }
72 |
73 | $this->telemetryClient->getContext()->getOperationContext()->setName($request->getMethod() . ' ' . $request->getPathInfo());
74 |
75 | $this->request = $this->telemetryClient->beginRequest(
76 | $request->getMethod() . ' ' . $request->getPathInfo(),
77 | $request->getUriForPath($request->getPathInfo()),
78 | $this->requestStartTime
79 | );
80 | }
81 |
82 | public function onKernelResponse(ResponseEvent $event) : void
83 | {
84 | if (!$this->isMainRequest($event)) {
85 | return;
86 | }
87 |
88 | if (!$this->telemetryClient->configuration()->requests()->isEnabled()) {
89 | return;
90 | }
91 |
92 | if (!$this->telemetryClient->getContext()->getInstrumentationKey()) {
93 | // instrumentation key is empty
94 | return;
95 | }
96 |
97 | $request = $event->getRequest();
98 | $response = $event->getResponse();
99 |
100 | $this->telemetryClient->endRequest(
101 | $this->request,
102 | (int) \round(\microtime(true) * 1000, 1) - $this->requestStartTimeMs,
103 | $response->getStatusCode(),
104 | $response->isSuccessful() || $response->isRedirection(),
105 | (new FlatArray([
106 | 'headers' => [
107 | 'accept-language' => $request->headers->get('accept-language'),
108 | 'accept-encoding' => $request->headers->get('accept-encoding'),
109 | 'accept' => $request->headers->get('accept'),
110 | 'user-agent' => $request->headers->get('user-agent'),
111 | 'host' => $request->headers->get('host'),
112 | ],
113 | 'query' => $request->query->all(),
114 | 'clientIps' => $request->getClientIps(),
115 | ]))()
116 | );
117 | }
118 |
119 | private function isMainRequest(KernelEvent $event) : bool
120 | {
121 | return \method_exists($event, 'isMainRequest')
122 | ? $event->isMainRequest()
123 | : $event->isMasterRequest();
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/Listener/KernelTerminateListener.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Listener;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use Symfony\Component\Console\ConsoleEvents;
18 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19 | use Symfony\Component\HttpKernel\KernelEvents;
20 |
21 | final class KernelTerminateListener implements EventSubscriberInterface
22 | {
23 | private $telemetryClient;
24 |
25 | public function __construct(Client $telemetryClient)
26 | {
27 | $this->telemetryClient = $telemetryClient;
28 | }
29 |
30 | public static function getSubscribedEvents()
31 | {
32 | $listeners = [
33 | KernelEvents::TERMINATE => ['onTerminate', -1000],
34 | ];
35 |
36 | if (\class_exists('Symfony\Component\Console\ConsoleEvents')) {
37 | $listeners[ConsoleEvents::TERMINATE] = 'onTerminate';
38 | }
39 |
40 | return $listeners;
41 | }
42 |
43 | public function onTerminate() : void
44 | {
45 | if (!$this->telemetryClient->getContext()->getInstrumentationKey()) {
46 | // instrumentation key is empty
47 | return;
48 | }
49 |
50 | if (!\count($this->telemetryClient->getChannel()->getQueue())) {
51 | // telemetry client queue is empty
52 | return;
53 | }
54 |
55 | $this->telemetryClient->flush();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AppInsightsPHPBundle
2 | =============
3 |
4 | The AppInsightsPHPBundle brings support for Microsoft Application Insights into Symfony 3.4+ applications.
5 | It's a profiler you can use on production to track everything that is important for you and your system.
6 |
7 | [](https://packagist.org/packages/app-insights-php/app-insights-php-bundle)
8 | [](https://packagist.org/packages/app-insights-php/app-insights-php-bundle)
9 | [](https://packagist.org/packages/app-insights-php/app-insights-php-bundle)
10 | [](https://packagist.org/packages/app-insights-php/app-insights-php-bundle)
11 |
12 |
13 | Microsoft App Insights allows you to track on production following metrics
14 |
15 | * Traces (Logs with different verbosity level)
16 | * Requests (http requests served by your app)
17 | * Custom Events (web/cli/javascript)
18 | * Dependencies (SQL, Elasticsearch, Redis - any 3rd party service/system/api)
19 | * Exceptions (web/cli/javascript)
20 | * PageViews (javascript)
21 |
22 | Query logs, visualize metrics and pin them to Azure Portal Dashboard, create alerts from metrics & health checks
23 |
24 | All you need to do is register free [Microsoft Azure Account](https://azure.microsoft.com/en-us/free/free-account-faq/),
25 | setup new [App Insights Instance](https://docs.microsoft.com/en-us/azure/azure-monitor/app/create-new-resource) and install
26 | this bundle in you symfony app.
27 |
28 | This bundle integrates app insights with all important libraries used by most of Symfony based applications.
29 |
30 | * Monolog Handler (Trace)
31 | * Doctrine Logger (Dependency)
32 | * Symfony HTTP (Request)
33 | * Symfony Exception (Exceptions)
34 |
35 | Microsoft App Insights is perfect for small teams that can't afford expensive monitoring tools or don't
36 | have enough resources to install, configure and maintain powerful open source alternatives.
37 |
38 | If you are looking for a SAAS alternative to:
39 |
40 | * Graylog / Kibana
41 | * Zabbix
42 | * Grafana
43 | * New Relic / Datadog / etc
44 | * Google Analytics
45 |
46 | With 90 days data retention period for ~2.5EUR per GB [Pricing](https://azure.microsoft.com/en-us/pricing/details/monitor/)
47 | First 5GB are free for 31 days..
48 | Microsoft App Insights is exactly what you need.
49 |
50 | This bundle simplifies App Insights integration with your new or existing project.
51 |
52 | 
53 |
54 | Documentation
55 | -------------
56 |
57 | The source of the documentation is stored in the `Resources/doc/` folder
58 | in this bundle, and available on symfony.com:
59 |
60 | [Read the Documentation for master](Resources/doc/index.md)
61 |
62 | Installation
63 | ------------
64 |
65 | All the installation instructions are located in the documentation.
66 |
67 | License
68 | -------
69 |
70 | This bundle is under the MIT license. See the complete license [in the bundle](LICENSE)
71 |
--------------------------------------------------------------------------------
/Resources/config/app_insights_php.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | use AppInsightsPHP\Client\Client;
15 | use AppInsightsPHP\Client\ClientFactory;
16 | use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
17 | use Symfony\Component\DependencyInjection\Reference;
18 |
19 | return static function (ContainerConfigurator $containerConfigurator) : void {
20 | $services = $containerConfigurator->services();
21 |
22 | $services->set('app_insights_php.telemetry.factory', ClientFactory::class)
23 | ->args(['%app_insights_php.instrumentation_key%', '', '', '']);
24 |
25 | $services->set('app_insights_php.telemetry', Client::class)
26 | ->public()
27 | ->factory([new Reference('app_insights_php.telemetry.factory'), 'create']);
28 | };
29 |
--------------------------------------------------------------------------------
/Resources/config/app_insights_php_console.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command\TrackDependencyCommand;
15 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command\TrackEventCommand;
16 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command\TrackExceptionCommand;
17 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command\TrackMetricCommand;
18 | use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
19 | use Symfony\Component\DependencyInjection\Reference;
20 |
21 | return static function (ContainerConfigurator $containerConfigurator) : void {
22 | $services = $containerConfigurator->services();
23 |
24 | $services->set('app_insights_php.symfony.command.track_dependency', TrackDependencyCommand::class)
25 | ->tag('console.command', [])
26 | ->args([new Reference('app_insights_php.telemetry')]);
27 |
28 | $services->set('app_insights_php.symfony.command.track_metric', TrackMetricCommand::class)
29 | ->tag('console.command', [])
30 | ->args([new Reference('app_insights_php.telemetry')]);
31 |
32 | $services->set('app_insights_php.symfony.command.track_event', TrackEventCommand::class)
33 | ->tag('console.command', [])
34 | ->args([new Reference('app_insights_php.telemetry')]);
35 |
36 | $services->set('app_insights_php.symfony.command.track_exception', TrackExceptionCommand::class)
37 | ->tag('console.command', [])
38 | ->args([new Reference('app_insights_php.telemetry')]);
39 | };
40 |
--------------------------------------------------------------------------------
/Resources/config/app_insights_php_doctrine.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | use AppInsightsPHP\Doctrine\DBAL\Logging\DependencyLogger;
15 | use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
16 | use Symfony\Component\DependencyInjection\Reference;
17 |
18 | return static function (ContainerConfigurator $containerConfigurator) : void {
19 | $services = $containerConfigurator->services();
20 |
21 | $services->set('app_insights_php.doctrine.logger.dependency', DependencyLogger::class)
22 | ->args([new Reference('app_insights_php.telemetry')]);
23 | };
24 |
--------------------------------------------------------------------------------
/Resources/config/app_insights_php_monolog.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | use AppInsightsPHP\Monolog\Handler\AppInsightsTraceHandler;
15 | use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
16 | use Symfony\Component\DependencyInjection\Reference;
17 |
18 | return static function (ContainerConfigurator $containerConfigurator) : void {
19 | $services = $containerConfigurator->services();
20 |
21 | $services->set('app_insights_php.monolog.handler.app_insights.trace', AppInsightsTraceHandler::class)
22 | ->args([new Reference('app_insights_php.telemetry')]);
23 | };
24 |
--------------------------------------------------------------------------------
/Resources/config/app_insights_php_symfony.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Listener\ExceptionListener;
15 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Listener\HttpRequestListener;
16 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Listener\KernelTerminateListener;
17 | use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
18 | use Symfony\Component\DependencyInjection\Reference;
19 |
20 | return static function (ContainerConfigurator $containerConfigurator) : void {
21 | $services = $containerConfigurator->services();
22 |
23 | $services->set('app_insights_php.symfony.listener.http_request', HttpRequestListener::class)
24 | ->tag('kernel.event_subscriber', [])
25 | ->args([new Reference('app_insights_php.telemetry')]);
26 |
27 | $services->set('app_insights_php.symfony.listener.kernel_terminate', KernelTerminateListener::class)
28 | ->tag('kernel.event_subscriber', [])
29 | ->args([new Reference('app_insights_php.telemetry')]);
30 |
31 | $services->set('app_insights_php.symfony.listener.exception', ExceptionListener::class)
32 | ->tag('kernel.event_subscriber', [])
33 | ->args([new Reference('app_insights_php.telemetry'), []]);
34 | };
35 |
--------------------------------------------------------------------------------
/Resources/config/app_insights_php_twig.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Twig\TelemetryExtension;
15 | use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
16 | use Symfony\Component\DependencyInjection\Reference;
17 |
18 | return static function (ContainerConfigurator $containerConfigurator) : void {
19 | $services = $containerConfigurator->services();
20 |
21 | $services->set('app_insights_php.twig.telemetry', TelemetryExtension::class)
22 | ->tag('twig.extension', [])
23 | ->args([new Reference('app_insights_php.telemetry')]);
24 | };
25 |
--------------------------------------------------------------------------------
/Resources/doc/dependencies.md:
--------------------------------------------------------------------------------
1 | # Dependencies
2 |
3 | Tracking dependencies might be really useful, App Insights will build Application Map from your
4 | dependencies and will track performance degradation for your automatically.
5 |
6 | 
7 |
8 | ## Disable dependencies tracking
9 | Disabling app insights in long running CLI commands could help you to save extra money and reduce some noise
10 | in your logs. For example if you are reindexing your whole database in elasticsearch tracking each
11 | call to dependency (elasticsearch) is probably useless, it wont give you any valuable data and might slow
12 | down the process and generate extra costs.
13 |
14 | In this case you can disable whole App Insights client or just specific metric type
15 |
16 | ```php
17 | configuration()->disable();
21 | ```
22 |
23 | Above code will prevent App Insights PHP Client from tracking any metrics but if for example
24 | you want to disable dependency tracking (indexing documents in elasticsearch) but still need
25 | to track exceptions or critical logs you might want to use following code:
26 |
27 | ```php
28 | configuration()->dependencies()->disable();
32 | ```
33 |
34 | Still not satisfied? If for any reason you would like to disable only specific dependency you
35 | can also tell Telemetryt Client to ignore them by name.
36 |
37 | Below example shows how you can ignore Doctrine DBAL SQL dependencies only:
38 |
39 | ```php
40 | configuration()
44 | ->dependencies()
45 | ->ignore(\AppInsightsPHP\Doctrine\DBAL\Logging\DependencyLogger::DEFAULT_NAME);
46 | ```
47 |
48 |
--------------------------------------------------------------------------------
/Resources/doc/how_it_works.md:
--------------------------------------------------------------------------------
1 | # How it works
2 |
3 | All components from [App Insights PHP](https://github.com/app-insights-php) are build on top of
4 | official [Microsoft App Insights SDK](https://github.com/Microsoft/ApplicationInsights-PHP) for PHP. Official SDK talks to App Insights API through HTTP protocol.
5 |
6 | What about performance? This bundle should not affect your system performance at all however
7 | there are some best practices we recommend you to follow (more later).
8 |
9 | Basically whole idea behind official SDK is to collect all metrics/logs in memory and flush them
10 | when needed.
11 |
12 | ```php
13 | trackEvent('My Custom Event!');
18 |
19 | $redisStartTime = time();
20 |
21 | $appInsights->doSomething();
22 |
23 | $appInsights->trackDependency('Redis', 'Cache', 'do something()', $redisStartTime);
24 | ```
25 |
26 | In above example AppInsights client will track custom event and redis call (dependency) however
27 | it will not fire any HTTP call, it needs to be done explicitly by calling `flush()` method.
28 |
29 | ```php
30 | flush();
33 |
34 | ```
35 |
36 | `AppInsightsPHPBundle` makes use of Symfony [kernel.terminate](https://symfony.com/doc/current/reference/events.html#kernel-terminate) event
37 | to flush SDK telemetry queue.
38 |
39 |
40 | Read more about tracking:
41 |
42 | * [Dependencies](dependencies.md)
43 | * [Traces](traces.md)
44 | * [PageViews](page_views.md)
--------------------------------------------------------------------------------
/Resources/doc/index.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | Supported symfony versions:
4 |
5 | * `>= 3.4`
6 | * `>= 4.0`
7 |
8 | ## Applications that don't use Symfony Flex
9 |
10 | ### Step 1: Download the Bundle
11 |
12 | Open a command console, enter your project directory and execute the
13 | following command to download the latest stable version of this bundle:
14 |
15 | ```console
16 | $ composer require app-insights-php/app-insights-php-bundle
17 | ```
18 |
19 | This command requires you to have Composer installed globally, as explained
20 | in the [installation chapter](https://getcomposer.org/doc/00-intro.md)
21 | of the Composer documentation.
22 |
23 | ## Applications that use Symfony Flex
24 |
25 | (**Not available yet**)
26 |
27 | Open a command console, enter your project directory and execute:
28 |
29 | ```console
30 | $ composer require app-insights-php
31 | ```
32 |
33 | ### Step 2: Enable the Bundle
34 |
35 | Then, enable the bundle by adding it to the list of registered bundles
36 | in the `app/AppKernel.php` file of your project:
37 |
38 | ```php
39 |
11 |
12 |
13 | ...
14 | {{ app_insights_php() }}
15 |
16 |
17 | ...
18 |
19 |
20 | ```
21 |
22 | If you want to identify your metrics by logged users you can also pass username/userid
23 | optional id to this function
24 |
25 | ```html
26 | {% if app.user %}
27 | {{ app_insights_php(app.user.username) }}
28 | {% else %}
29 | {{ app_insights_php() }}
30 | {% endif %}
31 | ```
--------------------------------------------------------------------------------
/Resources/doc/traces.md:
--------------------------------------------------------------------------------
1 | # Traces
2 |
3 | Traces in App Insights are nothing else than good known to everyone in PHP community Logs (Monolog).
4 |
5 | You can use one of following trace level:
6 |
7 | ```
8 | abstract class Severity_Level
9 | {
10 | const Verbose = 0;
11 | const Information = 1;
12 | const Warning = 2;
13 | const Error = 3;
14 | const Critical = 4;
15 | }
16 | ```
17 |
18 | [Our monolog hanlder](https://github.com/app-insights-php/monolog-handler) brings for you out of the
19 | box integration with app insights. This means that if your system is using monolog stream logger you
20 | can easily replace it with App Insights PHP trace logger to start sending your logs into the cloud.
21 |
22 | ## Optimize Memory Usage
23 |
24 | This is especially problematic when you log things in lon running CLI command. In order to
25 | avoid memory leaks you should be using [Buffer Handler](https://github.com/Seldaek/monolog/blob/master/src/Monolog/Handler/BufferHandler.php)
26 | in from of App Insights PHP trace handler.
27 |
28 | ## Configuration
29 |
30 | ```yaml
31 | app_insights_php:
32 | monolog:
33 | handlers:
34 | trace: # app_insights_php.monolog.handler.trace
35 | type: trace # trace | dependency
36 | level: ERROR
37 | bubble: true
38 | dependency: # app_insights_php.monolog.handler.dependency
39 | type: dependency # trace | dependency
40 | ```
41 |
42 | Above configuration will register in service container trace handler with `app_insights_php.monolog.handler.trace` id.
43 | You can use it later directly in your monolog bundle configuration:
44 |
45 | ```yaml
46 | monolog:
47 | handlers:
48 | logger_buffer:
49 | type: buffer
50 | buffer_size: 100
51 | handler: app_insights
52 | level: error
53 | app_insights:
54 | type: service
55 | id: "app_insights_php.monolog.handler.trace"
56 | ```
57 |
58 | ### Types
59 |
60 | `trace`
61 |
62 | Regular handler with few log levels, should be used in most cases.
63 |
64 | `dependency`
65 |
66 | Special handler useful when you are logging requests/responses from external
67 | services/systems/apis.
68 | Instead of using `trackTrace` this handler will use `trackDependency` method
69 | on App Insights PHP Client.
70 |
71 | **Known limitations**
72 |
73 | There is no good and easy way to track dependency start and duration time :|
74 | Those fields are going to be null.
75 |
--------------------------------------------------------------------------------
/Tests/Command/TrackDependencyCommandTest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Tests\Command;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use AppInsightsPHP\Client\Configuration;
18 | use AppInsightsPHP\Client\FailureCache;
19 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command\TrackDependencyCommand;
20 | use ApplicationInsights\Channel\Telemetry_Channel;
21 | use ApplicationInsights\Telemetry_Client;
22 | use GuzzleHttp\Psr7\Response;
23 | use PHPUnit\Framework\TestCase;
24 | use Psr\Log\NullLogger;
25 | use Psr\SimpleCache\CacheInterface;
26 | use Symfony\Component\Console\Application;
27 | use Symfony\Component\Console\Tester\CommandTester;
28 |
29 | final class TrackDependencyCommandTest extends TestCase
30 | {
31 | public function test_tracking_dependency() : void
32 | {
33 | $telemetryClientMock = $this->createMock(Telemetry_Client::class);
34 | $telemetryClientMock->method('getChannel')->willReturn($telemetryChannelMock = $this->createMock(Telemetry_Channel::class));
35 |
36 | $client = new Client(
37 | $telemetryClientMock,
38 | Configuration::createDefault(),
39 | new FailureCache($this->createMock(CacheInterface::class)),
40 | new NullLogger()
41 | );
42 |
43 | $application = new Application();
44 | $application->add(new TrackDependencyCommand($client));
45 |
46 | $tester = new CommandTester($application->get(TrackDependencyCommand::NAME));
47 |
48 | $telemetryClientMock->expects($this->once())
49 | ->method('trackDependency')
50 | ->with('Dependency Name', 'SQL', 'veryComplexQuery', $this->greaterThan(0), 10, true, null, null);
51 |
52 | $telemetryClientMock->expects($this->once())
53 | ->method('flush')
54 | ->willReturn(new Response());
55 |
56 | $result = $tester->execute([
57 | 'name' => 'Dependency Name',
58 | '--type' => 'SQL',
59 | '--commandName' => 'veryComplexQuery',
60 | '--durationTime' => 10,
61 | ]);
62 |
63 | $this->assertEquals($result, 0);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Tests/Command/TrackEventCommandTest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Tests\Command;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use AppInsightsPHP\Client\Configuration;
18 | use AppInsightsPHP\Client\FailureCache;
19 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command\TrackEventCommand;
20 | use ApplicationInsights\Channel\Telemetry_Channel;
21 | use ApplicationInsights\Telemetry_Client;
22 | use GuzzleHttp\Psr7\Response;
23 | use PHPUnit\Framework\TestCase;
24 | use Psr\Log\NullLogger;
25 | use Psr\SimpleCache\CacheInterface;
26 | use Symfony\Component\Console\Application;
27 | use Symfony\Component\Console\Tester\CommandTester;
28 |
29 | final class TrackEventCommandTest extends TestCase
30 | {
31 | public function test_tracking_event() : void
32 | {
33 | $telemetryClientMock = $this->createMock(Telemetry_Client::class);
34 | $telemetryClientMock->method('getChannel')->willReturn($telemetryChannelMock = $this->createMock(Telemetry_Channel::class));
35 |
36 | $client = new Client(
37 | $telemetryClientMock,
38 | Configuration::createDefault(),
39 | new FailureCache($this->createMock(CacheInterface::class)),
40 | new NullLogger()
41 | );
42 |
43 | $application = new Application();
44 | $application->add(new TrackEventCommand($client));
45 |
46 | $tester = new CommandTester($application->get(TrackEventCommand::NAME));
47 |
48 | $telemetryClientMock->expects($this->once())
49 | ->method('trackEvent')
50 | ->with('Event Name', ['property' => 1], ['measurement' => 2]);
51 |
52 | $telemetryClientMock->expects($this->once())
53 | ->method('flush')
54 | ->willReturn(new Response());
55 |
56 | $result = $tester->execute([
57 | 'name' => 'Event Name',
58 | '--properties' => '{"property":1}',
59 | '--measurements' => '{"measurement":2}',
60 | ]);
61 |
62 | $this->assertEquals($result, 0);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Tests/Command/TrackExceptionCommandTest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Tests\Command;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use AppInsightsPHP\Client\Configuration;
18 | use AppInsightsPHP\Client\FailureCache;
19 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command\TrackExceptionCommand;
20 | use ApplicationInsights\Channel\Telemetry_Channel;
21 | use ApplicationInsights\Telemetry_Client;
22 | use GuzzleHttp\Psr7\Response;
23 | use PHPUnit\Framework\TestCase;
24 | use Psr\Log\NullLogger;
25 | use Psr\SimpleCache\CacheInterface;
26 | use Symfony\Component\Console\Application;
27 | use Symfony\Component\Console\Tester\CommandTester;
28 |
29 | final class TrackExceptionCommandTest extends TestCase
30 | {
31 | public function test_tracking_metric() : void
32 | {
33 | $telemetryClientMock = $this->createMock(Telemetry_Client::class);
34 | $telemetryClientMock->method('getChannel')->willReturn($telemetryChannelMock = $this->createMock(Telemetry_Channel::class));
35 |
36 | $client = new Client(
37 | $telemetryClientMock,
38 | Configuration::createDefault(),
39 | new FailureCache($this->createMock(CacheInterface::class)),
40 | new NullLogger()
41 | );
42 |
43 | $application = new Application();
44 | $application->add(new TrackexceptionCommand($client));
45 |
46 | $tester = new CommandTester($application->get(TrackexceptionCommand::NAME));
47 |
48 | $telemetryClientMock->expects($this->once())
49 | ->method('trackException')
50 | ->with(new \Exception(''));
51 |
52 | $telemetryClientMock->expects($this->once())
53 | ->method('flush')
54 | ->willReturn(new Response());
55 |
56 | $result = $tester->execute([]);
57 |
58 | $this->assertEquals($result, 0);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Tests/Command/TrackMetricCommandTest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Tests\Command;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use AppInsightsPHP\Client\Configuration;
18 | use AppInsightsPHP\Client\FailureCache;
19 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Command\TrackMetricCommand;
20 | use ApplicationInsights\Channel\Telemetry_Channel;
21 | use ApplicationInsights\Telemetry_Client;
22 | use GuzzleHttp\Psr7\Response;
23 | use PHPUnit\Framework\TestCase;
24 | use Psr\Log\NullLogger;
25 | use Psr\SimpleCache\CacheInterface;
26 | use Symfony\Component\Console\Application;
27 | use Symfony\Component\Console\Tester\CommandTester;
28 |
29 | final class TrackMetricCommandTest extends TestCase
30 | {
31 | public function test_tracking_metric() : void
32 | {
33 | $telemetryClientMock = $this->createMock(Telemetry_Client::class);
34 | $telemetryClientMock->method('getChannel')->willReturn($telemetryChannelMock = $this->createMock(Telemetry_Channel::class));
35 |
36 | $client = new Client(
37 | $telemetryClientMock,
38 | Configuration::createDefault(),
39 | new FailureCache($this->createMock(CacheInterface::class)),
40 | new NullLogger()
41 | );
42 |
43 | $application = new Application();
44 | $application->add(new TrackMetricCommand($client));
45 |
46 | $tester = new CommandTester($application->get(TrackMetricCommand::NAME));
47 |
48 | $telemetryClientMock->expects($this->once())
49 | ->method('trackMetric')
50 | ->with('Metric Name', '123', 0);
51 |
52 | $telemetryClientMock->expects($this->once())
53 | ->method('flush')
54 | ->willReturn(new Response());
55 |
56 | $result = $tester->execute([
57 | 'name' => 'Metric Name',
58 | 'value' => '123',
59 | '--type' => 0,
60 | ]);
61 |
62 | $this->assertEquals($result, 0);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Tests/DependencyInjection/AppInsightsPHPExtensionTest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Tests\DependencyInjection;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use AppInsightsPHP\Doctrine\DBAL\Logging\DependencyLogger;
18 | use AppInsightsPHP\Monolog\Handler\AppInsightsTraceHandler;
19 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\DependencyInjection\AppInsightsPHPExtension;
20 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Twig\TelemetryExtension;
21 | use Monolog\Logger;
22 | use PHPUnit\Framework\TestCase;
23 | use Symfony\Component\DependencyInjection\ContainerBuilder;
24 | use Symfony\Component\HttpKernel\KernelInterface;
25 |
26 | final class AppInsightsPHPExtensionTest extends TestCase
27 | {
28 | private $kernel;
29 |
30 | /**
31 | * @var \Symfony\Component\DependencyInjection\ContainerBuilder
32 | */
33 | private $container;
34 |
35 | protected function setUp() : void
36 | {
37 | parent::setUp();
38 |
39 | $this->kernel = $this->getMockBuilder(KernelInterface::class)->getMock();
40 | $this->container = new ContainerBuilder();
41 | }
42 |
43 | protected function tearDown() : void
44 | {
45 | parent::tearDown();
46 |
47 | $this->container = null;
48 | $this->kernel = null;
49 | }
50 |
51 | public function test_default_configuration() : void
52 | {
53 | $extension = new AppInsightsPHPExtension();
54 | $extension->load(
55 | [[
56 | 'instrumentation_key' => 'test_key',
57 | ]],
58 | $this->container
59 | );
60 |
61 | $this->assertTrue($this->container->hasDefinition('app_insights_php.telemetry'));
62 | $this->assertTrue($this->container->hasParameter('app_insights_php.instrumentation_key'));
63 |
64 | $this->assertFalse($this->container->hasDefinition('app_insights_php.doctrine.logger.app_insights'));
65 |
66 | $this->assertTrue($this->container->get('app_insights_php.configuration')->isEnabled());
67 | $this->assertFalse($this->container->get('app_insights_php.configuration')->gzipEnabled());
68 | $this->assertTrue($this->container->get('app_insights_php.configuration.exceptions')->isEnabled());
69 | $this->assertTrue($this->container->get('app_insights_php.configuration.traces')->isEnabled());
70 | $this->assertTrue($this->container->get('app_insights_php.configuration.dependencies')->isEnabled());
71 | $this->assertTrue($this->container->get('app_insights_php.configuration.requests')->isEnabled());
72 |
73 | $this->assertTrue($this->container->hasDefinition('app_insights_php.symfony.listener.http_request'));
74 | $this->assertTrue($this->container->hasDefinition('app_insights_php.symfony.listener.kernel_terminate'));
75 | $this->assertTrue($this->container->hasDefinition('app_insights_php.symfony.listener.exception'));
76 |
77 | $this->assertInstanceOf(Client::class, $this->container->get('app_insights_php.telemetry'));
78 | }
79 |
80 | public function test_configuration_when_enabled_is_set_to_false() : void
81 | {
82 | $extension = new AppInsightsPHPExtension();
83 | $extension->load(
84 | [[
85 | 'enabled' => false,
86 | 'instrumentation_key' => 'test_key',
87 | ]],
88 | $this->container
89 | );
90 |
91 | $this->assertTrue($this->container->hasDefinition('app_insights_php.telemetry'));
92 | $this->assertTrue($this->container->hasParameter('app_insights_php.instrumentation_key'));
93 |
94 | $this->assertFalse($this->container->hasDefinition('app_insights_php.doctrine.logger.app_insights'));
95 |
96 | $this->assertFalse($this->container->get('app_insights_php.configuration')->isEnabled());
97 | $this->assertTrue($this->container->get('app_insights_php.configuration.exceptions')->isEnabled());
98 | $this->assertTrue($this->container->get('app_insights_php.configuration.traces')->isEnabled());
99 | $this->assertTrue($this->container->get('app_insights_php.configuration.dependencies')->isEnabled());
100 | $this->assertTrue($this->container->get('app_insights_php.configuration.requests')->isEnabled());
101 |
102 | $this->assertFalse($this->container->hasDefinition('app_insights_php.symfony.listener.http_request'));
103 | $this->assertFalse($this->container->hasDefinition('app_insights_php.symfony.listener.kernel_terminate'));
104 | $this->assertFalse($this->container->hasDefinition('app_insights_php.symfony.listener.exception'));
105 |
106 | $this->assertInstanceOf(Client::class, $this->container->get('app_insights_php.telemetry'));
107 | }
108 |
109 | public function test_fallback_logger_configuration() : void
110 | {
111 | $extension = new AppInsightsPHPExtension();
112 | $extension->load(
113 | [[
114 | 'instrumentation_key' => 'test_key',
115 | 'fallback_logger' => [
116 | 'service_id' => 'logger',
117 | ],
118 | ]],
119 | $this->container
120 | );
121 |
122 | $this->assertSame(
123 | 'logger',
124 | (string) $this->container->getDefinition('app_insights_php.telemetry.factory')->getArgument(3)
125 | );
126 | }
127 |
128 | public function test_fallback_logger_with_monolog_channel_configuration() : void
129 | {
130 | $extension = new AppInsightsPHPExtension();
131 | $extension->load(
132 | [[
133 | 'instrumentation_key' => 'test_key',
134 | 'fallback_logger' => [
135 | 'service_id' => 'logger',
136 | 'monolog_channel' => 'main',
137 | ],
138 | ]],
139 | $this->container
140 | );
141 |
142 | $this->assertSame(
143 | 'logger',
144 | (string) $this->container->getDefinition('app_insights_php.telemetry.factory')->getArgument(3)
145 | );
146 | $this->assertSame(
147 | 'main',
148 | $this->container->getDefinition('app_insights_php.telemetry.factory')->getTag('monolog.logger')[0]['channel']
149 | );
150 | }
151 |
152 | public function test_failure_cache_configuration() : void
153 | {
154 | $extension = new AppInsightsPHPExtension();
155 | $extension->load(
156 | [[
157 | 'instrumentation_key' => 'test_key',
158 | 'failure_cache_service_id' => 'failure_cache_id',
159 | ]],
160 | $this->container
161 | );
162 |
163 | $this->assertSame(
164 | 'failure_cache_id',
165 | (string) $this->container->getDefinition('app_insights_php.telemetry.factory')->getArgument(2)
166 | );
167 | }
168 |
169 | public function test_doctrine_logger_configuration() : void
170 | {
171 | $extension = new AppInsightsPHPExtension();
172 | $extension->load(
173 | [[
174 | 'instrumentation_key' => 'test_key',
175 | 'doctrine' => [
176 | 'track_dependency' => true,
177 | ],
178 | ]],
179 | $this->container
180 | );
181 |
182 | $this->assertTrue($this->container->hasDefinition('app_insights_php.doctrine.logger.dependency'));
183 | $this->assertInstanceOf(DependencyLogger::class, $this->container->get('app_insights_php.doctrine.logger.dependency'));
184 | }
185 |
186 | public function test_twig_configuration() : void
187 | {
188 | $extension = new AppInsightsPHPExtension();
189 | $extension->load(
190 | [[
191 | 'instrumentation_key' => 'test_key',
192 | ]],
193 | $this->container
194 | );
195 |
196 | $this->assertInstanceOf(TelemetryExtension::class, $this->container->get('app_insights_php.twig.telemetry'));
197 | }
198 |
199 | public function test_ignored_exceptions_configuration() : void
200 | {
201 | $extension = new AppInsightsPHPExtension();
202 | $extension->load(
203 | [[
204 | 'instrumentation_key' => 'test_key',
205 | 'exceptions' => [
206 | 'ignored_exceptions' => [\RuntimeException::class],
207 | ],
208 | ]],
209 | $this->container
210 | );
211 |
212 | $this->assertTrue($this->container->get('app_insights_php.configuration')->exceptions()->isIgnored(\RuntimeException::class));
213 | $this->assertFalse($this->container->get('app_insights_php.configuration')->exceptions()->isIgnored(\Exception::class));
214 | }
215 |
216 | public function test_monolog_configuration() : void
217 | {
218 | $extension = new AppInsightsPHPExtension();
219 | $extension->load(
220 | [[
221 | 'instrumentation_key' => 'test_key',
222 | 'monolog' => [
223 | 'handlers' => [
224 | [
225 | 'name' => 'foo.logger',
226 | 'level' => Logger::DEBUG,
227 | ],
228 | ],
229 | ],
230 | ]],
231 | $this->container
232 | );
233 |
234 | $this->assertInstanceOf(AppInsightsTraceHandler::class, $this->container->get('app_insights_php.monolog.handler.foo.logger'));
235 | }
236 |
237 | public function test_gzip_configuration() : void
238 | {
239 | $extension = new AppInsightsPHPExtension();
240 | $extension->load(
241 | [[
242 | 'instrumentation_key' => 'test_key',
243 | 'gzip_enabled' => true,
244 | ]],
245 | $this->container
246 | );
247 |
248 | $this->assertTrue($this->container->get('app_insights_php.configuration')->gzipEnabled());
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/Tests/DependencyInjection/ConfigurationTest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Tests\DependencyInjection;
15 |
16 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\DependencyInjection\Configuration;
17 | use Monolog\Logger;
18 | use PHPUnit\Framework\TestCase;
19 | use Symfony\Component\Config\Definition\Processor;
20 |
21 | final class ConfigurationTest extends Testcase
22 | {
23 | public function test_default_configuration() : void
24 | {
25 | $configs = [
26 | [
27 | 'instrumentation_key' => 'test_key',
28 | ],
29 | ];
30 |
31 | $config = $this->process($configs);
32 |
33 | $this->assertEquals('test_key', $config['instrumentation_key']);
34 | $this->assertNull($config['failure_cache_service_id']);
35 | $this->assertTrue($config['enabled']);
36 | $this->assertFalse($config['gzip_enabled']);
37 | $this->assertEquals([], $config['exceptions']['ignored_exceptions']);
38 | $this->assertFalse($config['doctrine']['track_dependency']);
39 | $this->assertEmpty($config['monolog']['handlers']);
40 | }
41 |
42 | public function test_monolog_configuration() : void
43 | {
44 | $configs = [
45 | [
46 | 'instrumentation_key' => 'test_key',
47 | 'monolog' => [
48 | 'handlers' => [
49 | [
50 | 'type' => 'trace',
51 | 'name' => 'foo.logger',
52 | 'level' => Logger::DEBUG,
53 | ],
54 | [
55 | 'name' => 'bar.logger',
56 | 'type' => 'dependency',
57 | ],
58 | ],
59 | ],
60 | ],
61 | ];
62 |
63 | $config = $this->process($configs);
64 |
65 | $this->assertArrayHasKey('foo.logger', $config['monolog']['handlers']);
66 | $this->assertEquals(Logger::DEBUG, $config['monolog']['handlers']['foo.logger']['level']);
67 | $this->assertTrue($config['monolog']['handlers']['foo.logger']['bubble']);
68 | $this->assertEquals('trace', $config['monolog']['handlers']['foo.logger']['type']);
69 | $this->assertEquals('dependency', $config['monolog']['handlers']['bar.logger']['type']);
70 | }
71 |
72 | public function test_gzip_configuration() : void
73 | {
74 | $configs = [
75 | [
76 | 'instrumentation_key' => 'test_key',
77 | 'gzip_enabled' => true,
78 | ],
79 | ];
80 |
81 | $config = $this->process($configs);
82 |
83 | $this->assertTrue($config['gzip_enabled']);
84 | }
85 |
86 | public function test_failure_cache_configuration() : void
87 | {
88 | $configs = [
89 | [
90 | 'instrumentation_key' => 'test_key',
91 | 'failure_cache_service_id' => 'failure_cache_id',
92 | ],
93 | ];
94 |
95 | $config = $this->process($configs);
96 |
97 | $this->assertEquals('failure_cache_id', $config['failure_cache_service_id']);
98 | }
99 |
100 | protected function process($configs)
101 | {
102 | $processor = new Processor();
103 |
104 | return $processor->processConfiguration(new Configuration(), $configs);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/Tests/FlatArrayTest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Tests;
15 |
16 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\FlatArray;
17 | use PHPUnit\Framework\TestCase;
18 |
19 | final class FlatArrayTest extends TestCase
20 | {
21 | public static function arrays() : \Generator
22 | {
23 | yield [[], []];
24 | yield [
25 | [
26 | 'id' => 'user-id',
27 | 'dimensions.length.value' => 10,
28 | 'dimensions.length.uom' => 'inches',
29 | 'dimensions.width.value' => 20,
30 | 'dimensions.width.uom' => 'inches',
31 | 'dimensions.height.value' => 30,
32 | 'dimensions.height.uom' => 'inches',
33 | 'names' => 'John Snow',
34 | 'tags.0' => 'primary',
35 | 'tags.1' => 'default',
36 | 'tags.2' => 'principle',
37 | ],
38 | [
39 | 'id' => 'user-id',
40 | 'dimensions' => [
41 | 'length' => [
42 | 'value' => 10,
43 | 'uom' => 'inches',
44 | ],
45 | 'width' => [
46 | 'value' => 20,
47 | 'uom' => 'inches',
48 | ],
49 | 'height' => [
50 | 'value' => 30,
51 | 'uom' => 'inches',
52 | ],
53 | ],
54 | 'names' => ['John Snow'],
55 | 'tags' => ['primary', 'default', 'principle'],
56 | ],
57 | ];
58 | }
59 |
60 | /**
61 | * @dataProvider arrays
62 | */
63 | public function test_flat_array(array $flatArray, array $array) : void
64 | {
65 | $this->assertEquals(
66 | $flatArray,
67 | (new FlatArray($array))()
68 | );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Tests/Functional/AppKernel.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Tests\Functional;
15 |
16 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\AppInsightsPHPBundle;
17 | use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
18 | use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
19 | use Symfony\Bundle\MonologBundle\MonologBundle;
20 | use Symfony\Component\Config\Loader\LoaderInterface;
21 | use Symfony\Component\DependencyInjection\ContainerBuilder;
22 | use Symfony\Component\HttpKernel\Kernel as BaseKernel;
23 | use Symfony\Component\Routing\RouteCollectionBuilder;
24 |
25 | final class AppKernel extends BaseKernel
26 | {
27 | use MicroKernelTrait;
28 |
29 | public function registerBundles()
30 | {
31 | return [
32 | new FrameworkBundle(),
33 | new MonologBundle(),
34 | new AppInsightsPHPBundle(),
35 | ];
36 | }
37 |
38 | public function getCacheDir()
39 | {
40 | return \sys_get_temp_dir() . '/PHPAppInsights/cache';
41 | }
42 |
43 | public function getLogDir()
44 | {
45 | return \sys_get_temp_dir() . '/PHPAppInsights/logs';
46 | }
47 |
48 | protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader) : void
49 | {
50 | $configFilePath = __DIR__ . '/config/app_insights_php.php';
51 |
52 | if (!\file_exists($configFilePath)) {
53 | throw new \RuntimeException('Please create ' . $configFilePath . ' first, use ' . $configFilePath . '.dist as a template');
54 | }
55 |
56 | $c->loadFromExtension('framework', [
57 | 'secret' => 'S0ME_SECRET',
58 | ]);
59 | $c->loadFromExtension('app_insights_php', require_once $configFilePath);
60 | $c->loadFromExtension('monolog', [
61 | 'handlers' => [
62 | 'file_log' => [
63 | 'type' => 'stream',
64 | 'path' => '%kernel.logs_dir%/%kernel.environment%.log',
65 | 'level' => 'error',
66 | ],
67 | 'console' => [
68 | 'type' => 'console',
69 | 'process_psr_3_messages' => false,
70 | 'channels' => ['!event', '!doctrine', '!console'],
71 | ],
72 | ],
73 | ]);
74 | }
75 |
76 | protected function configureRoutes(RouteCollectionBuilder $routes) : void
77 | {
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Tests/Functional/README.md:
--------------------------------------------------------------------------------
1 | # Functional Testing
2 |
3 | This isn't really a place with automated functional tests, it's more a sandbox for AppInsightsPHPBundle that
4 | you can using during this bundle development.
5 |
6 | If you would like to manually test this bundle during development you might want to use [bin/console](bin/console)
7 | CLI Application.
8 |
9 | First prepare [config/app_insights_php.php](config/app_insights_php.php.dist) using `config/app_insights_php.php.dist` template.
10 | If you provide valid App Insights Instrumentation Key you should be able to start using App Insights PHP CLI commands.
11 |
12 |
--------------------------------------------------------------------------------
/Tests/Functional/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | run($input);
--------------------------------------------------------------------------------
/Tests/Functional/config/app_insights_php.php.dist:
--------------------------------------------------------------------------------
1 | 'change_me'
5 | ];
--------------------------------------------------------------------------------
/Tests/Listener/KernelTerminateListenerTest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Tests\Listener;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use AppInsightsPHP\Client\Configuration;
18 | use AppInsightsPHP\Client\FailureCache;
19 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Listener\KernelTerminateListener;
20 | use ApplicationInsights\Channel\Telemetry_Channel;
21 | use ApplicationInsights\Telemetry_Client;
22 | use ApplicationInsights\Telemetry_Context;
23 | use PHPUnit\Framework\TestCase;
24 | use Psr\Log\NullLogger;
25 | use Psr\SimpleCache\CacheInterface;
26 |
27 | final class KernelTerminateListenerTest extends TestCase
28 | {
29 | public function test_do_nothing_when_instrumentation_key_is_empty() : void
30 | {
31 | $telemetryClientMock = $this->createMock(Telemetry_Client::class);
32 | $telemetryClientMock->method('getChannel')->willReturn($telemetryChannelMock = $this->createMock(Telemetry_Channel::class));
33 | $telemetryClientMock->method('getContext')->willReturn($telemetryContextMock = $this->createMock(Telemetry_Context::class));
34 | $telemetryContextMock->method('getInstrumentationKey')->willReturn('');
35 | $telemetryChannelMock->method('getQueue')->willReturn([]);
36 |
37 | $client = new Client(
38 | $telemetryClientMock,
39 | Configuration::createDefault(),
40 | new FailureCache($this->createMock(CacheInterface::class)),
41 | new NullLogger()
42 | );
43 |
44 | $telemetryClientMock->expects($this->never())
45 | ->method('flush');
46 |
47 | $listener = new KernelTerminateListener($client);
48 |
49 | $listener->onTerminate();
50 | }
51 |
52 | public function test_do_nothing_when_telemetry_queue_is_empty() : void
53 | {
54 | $telemetryClientMock = $this->createMock(Telemetry_Client::class);
55 | $telemetryClientMock->method('getChannel')->willReturn($telemetryChannelMock = $this->createMock(Telemetry_Channel::class));
56 | $telemetryClientMock->method('getContext')->willReturn($telemetryContextMock = $this->createMock(Telemetry_Context::class));
57 | $telemetryContextMock->method('getInstrumentationKey')->willReturn('instrumentation_key');
58 | $telemetryChannelMock->method('getQueue')->willReturn([]);
59 |
60 | $client = new Client(
61 | $telemetryClientMock,
62 | Configuration::createDefault(),
63 | new FailureCache($this->createMock(CacheInterface::class)),
64 | new NullLogger()
65 | );
66 |
67 | $telemetryClientMock->expects($this->never())
68 | ->method('flush');
69 |
70 | $listener = new KernelTerminateListener($client);
71 |
72 | $listener->onTerminate();
73 | }
74 |
75 | public function test_successful_flush() : void
76 | {
77 | $telemetryClientMock = $this->createMock(Telemetry_Client::class);
78 | $telemetryClientMock->method('getChannel')->willReturn($telemetryChannelMock = $this->createMock(Telemetry_Channel::class));
79 | $telemetryClientMock->method('getContext')->willReturn($telemetryContextMock = $this->createMock(Telemetry_Context::class));
80 | $telemetryContextMock->method('getInstrumentationKey')->willReturn('instrumentation_key');
81 | $telemetryChannelMock->method('getQueue')->willReturn(['some_log_entry']);
82 |
83 | $client = new Client(
84 | $telemetryClientMock,
85 | Configuration::createDefault(),
86 | new FailureCache($this->createMock(CacheInterface::class)),
87 | new NullLogger()
88 | );
89 |
90 | $telemetryClientMock->expects($this->once())
91 | ->method('flush');
92 |
93 | $listener = new KernelTerminateListener($client);
94 |
95 | $listener->onTerminate();
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Tests/Twig/TelemetryExtensionTest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Tests\Twig;
15 |
16 | use AppInsightsPHP\Client\ClientFactory;
17 | use AppInsightsPHP\Client\Configuration;
18 | use AppInsightsPHP\Symfony\AppInsightsPHPBundle\Twig\TelemetryExtension;
19 | use PHPUnit\Framework\TestCase;
20 | use Psr\Log\NullLogger;
21 | use Psr\SimpleCache\CacheInterface;
22 |
23 | final class TelemetryExtensionTest extends TestCase
24 | {
25 | public function test_app_insights_php_function_without_user_id() : void
26 | {
27 | $client = (new ClientFactory('instrumentation_key', Configuration::createDefault(), $this->createMock(CacheInterface::class), new NullLogger()))->create();
28 | $client->getContext()->getOperationContext()->setId('operation_id');
29 | $twigExtension = new TelemetryExtension($client);
30 |
31 | $this->assertSame(
32 | <<<'TWIG'
33 |
46 | TWIG
47 | ,
48 | $twigExtension->appInsightsPHP()
49 | );
50 | }
51 |
52 | public function test_app_insights_php_function_with_user_id() : void
53 | {
54 | $client = (new ClientFactory('instrumentation_key', Configuration::createDefault(), $this->createMock(CacheInterface::class), new NullLogger()))->create();
55 | $client->getContext()->getOperationContext()->setId('operation_id');
56 | $twigExtension = new TelemetryExtension($client);
57 |
58 | $this->assertSame(
59 | <<<'TWIG'
60 |
74 | TWIG
75 | ,
76 | $twigExtension->appInsightsPHP('norbert@orzechowicz.pl')
77 | );
78 | }
79 |
80 | public function test_app_insights_php_function_with_disabled_tracking() : void
81 | {
82 | $config = Configuration::createDefault();
83 | $config->disable();
84 |
85 | $client = (new ClientFactory('instrumentation_key', $config, $this->createMock(CacheInterface::class), new NullLogger()))->create();
86 | $client->getContext()->getOperationContext()->setId('operation_id');
87 | $twigExtension = new TelemetryExtension($client);
88 |
89 | $this->assertSame(
90 | <<<'TWIG'
91 |
94 | TWIG
95 | ,
96 | $twigExtension->appInsightsPHP('norbert@orzechowicz.pl')
97 | );
98 | }
99 |
100 | public function test_app_insights_php_function_with_empty_instrumentation_key() : void
101 | {
102 | $config = Configuration::createDefault();
103 |
104 | $client = (new ClientFactory('', $config, $this->createMock(CacheInterface::class), new NullLogger()))->create();
105 | $client->getContext()->getOperationContext()->setId('operation_id');
106 | $twigExtension = new TelemetryExtension($client);
107 |
108 | $this->assertSame(
109 | <<<'TWIG'
110 |
113 | TWIG
114 | ,
115 | $twigExtension->appInsightsPHP('norbert@orzechowicz.pl')
116 | );
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/Twig/TelemetryExtension.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace AppInsightsPHP\Symfony\AppInsightsPHPBundle\Twig;
15 |
16 | use AppInsightsPHP\Client\Client;
17 | use Twig\Extension\AbstractExtension;
18 | use Twig\TwigFunction;
19 |
20 | final class TelemetryExtension extends AbstractExtension
21 | {
22 | private $client;
23 |
24 | public function __construct(Client $client)
25 | {
26 | $this->client = $client;
27 | }
28 |
29 | /**
30 | * {@inheritdoc}
31 | */
32 | public function getFunctions() : array
33 | {
34 | return [
35 | new TwigFunction('app_insights_php', [$this, 'appInsightsPHP'], ['is_safe' => ['html']]),
36 | ];
37 | }
38 |
39 | public function appInsightsPHP(?string $userId = null) : string
40 | {
41 | $script = "';
76 |
77 | return $script;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app-insights-php/app-insights-php-bundle",
3 | "description": "Microsoft App Insights Symfony bundle",
4 | "type": "symfony-bundle",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Norbert Orzechowicz",
9 | "email": "norbert@orzechowicz.pl"
10 | }
11 | ],
12 | "autoload": {
13 | "psr-4": {"AppInsightsPHP\\Symfony\\AppInsightsPHPBundle\\": ""},
14 | "exclude-from-classmap": [
15 | "/Tests/"
16 | ]
17 | },
18 | "suggest": {
19 | "app-insights-php/doctrine-dependency-logger": "Trace Doctrine DBAL queries as dependency metric type."
20 | },
21 | "require": {
22 | "php": "~8.1 || ~8.2",
23 | "app-insights-php/monolog-handler": "^0.3",
24 | "app-insights-php/client": "^0.3",
25 | "symfony/framework-bundle": "~3.4||~4.4||~5.4||~6",
26 | "guzzlehttp/guzzle": "^7.4",
27 | "twig/twig": "^1.2|^2|^3"
28 | },
29 | "require-dev": {
30 | "app-insights-php/doctrine-dependency-logger": "^0.3",
31 | "friendsofphp/php-cs-fixer": "^3.4",
32 | "symfony/monolog-bundle": "~2||~3",
33 | "phpunit/phpunit": "^10"
34 | },
35 | "scripts": {
36 | "phpunit": [
37 | "phpunit --colors=always"
38 | ],
39 | "static:analyze": [
40 | "php-cs-fixer fix --dry-run"
41 | ],
42 | "test" : [
43 | "@phpunit"
44 | ],
45 | "cs:php:fix": [
46 | "php-cs-fixer fix"
47 | ]
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ./Tests
20 |
21 |
22 |
--------------------------------------------------------------------------------
/shell.nix:
--------------------------------------------------------------------------------
1 | let
2 | pkgs = import (fetchTarball "https://github.com/nixos/nixpkgs/archive/d44916d12f1d39baa02325040b381311364ad93a.tar.gz" ) {};
3 | in
4 |
5 | let
6 | php = pkgs.php74.buildEnv {
7 | extensions = ({ enabled, all }: enabled++ [ all.pcov ]);
8 | extraConfig =
9 | ''
10 | short_open_tag = Off
11 | memory_limit = -1
12 | date.timezone = UTC
13 | '';
14 | };
15 | in
16 |
17 | pkgs.mkShell {
18 | name = "app-insights-php";
19 | nativeBuildInputs = with pkgs; [
20 | php
21 | php.packages.composer
22 | ];
23 | }
24 |
--------------------------------------------------------------------------------